diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 364f8d95c3b..42dfd42ee7b 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -29,7 +29,7 @@ jobs: node-version: ${{ matrix.node-version }} cache: 'npm' - name: Install packages - run: npm ci + run: npm install - name: Lint Lib run: npm run lint:lib env: diff --git a/angular.json b/angular.json index 5e10aa45051..47dd96298e4 100644 --- a/angular.json +++ b/angular.json @@ -103,23 +103,10 @@ } }, "test": { - "builder": "@angular/build:karma", + "builder": "@angular/build:unit-test", "options": { - "main": "src/test.ts", - "polyfills": [ - "zone.js", - "zone.js/testing" - ], "tsConfig": "src/tsconfig.spec.json", - "karmaConfig": "src/karma.conf.js", - "styles": [ - "src/styles/styles.scss" - ], - "scripts": [], - "assets": [ - "src/favicon.ico", - "src/assets" - ] + "browsers": ["chromium"] } }, "lint": { @@ -180,35 +167,24 @@ "production": { "project": "projects/igniteui-angular/ng-package.prod.json", "tsConfig": "projects/igniteui-angular/tsconfig.lib.prod.json" + }, + "development": { + "tsConfig": "projects/igniteui-angular/tsconfig.lib.json", + "project": "projects/igniteui-angular/ng-package.json" } - } + }, + "defaultConfiguration": "development" }, "test": { - "builder": "@angular/build:karma", + "builder": "@angular/build:unit-test", "options": { - "polyfills": [ - "zone.js", - "zone.js/testing", - "hammerjs" - ], - "styles": [ - "src/styles/styles.scss", - "projects/igniteui-angular/test.css" - ], - "assets": [ - "projects/igniteui-angular/test-utils/assets" - ], - "stylePreprocessorOptions": { - "includePaths": [ - "node_modules" - ] - }, "tsConfig": "projects/igniteui-angular/tsconfig.spec.json", - "karmaConfig": "projects/igniteui-angular/karma.conf.js", + "browsers": ["chromium"], "exclude": [ "migrations", "schematics" - ] + ], + "coverage": true } }, "lint": { @@ -362,26 +338,10 @@ } }, "test": { - "builder": "@angular/build:karma", + "builder": "@angular/build:unit-test", "options": { - "main": "projects/igniteui-angular-elements/src/test.ts", - "polyfills": [ - "projects/igniteui-angular-elements/src/polyfills.ts" - ], "tsConfig": "projects/igniteui-angular-elements/tsconfig.spec.json", - "karmaConfig": "projects/igniteui-angular-elements/karma.conf.js", - "inlineStyleLanguage": "scss", - "assets": [ - "projects/igniteui-angular-elements/src/favicon.ico", - "projects/igniteui-angular-elements/src/assets" - ], - "styles": [ - "projects/igniteui-angular-elements/src/styles.scss" - ], - "stylePreprocessorOptions": { - "includePaths": ["node_modules"] - }, - "scripts": [] + "browsers": ["chromium"] } } } diff --git a/missing-vitest-imports.json b/missing-vitest-imports.json new file mode 100644 index 00000000000..5df8c55e789 --- /dev/null +++ b/missing-vitest-imports.json @@ -0,0 +1,590 @@ +[ + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\avatar\\src\\avatar\\avatar.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\badge\\src\\badge\\badge.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\bottom-nav\\src\\bottom-nav\\bottom-nav.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\button-group\\src\\button-group\\button-group.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\calendar\\src\\calendar\\days-view\\days-view.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\calendar\\src\\calendar\\month-picker\\month-picker.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\calendar\\src\\calendar\\calendar.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\card\\src\\card\\card.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\chat\\src\\chat.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\chat-extras\\src\\markdown-service.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\checkbox\\src\\checkbox\\checkbox.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\chips\\src\\chips\\chip.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\chips\\src\\chips\\chips-area.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\core\\src\\core\\i18n\\formatters\\formatter-base.spec.ts", + "UsedFunctions": "describe, it, expect" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\core\\src\\core\\i18n\\formatters\\formatter-intl.spec.ts", + "UsedFunctions": "describe, it, expect" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\core\\src\\core\\i18n\\resources.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\core\\src\\core\\selection.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\core\\src\\core\\utils.spec.ts", + "UsedFunctions": "describe, it, expect" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\core\\src\\data-operations\\data-util.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\core\\src\\data-operations\\expressions-tree-util.spec.ts", + "UsedFunctions": "describe, it, expect" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\core\\src\\data-operations\\filtering-condition.spec.ts", + "UsedFunctions": "describe, it, expect" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\core\\src\\data-operations\\filtering-strategy.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\core\\src\\data-operations\\groupby-strategy.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\core\\src\\data-operations\\sorting-strategy.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\core\\src\\date-common\\util\\date-time.util.spec.ts", + "UsedFunctions": "describe, it, expect" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\core\\src\\date-common\\util\\helpers.spec.ts", + "UsedFunctions": "describe, it, expect" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\core\\src\\date-common\\util\\model.spec.ts", + "UsedFunctions": "describe, it, expect" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\core\\src\\services\\direction\\directionality.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\core\\src\\services\\transaction\\igx-transaction.spec.ts", + "UsedFunctions": "describe, it, expect" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\date-picker\\src\\date-picker\\calendar-container\\calendar-container.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\date-picker\\src\\date-picker\\date-picker.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\date-picker\\src\\date-range-picker\\predefined-ranges\\predefined-ranges-area-component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\date-picker\\src\\date-range-picker\\date-range-picker.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\dialog\\src\\dialog\\dialog.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\directives\\src\\directives\\button\\button.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\directives\\src\\directives\\button\\icon-button.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\directives\\src\\directives\\divider\\divider.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\directives\\src\\directives\\drag-drop\\drag-drop.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\directives\\src\\directives\\filter\\filter.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\directives\\src\\directives\\focus\\focus.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\directives\\src\\directives\\focus-trap\\focus-trap.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\directives\\src\\directives\\for-of\\for_of.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach, beforeAll" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\directives\\src\\directives\\form-control\\form-control.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\directives\\src\\directives\\layout\\layout.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\directives\\src\\directives\\mask\\mask.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\directives\\src\\directives\\scroll-inertia\\scroll_inertia.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach, test" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\directives\\src\\directives\\size\\ig-size.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\directives\\src\\directives\\text-highlight\\text-highlight.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\directives\\src\\directives\\text-selection\\text-selection.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\directives\\src\\directives\\toggle\\toggle.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\drop-down\\src\\drop-down\\autocomplete\\autocomplete.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\expansion-panel\\src\\expansion-panel\\expansion-panel.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\expansion-panel\\src\\expansion-panel\\toggle-animation-component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\core\\src\\common\\random.spec.ts", + "UsedFunctions": "describe, it, expect, beforeAll, afterAll" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\core\\src\\grid-actions\\grid-editing-actions.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\core\\src\\grid-actions\\grid-pinning-actions.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\core\\src\\services\\csv\\csv-exporter-grid.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\core\\src\\services\\csv\\csv-exporter.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\core\\src\\services\\csv\\csv-verification-wrapper.spec.ts", + "UsedFunctions": "expect" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\core\\src\\services\\excel\\excel-exporter-grid.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\core\\src\\services\\excel\\excel-exporter.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\core\\src\\services\\excel\\zip-verification-wrapper.spec.ts", + "UsedFunctions": "expect" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\core\\src\\services\\exporter-common\\test-methods.spec.ts", + "UsedFunctions": "expect" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\core\\src\\state.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\core\\src\\state.hierarchicalgrid.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, test" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\core\\src\\state.pivotgrid.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\core\\src\\state.treegrid.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\cell-merge.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\cell.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\column-group.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\column-hiding.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\column-pinning.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\column-resizing.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\column-selection.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\column.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid-add-row.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid-cell-editing.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid-clipboard.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid-collapsible-columns.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, test" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid-filtering-ui.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid-filtering.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid-keyBoardNav-headers.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid-keyBoardNav.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid-mrl-keyboard-nav.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid-row-editing.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid-row-pinning.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid-row-selection.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid-toolbar.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid-validation.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid.crud.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid.groupby.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid.master-detail.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, test" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid.multi-row-layout.integration.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid.multi-row-layout.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid.nested.props.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid.pagination.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid.pinning.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid.search.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\grid.sorting.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\grid\\src\\row-drag.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\hierarchical-grid\\src\\hierarchical-grid-add-row.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\hierarchical-grid\\src\\hierarchical-grid.integration.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\hierarchical-grid\\src\\hierarchical-grid.navigation.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach, afterAll" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\hierarchical-grid\\src\\hierarchical-grid.selection.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\hierarchical-grid\\src\\hierarchical-grid.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\hierarchical-grid\\src\\hierarchical-grid.virtualization.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\pivot-grid\\src\\pivot-data-selector.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\pivot-grid\\src\\pivot-grid-keyboard-nav.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\pivot-grid\\src\\pivot-grid.pipes.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\pivot-grid\\src\\pivot-grid.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\tree-grid\\src\\tree-grid-add-row-ui.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\tree-grid\\src\\tree-grid-crud.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\tree-grid\\src\\tree-grid-expanding.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\tree-grid\\src\\tree-grid-filtering.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\tree-grid\\src\\tree-grid-grouping.pipe.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\tree-grid\\src\\tree-grid-grouping.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\tree-grid\\src\\tree-grid-indentation.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\tree-grid\\src\\tree-grid-integration.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\tree-grid\\src\\tree-grid-keyBoardNav.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\tree-grid\\src\\tree-grid-multi-cell-selection.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\tree-grid\\src\\tree-grid-search.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\tree-grid\\src\\tree-grid-selection.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\tree-grid\\src\\tree-grid-summaries.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\grids\\tree-grid\\src\\tree-grid.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, afterEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\icon\\src\\icon\\icon.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\icon\\src\\icon\\icon.service.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\input-group\\src\\input-group\\directives-hint\\hint.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\input-group\\src\\input-group\\directives-input\\input.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\input-group\\src\\input-group\\directives-input\\read-only-input.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\input-group\\src\\input-group\\input-group.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\list\\src\\list\\list.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\paginator\\src\\paginator\\paginator.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\progressbar\\src\\progressbar\\circularbar.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\progressbar\\src\\progressbar\\linearbar.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\progressbar\\src\\progressbar\\progressbar.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\query-builder\\src\\query-builder\\query-builder-functions.spec.ts", + "UsedFunctions": "expect" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\radio\\src\\radio\\radio-group\\radio-group.directive.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\radio\\src\\radio\\radio.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\snackbar\\src\\snackbar\\snackbar.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\splitter\\src\\splitter\\splitter.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\stepper\\src\\stepper\\stepper.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach, beforeAll, afterAll" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\switch\\src\\switch\\switch.component.spec.ts", + "UsedFunctions": "describe, it, expect, beforeEach" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\test-utils\\controls-functions.spec.ts", + "UsedFunctions": "expect" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\test-utils\\grid-validation-samples.spec.ts", + "UsedFunctions": "test" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\test-utils\\pivot-grid-functions.spec.ts", + "UsedFunctions": "expect" + }, + { + "File": "C:\\Users\\SStoychev\\Documents\\Git\\igniteui-angular\\projects\\igniteui-angular\\test-utils\\tree-grid-functions.spec.ts", + "UsedFunctions": "expect" + } +] diff --git a/package-lock.json b/package-lock.json index 7fa7a167cb6..28cac1a1909 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,13 +54,13 @@ "@types/estree": "^1.0.0", "@types/express": "^5.0.0", "@types/hammerjs": "^2.0.46", - "@types/jasmine": "^5.1.7", - "@types/jasminewd2": "^2.0.10", "@types/node": "^20.17.6", "@types/sass-true": "^6.0.2", "@types/webpack-env": "^1.18.3", "@typescript-eslint/eslint-plugin": "^8.33.1", "@typescript-eslint/parser": "^8.33.1", + "@vitest/browser-playwright": "^4.0.17", + "@vitest/coverage-v8": "^4.0.17", "autoprefixer": "^10.4.16", "del": "^6.0.0", "eslint": "^9.28.0", @@ -79,15 +79,6 @@ "igniteui-i18n-resources": "^1.0.2", "igniteui-sassdoc-theme": "^2.1.0", "igniteui-webcomponents": "^6.5.0", - "jasmine": "^5.6.0", - "jasmine-core": "^5.6.0", - "karma": "^6.4.4", - "karma-chrome-launcher": "~3.2.0", - "karma-coverage": "^2.0.3", - "karma-jasmine": "~5.1.0", - "karma-junit-reporter": "^2.0.1", - "karma-parallel": "^0.3.1", - "karma-spec-reporter": "^0.0.36", "lit-html": "^3.2.1", "ng-packagr": "^21.0.0", "postcss": "^8.5.1", @@ -105,7 +96,8 @@ "ts-node": "^10.8.1", "typedoc": "^0.28.14", "typedoc-plugin-localization": "^3.1.0", - "typescript": "5.9.3" + "typescript": "5.9.3", + "vitest": "^4.0.17" } }, "node_modules/@adobe/css-tools": { @@ -116,57 +108,57 @@ "license": "MIT" }, "node_modules/@algolia/abtesting": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.12.2.tgz", - "integrity": "sha512-oWknd6wpfNrmRcH0vzed3UPX0i17o4kYLM5OMITyMVM2xLgaRbIafoxL0e8mcrNNb0iORCJA0evnNDKRYth5WQ==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.6.1.tgz", + "integrity": "sha512-wV/gNRkzb7sI9vs1OneG129hwe3Q5zPj7zigz3Ps7M5Lpo2hSorrOnXNodHEOV+yXE/ks4Pd+G3CDFIjFTWhMQ==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" + "@algolia/client-common": "5.40.1", + "@algolia/requester-browser-xhr": "5.40.1", + "@algolia/requester-fetch": "5.40.1", + "@algolia/requester-node-http": "5.40.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-abtesting": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.46.2.tgz", - "integrity": "sha512-oRSUHbylGIuxrlzdPA8FPJuwrLLRavOhAmFGgdAvMcX47XsyM+IOGa9tc7/K5SPvBqn4nhppOCEz7BrzOPWc4A==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.40.1.tgz", + "integrity": "sha512-cxKNATPY5t+Mv8XAVTI57altkaPH+DZi4uMrnexPxPHODMljhGYY+GDZyHwv9a+8CbZHcY372OkxXrDMZA4Lnw==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" + "@algolia/client-common": "5.40.1", + "@algolia/requester-browser-xhr": "5.40.1", + "@algolia/requester-fetch": "5.40.1", + "@algolia/requester-node-http": "5.40.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-analytics": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.46.2.tgz", - "integrity": "sha512-EPBN2Oruw0maWOF4OgGPfioTvd+gmiNwx0HmD9IgmlS+l75DatcBkKOPNJN+0z3wBQWUO5oq602ATxIfmTQ8bA==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.40.1.tgz", + "integrity": "sha512-XP008aMffJCRGAY8/70t+hyEyvqqV7YKm502VPu0+Ji30oefrTn2al7LXkITz7CK6I4eYXWRhN6NaIUi65F1OA==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" + "@algolia/client-common": "5.40.1", + "@algolia/requester-browser-xhr": "5.40.1", + "@algolia/requester-fetch": "5.40.1", + "@algolia/requester-node-http": "5.40.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-common": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.46.2.tgz", - "integrity": "sha512-Hj8gswSJNKZ0oyd0wWissqyasm+wTz1oIsv5ZmLarzOZAp3vFEda8bpDQ8PUhO+DfkbiLyVnAxsPe4cGzWtqkg==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.40.1.tgz", + "integrity": "sha512-gWfQuQUBtzUboJv/apVGZMoxSaB0M4Imwl1c9Ap+HpCW7V0KhjBddqF2QQt5tJZCOFsfNIgBbZDGsEPaeKUosw==", "dev": true, "license": "MIT", "engines": { @@ -174,151 +166,151 @@ } }, "node_modules/@algolia/client-insights": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.46.2.tgz", - "integrity": "sha512-6dBZko2jt8FmQcHCbmNLB0kCV079Mx/DJcySTL3wirgDBUH7xhY1pOuUTLMiGkqM5D8moVZTvTdRKZUJRkrwBA==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.40.1.tgz", + "integrity": "sha512-RTLjST/t+lsLMouQ4zeLJq2Ss+UNkLGyNVu+yWHanx6kQ3LT5jv8UvPwyht9s7R6jCPnlSI77WnL80J32ZuyJg==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" + "@algolia/client-common": "5.40.1", + "@algolia/requester-browser-xhr": "5.40.1", + "@algolia/requester-fetch": "5.40.1", + "@algolia/requester-node-http": "5.40.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-personalization": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.46.2.tgz", - "integrity": "sha512-1waE2Uqh/PHNeDXGn/PM/WrmYOBiUGSVxAWqiJIj73jqPqvfzZgzdakHscIVaDl6Cp+j5dwjsZ5LCgaUr6DtmA==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.40.1.tgz", + "integrity": "sha512-2FEK6bUomBzEYkTKzD0iRs7Ljtjb45rKK/VSkyHqeJnG+77qx557IeSO0qVFE3SfzapNcoytTofnZum0BQ6r3Q==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" + "@algolia/client-common": "5.40.1", + "@algolia/requester-browser-xhr": "5.40.1", + "@algolia/requester-fetch": "5.40.1", + "@algolia/requester-node-http": "5.40.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-query-suggestions": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.46.2.tgz", - "integrity": "sha512-EgOzTZkyDcNL6DV0V/24+oBJ+hKo0wNgyrOX/mePBM9bc9huHxIY2352sXmoZ648JXXY2x//V1kropF/Spx83w==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.40.1.tgz", + "integrity": "sha512-Nju4NtxAvXjrV2hHZNLKVJLXjOlW6jAXHef/CwNzk1b2qIrCWDO589ELi5ZHH1uiWYoYyBXDQTtHmhaOVVoyXg==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" + "@algolia/client-common": "5.40.1", + "@algolia/requester-browser-xhr": "5.40.1", + "@algolia/requester-fetch": "5.40.1", + "@algolia/requester-node-http": "5.40.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-search": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.46.2.tgz", - "integrity": "sha512-ZsOJqu4HOG5BlvIFnMU0YKjQ9ZI6r3C31dg2jk5kMWPSdhJpYL9xa5hEe7aieE+707dXeMI4ej3diy6mXdZpgA==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.40.1.tgz", + "integrity": "sha512-Mw6pAUF121MfngQtcUb5quZVqMC68pSYYjCRZkSITC085S3zdk+h/g7i6FxnVdbSU6OztxikSDMh1r7Z+4iPlA==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" + "@algolia/client-common": "5.40.1", + "@algolia/requester-browser-xhr": "5.40.1", + "@algolia/requester-fetch": "5.40.1", + "@algolia/requester-node-http": "5.40.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/ingestion": { - "version": "1.46.2", - "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.46.2.tgz", - "integrity": "sha512-1Uw2OslTWiOFDtt83y0bGiErJYy5MizadV0nHnOoHFWMoDqWW0kQoMFI65pXqRSkVvit5zjXSLik2xMiyQJDWQ==", + "version": "1.40.1", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.40.1.tgz", + "integrity": "sha512-z+BPlhs45VURKJIxsR99NNBWpUEEqIgwt10v/fATlNxc4UlXvALdOsWzaFfe89/lbP5Bu4+mbO59nqBC87ZM/g==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" + "@algolia/client-common": "5.40.1", + "@algolia/requester-browser-xhr": "5.40.1", + "@algolia/requester-fetch": "5.40.1", + "@algolia/requester-node-http": "5.40.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/monitoring": { - "version": "1.46.2", - "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.46.2.tgz", - "integrity": "sha512-xk9f+DPtNcddWN6E7n1hyNNsATBCHIqAvVGG2EAGHJc4AFYL18uM/kMTiOKXE/LKDPyy1JhIerrh9oYb7RBrgw==", + "version": "1.40.1", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.40.1.tgz", + "integrity": "sha512-VJMUMbO0wD8Rd2VVV/nlFtLJsOAQvjnVNGkMkspFiFhpBA7s/xJOb+fJvvqwKFUjbKTUA7DjiSi1ljSMYBasXg==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" + "@algolia/client-common": "5.40.1", + "@algolia/requester-browser-xhr": "5.40.1", + "@algolia/requester-fetch": "5.40.1", + "@algolia/requester-node-http": "5.40.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/recommend": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.46.2.tgz", - "integrity": "sha512-NApbTPj9LxGzNw4dYnZmj2BoXiAc8NmbbH6qBNzQgXklGklt/xldTvu+FACN6ltFsTzoNU6j2mWNlHQTKGC5+Q==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.40.1.tgz", + "integrity": "sha512-ehvJLadKVwTp9Scg9NfzVSlBKH34KoWOQNTaN8i1Ac64AnO6iH2apJVSP6GOxssaghZ/s8mFQsDH3QIZoluFHA==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" + "@algolia/client-common": "5.40.1", + "@algolia/requester-browser-xhr": "5.40.1", + "@algolia/requester-fetch": "5.40.1", + "@algolia/requester-node-http": "5.40.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.46.2.tgz", - "integrity": "sha512-ekotpCwpSp033DIIrsTpYlGUCF6momkgupRV/FA3m62SreTSZUKjgK6VTNyG7TtYfq9YFm/pnh65bATP/ZWJEg==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.40.1.tgz", + "integrity": "sha512-PbidVsPurUSQIr6X9/7s34mgOMdJnn0i6p+N6Ab+lsNhY5eiu+S33kZEpZwkITYBCIbhzDLOvb7xZD3gDi+USA==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.46.2" + "@algolia/client-common": "5.40.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-fetch": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.46.2.tgz", - "integrity": "sha512-gKE+ZFi/6y7saTr34wS0SqYFDcjHW4Wminv8PDZEi0/mE99+hSrbKgJWxo2ztb5eqGirQTgIh1AMVacGGWM1iw==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.40.1.tgz", + "integrity": "sha512-ThZ5j6uOZCF11fMw9IBkhigjOYdXGXQpj6h4k+T9UkZrF2RlKcPynFzDeRgaLdpYk8Yn3/MnFbwUmib7yxj5Lw==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.46.2" + "@algolia/client-common": "5.40.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-node-http": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.46.2.tgz", - "integrity": "sha512-ciPihkletp7ttweJ8Zt+GukSVLp2ANJHU+9ttiSxsJZThXc4Y2yJ8HGVWesW5jN1zrsZsezN71KrMx/iZsOYpg==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.40.1.tgz", + "integrity": "sha512-H1gYPojO6krWHnUXu/T44DrEun/Wl95PJzMXRcM/szstNQczSbwq6wIFJPI9nyE95tarZfUNU3rgorT+wZ6iCQ==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/client-common": "5.46.2" + "@algolia/client-common": "5.40.1" }, "engines": { "node": ">= 14.0.0" @@ -382,40 +374,10 @@ } } }, - "node_modules/@angular-devkit/architect/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@angular-devkit/architect/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@angular-devkit/core": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-21.1.0.tgz", - "integrity": "sha512-dPfVy0CictDjWffRv4pGTPOFjdlJL3ZkGUqxzaosUjMbJW+Ai9cNn1VNr7zxYZ4kem3BxLBh1thzDsCPrkXlZA==", + "version": "21.0.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-21.0.5.tgz", + "integrity": "sha512-STDOtPbd8vePqyneQaLR8c9hnu7BieU7aPG5Icgl0pevv7EfCmwZUTqvK5nCpLk0tVFo6D1WHwIDZ3fnyvFW1A==", "dev": true, "license": "MIT", "dependencies": { @@ -432,7 +394,7 @@ "yarn": ">= 1.13.0" }, "peerDependencies": { - "chokidar": "^5.0.0" + "chokidar": "^4.0.0" }, "peerDependenciesMeta": { "chokidar": { @@ -441,15 +403,15 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-21.1.0.tgz", - "integrity": "sha512-sVgTntCZCOV7mOpHzj6V14KOAoy4B9Ur9yHNRFZVgL2yD77TYRrJ0qwq+l7Im9fSjMCar6csjboqCvyAEpfV1g==", + "version": "21.0.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-21.0.5.tgz", + "integrity": "sha512-U6Z/OEce3R9CJl8/xuVrNVp0uhv3Ac4wRjpG18kE0dh5R87ablhqr/wkP3rZbWpdGwuGSJ+cR7LE5IbwSswejA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "21.1.0", + "@angular-devkit/core": "21.0.5", "jsonc-parser": "3.3.1", - "magic-string": "0.30.21", + "magic-string": "0.30.19", "ora": "9.0.0", "rxjs": "7.8.2" }, @@ -502,36 +464,6 @@ } } }, - "node_modules/@angular-eslint/builder/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@angular-eslint/builder/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@angular-eslint/bundled-angular-compiler": { "version": "20.7.0", "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-20.7.0.tgz", @@ -652,22 +584,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@angular-eslint/schematics/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@angular-eslint/schematics/node_modules/cli-spinners": { "version": "2.9.2", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", @@ -752,20 +668,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@angular-eslint/schematics/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@angular-eslint/schematics/node_modules/string-width": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", @@ -815,9 +717,9 @@ } }, "node_modules/@angular/animations": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-21.1.0.tgz", - "integrity": "sha512-RTpRdWhwz1PsMJC8NuuYIKCgMFP9EyxOrSaI0bpCLIGtXCfmvvHiU2FkBksV86MqYOf+wurKATb71QcfGrV3Hg==", + "version": "21.0.8", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-21.0.8.tgz", + "integrity": "sha512-1YXHZQO/LYiExbg7sZhiqqF5fMcH17iVgK1tI2Gk90Yy0HQAuqnteOv3pPGgUfLowNOWK0sGhCYbB2Lq21LA3w==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -826,43 +728,43 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/core": "21.1.0" + "@angular/core": "21.0.8" } }, "node_modules/@angular/build": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-21.1.0.tgz", - "integrity": "sha512-ftms4F/TlkRNhf/4ykFO12zTG0f9sIRZ4fGFnaOVGmnKYkPKZklWvMCPoaoIligHS2pqKye1a5JSiTgTeUDp9w==", + "version": "21.0.5", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-21.0.5.tgz", + "integrity": "sha512-4Ejb5pA118GGyZOAGjSmZMCx5HbovRSjiqLuCmpjf9hUgs50GPNJbigWW1ewz5+KmFrc8ouEoirpgTQyaKKZ3Q==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.2101.0", - "@babel/core": "7.28.5", + "@angular-devkit/architect": "0.2100.5", + "@babel/core": "7.28.4", "@babel/helper-annotate-as-pure": "7.27.3", "@babel/helper-split-export-declaration": "7.24.7", - "@inquirer/confirm": "5.1.21", + "@inquirer/confirm": "5.1.19", "@vitejs/plugin-basic-ssl": "2.1.0", "beasties": "0.3.5", "browserslist": "^4.26.0", - "esbuild": "0.27.2", + "esbuild": "0.26.0", "https-proxy-agent": "7.0.6", "istanbul-lib-instrument": "6.0.3", "jsonc-parser": "3.3.1", "listr2": "9.0.5", - "magic-string": "0.30.21", + "magic-string": "0.30.19", "mrmime": "2.0.1", "parse5-html-rewriting-stream": "8.0.0", "picomatch": "4.0.3", - "piscina": "5.1.4", - "rolldown": "1.0.0-beta.58", - "sass": "1.97.1", + "piscina": "5.1.3", + "rolldown": "1.0.0-beta.47", + "sass": "1.93.2", "semver": "7.7.3", "source-map-support": "0.5.21", "tinyglobby": "0.2.15", - "undici": "7.18.0", - "vite": "7.3.0", - "watchpack": "2.5.0" + "undici": "7.16.0", + "vite": "7.2.2", + "watchpack": "2.4.4" }, "engines": { "node": "^20.19.0 || ^22.12.0 || >=24.0.0", @@ -870,7 +772,7 @@ "yarn": ">= 1.13.0" }, "optionalDependencies": { - "lmdb": "3.4.4" + "lmdb": "3.4.3" }, "peerDependencies": { "@angular/compiler": "^21.0.0", @@ -880,7 +782,7 @@ "@angular/platform-browser": "^21.0.0", "@angular/platform-server": "^21.0.0", "@angular/service-worker": "^21.0.0", - "@angular/ssr": "^21.1.0", + "@angular/ssr": "^21.0.5", "karma": "^6.4.0", "less": "^4.2.0", "ng-packagr": "^21.0.0", @@ -930,18 +832,15 @@ } }, "node_modules/@angular/build/node_modules/@angular-devkit/architect": { - "version": "0.2101.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2101.0.tgz", - "integrity": "sha512-vnNAzWXwSRGTHk2K7woIQsj7WDYZp69Z3DBdlxkK0H08ymkJ/ELbhN0/AnIJNNtYCqEb57AH7Ro98n422beDuw==", + "version": "0.2100.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2100.5.tgz", + "integrity": "sha512-KKmZMXzHCX0cWHY7xo9yy1J0fV7S/suhPO00YTcHBgLivkLsnbI177CrmWiMdLxSJD3NqTVkBEMPFQ2I2ooDFw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "21.1.0", + "@angular-devkit/core": "21.0.5", "rxjs": "7.8.2" }, - "bin": { - "architect": "bin/cli.js" - }, "engines": { "node": "^20.19.0 || ^22.12.0 || >=24.0.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", @@ -949,31 +848,31 @@ } }, "node_modules/@angular/cli": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-21.1.0.tgz", - "integrity": "sha512-kzk8du388x6EBybJeq5AB27qGm8oGC9HhvBJDbu8o+aBIOY+JwVON9m4SYLCzeT+EVK8sKA1NMVYi2CDerk6hA==", + "version": "21.0.5", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-21.0.5.tgz", + "integrity": "sha512-UYFQqn9Ow1wFVSwdB/xfjmZo4Yb7CUNxilbeYDFIybesfxXSdjMJBbXLtV0+icIhjmqfSUm2gTls6WIrG8qv9A==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.2101.0", - "@angular-devkit/core": "21.1.0", - "@angular-devkit/schematics": "21.1.0", - "@inquirer/prompts": "7.10.1", + "@angular-devkit/architect": "0.2100.5", + "@angular-devkit/core": "21.0.5", + "@angular-devkit/schematics": "21.0.5", + "@inquirer/prompts": "7.9.0", "@listr2/prompt-adapter-inquirer": "3.0.5", "@modelcontextprotocol/sdk": "1.25.2", - "@schematics/angular": "21.1.0", + "@schematics/angular": "21.0.5", "@yarnpkg/lockfile": "1.1.0", - "algoliasearch": "5.46.2", - "ini": "6.0.0", + "algoliasearch": "5.40.1", + "ini": "5.0.0", "jsonc-parser": "3.3.1", "listr2": "9.0.5", - "npm-package-arg": "13.0.2", - "pacote": "21.0.4", + "npm-package-arg": "13.0.1", + "pacote": "21.0.3", "parse5-html-rewriting-stream": "8.0.0", "resolve": "1.22.11", "semver": "7.7.3", "yargs": "18.0.0", - "zod": "4.3.5" + "zod": "4.1.13" }, "bin": { "ng": "bin/ng.js" @@ -985,18 +884,15 @@ } }, "node_modules/@angular/cli/node_modules/@angular-devkit/architect": { - "version": "0.2101.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2101.0.tgz", - "integrity": "sha512-vnNAzWXwSRGTHk2K7woIQsj7WDYZp69Z3DBdlxkK0H08ymkJ/ELbhN0/AnIJNNtYCqEb57AH7Ro98n422beDuw==", + "version": "0.2100.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2100.5.tgz", + "integrity": "sha512-KKmZMXzHCX0cWHY7xo9yy1J0fV7S/suhPO00YTcHBgLivkLsnbI177CrmWiMdLxSJD3NqTVkBEMPFQ2I2ooDFw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "21.1.0", + "@angular-devkit/core": "21.0.5", "rxjs": "7.8.2" }, - "bin": { - "architect": "bin/cli.js" - }, "engines": { "node": "^20.19.0 || ^22.12.0 || >=24.0.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", @@ -1004,9 +900,9 @@ } }, "node_modules/@angular/cli/node_modules/zod": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.5.tgz", - "integrity": "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==", + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz", + "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", "dev": true, "license": "MIT", "funding": { @@ -1014,9 +910,9 @@ } }, "node_modules/@angular/common": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-21.1.0.tgz", - "integrity": "sha512-hL3Chp51TU9iBcIfkNtoBS1wuseP1gsyDW2IFtK5HUpAVhbso9B3fdCaDTFkU98A2unluo2YgzI6D/6IS6N+1g==", + "version": "21.0.8", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-21.0.8.tgz", + "integrity": "sha512-on1B4oc/pf7IlkbG08Et/cCDSX8dpZz9iwp3zMFN/0JvorspyL5YOovFJfjdpmjdlrIi+ToGImwyIkY9P8Mblw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1025,14 +921,14 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/core": "21.1.0", + "@angular/core": "21.0.8", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-21.1.0.tgz", - "integrity": "sha512-UprCiJwEU1Ilw1dVk+yLgNiHlbH81obAuh92lRKozUQRgtSCpOfCQUM79q5r+VdmCPxDshr79U2Ke0fRaiJfAQ==", + "version": "21.0.8", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-21.0.8.tgz", + "integrity": "sha512-k/EPMuNvfn0eebEMmVcwhMlCWqzER/BEHVqTQCKsAAt7AuYZuluz7oR8Ypw96v3jbY+ZaH1ZvAzrK6URzryhOg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1042,15 +938,15 @@ } }, "node_modules/@angular/compiler-cli": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-21.1.0.tgz", - "integrity": "sha512-//BTtxJovsF0LaOWQkOVxWX4EVyNJaPus+IlwWxzmdRHpojIl1Zdyy9BJMVJOifvj3XQ16sZwR1PDWDI5DIWrg==", + "version": "21.0.8", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-21.0.8.tgz", + "integrity": "sha512-+i/wFvi5FTg47Ei+aiFf8j3iYfjQ79ieg8oJM86+Mw4bNwEKQqvWcpmKjoqcfmCescuw0sr2DXU6OEeX+yWeVg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "7.28.5", + "@babel/core": "7.28.4", "@jridgewell/sourcemap-codec": "^1.4.14", - "chokidar": "^5.0.0", + "chokidar": "^4.0.0", "convert-source-map": "^1.5.1", "reflect-metadata": "^0.2.0", "semver": "^7.0.0", @@ -1065,7 +961,7 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/compiler": "21.1.0", + "@angular/compiler": "21.0.8", "typescript": ">=5.9 <6.0" }, "peerDependenciesMeta": { @@ -1075,9 +971,9 @@ } }, "node_modules/@angular/core": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-21.1.0.tgz", - "integrity": "sha512-QTl9s8GYNN0pt1k3GE6UVlfe6zWtfdykhfchinKq2YJywQ6LBM4UcZgoc56YkgscmyrRFYrr4JYUJjlzTF57+A==", + "version": "21.0.8", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-21.0.8.tgz", + "integrity": "sha512-8dNolIQn8WHrD3PsqGuPrujxDX5hjpMbioifIByjjX9yaJy9on7AewVGb8m/DHVwWQ1eGVAGmvW9wt+h+nlzLg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1086,7 +982,7 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/compiler": "21.1.0", + "@angular/compiler": "21.0.8", "rxjs": "^6.5.3 || ^7.4.0", "zone.js": "~0.15.0 || ~0.16.0" }, @@ -1100,9 +996,9 @@ } }, "node_modules/@angular/elements": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/@angular/elements/-/elements-21.1.0.tgz", - "integrity": "sha512-AkCSV757KYgeTLo/x0pZbkvLAaqfzC8QyDLUOUBn48hFAjPB0IA9yApxzP/EkV2nY9Hq8GEJgGeR6Cgo9yalYA==", + "version": "21.0.8", + "resolved": "https://registry.npmjs.org/@angular/elements/-/elements-21.0.8.tgz", + "integrity": "sha512-eOvxX5eQw5u5Dp1UT6hhv7OSH6P/xzWb4MwiKS8fZhAJs0CNY3WtJfKTJCFJ3vwIk0zIoqz52OV1lrT6fuozHQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1111,14 +1007,14 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/core": "21.1.0", + "@angular/core": "21.0.8", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/forms": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-21.1.0.tgz", - "integrity": "sha512-1Qxsu2cQhraKe2dKzIVm7no1qWi76QsXVwY7+VGKRYG7p+fKaFmnr7oU5EbJL66TsFzCb8mDGxLGikS+YE+X/g==", + "version": "21.0.8", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-21.0.8.tgz", + "integrity": "sha512-H03A50elawXO53xkz0Aytar5kYT14GLeaj6dLKc1kcR5NqvX9Y/R7z3bY52tvypAdIR8CmPT7ad07TlT4O9lkg==", "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.0.0", @@ -1128,16 +1024,16 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/common": "21.1.0", - "@angular/core": "21.1.0", - "@angular/platform-browser": "21.1.0", + "@angular/common": "21.0.8", + "@angular/core": "21.0.8", + "@angular/platform-browser": "21.0.8", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/language-service": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-21.1.0.tgz", - "integrity": "sha512-xl6wdJCmC/2tkkWeBxir/szDSnNXFtlnaONVG7GViIT++xksh7PNQXt90pnFrP1hSZDAZ41TnWYlWHvFVQRIMQ==", + "version": "21.0.8", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-21.0.8.tgz", + "integrity": "sha512-vbgqbBwJxbB3p68nQwacDK5bfpsCd2b8evJCvtG5vEqPr0oTok9APpjQ3F56Yzfi5RjPjSyZY6SbqwAqwy/esQ==", "dev": true, "license": "MIT", "engines": { @@ -1145,9 +1041,9 @@ } }, "node_modules/@angular/platform-browser": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-21.1.0.tgz", - "integrity": "sha512-Drkal25x+OuRQosAE/cL4uM5WDmgFehanCpsjQ1jGp6Rxoad6Q5Do1uQAE3qgMKHL1aqCPZ+uWzcVVG+Bn1ddg==", + "version": "21.0.8", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-21.0.8.tgz", + "integrity": "sha512-5rPyrP6n6ClO0ZEUXndS2/Xb7nZrbjjYWOxgfCb+ZTCiU7eyN6zhSmicKk2dLQxE1M15wbTa87dN6/Ytuq2uvg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1156,9 +1052,9 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/animations": "21.1.0", - "@angular/common": "21.1.0", - "@angular/core": "21.1.0" + "@angular/animations": "21.0.8", + "@angular/common": "21.0.8", + "@angular/core": "21.0.8" }, "peerDependenciesMeta": { "@angular/animations": { @@ -1167,9 +1063,9 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-21.1.0.tgz", - "integrity": "sha512-NsjHxqgErrIIp96lWq5IqyuyJv5sb8L6pdINtY04kFh8bVWzS7+clr/P6emIi3N7d+pX+JGd4EOp8b8veQi8Lg==", + "version": "21.0.8", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-21.0.8.tgz", + "integrity": "sha512-i1pW2tSl9zG8hkqPYPifP7WGNDUuqIn8YVCLizNahINin5OIcb/KfuoYBC2zfDlaJaTY9no6PHbsbTD0cP5hrg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1178,16 +1074,16 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/common": "21.1.0", - "@angular/compiler": "21.1.0", - "@angular/core": "21.1.0", - "@angular/platform-browser": "21.1.0" + "@angular/common": "21.0.8", + "@angular/compiler": "21.0.8", + "@angular/core": "21.0.8", + "@angular/platform-browser": "21.0.8" } }, "node_modules/@angular/platform-server": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-21.1.0.tgz", - "integrity": "sha512-adxFwVkWH2NkYc0/GulKLUyJfPxWNJjvHaQTOfZzKIHoIHjUJzz5Zug8EvM/YVepYUozyzx3mKvbTrpruqV10A==", + "version": "21.0.8", + "resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-21.0.8.tgz", + "integrity": "sha512-EwAQ7W/zFF7LHd9vHca3ewQ14GL9CQ4UL3TWxWlRGDgTDI9pVyQNkfW6RecleGp40vg3sFZZtIocpTYM4gKZ+A==", "license": "MIT", "dependencies": { "tslib": "^2.3.0", @@ -1197,17 +1093,17 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/common": "21.1.0", - "@angular/compiler": "21.1.0", - "@angular/core": "21.1.0", - "@angular/platform-browser": "21.1.0", + "@angular/common": "21.0.8", + "@angular/compiler": "21.0.8", + "@angular/core": "21.0.8", + "@angular/platform-browser": "21.0.8", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/router": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-21.1.0.tgz", - "integrity": "sha512-Sneu0ePuH+bf8ZslRX3iQk1iLziindLskdTeHV1ZCrXdT0ZScsZyI/gjxQKBtsIU9692D2DnFQRLGnzTBYVGVw==", + "version": "21.0.8", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-21.0.8.tgz", + "integrity": "sha512-LPR65wyWBSyR46fGeQtD92+TM635o0lh+N5k9qPZdMacogwViTrtBHWPfKYBtBUXLWEWXXKJfSbXvhh3w3uLxw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1216,16 +1112,16 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/common": "21.1.0", - "@angular/core": "21.1.0", - "@angular/platform-browser": "21.1.0", + "@angular/common": "21.0.8", + "@angular/core": "21.0.8", + "@angular/platform-browser": "21.0.8", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/ssr": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/@angular/ssr/-/ssr-21.1.0.tgz", - "integrity": "sha512-ghDVijKzBeN7HMgczPqrrEfLimr0SUGPlg7sYpT2yHWDhOh1Ncn1RmegwSOl+/fIB8Wv9R8S9ViGKWyGlIMyIg==", + "version": "21.0.5", + "resolved": "https://registry.npmjs.org/@angular/ssr/-/ssr-21.0.5.tgz", + "integrity": "sha512-8WgAPimT6005FFrud1ouCNpcar8WqQNtcG1dQHTdhkp2SeWttnaXg+J0udkYYaEeHqPiH9/wKIN9Aenu0WmhiA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -1347,13 +1243,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz", - "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", + "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, @@ -1362,9 +1258,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz", - "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", "dev": true, "license": "MIT", "engines": { @@ -1372,21 +1268,21 @@ } }, "node_modules/@babel/core": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", - "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", + "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", + "@babel/generator": "^7.28.3", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.28.3", "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.5", + "@babel/parser": "^7.28.4", "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5", + "@babel/traverse": "^7.28.4", + "@babel/types": "^7.28.4", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -1420,14 +1316,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.6.tgz", - "integrity": "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6", + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -1450,13 +1346,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.28.6", + "@babel/compat-data": "^7.27.2", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", @@ -1487,29 +1383,29 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" }, "engines": { "node": ">=6.9.0" @@ -1562,27 +1458,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz", - "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.28.6" + "@babel/types": "^7.28.5" }, "bin": { "parser": "bin/babel-parser.js" @@ -1592,42 +1488,42 @@ } }, "node_modules/@babel/runtime": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", - "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.6.tgz", - "integrity": "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/generator": "^7.28.6", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.6", - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", "debug": "^4.3.1" }, "engines": { @@ -1635,9 +1531,9 @@ } }, "node_modules/@babel/types": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz", - "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", "dev": true, "license": "MIT", "dependencies": { @@ -1648,6 +1544,16 @@ "node": ">=6.9.0" } }, + "node_modules/@bcoe/v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/@bufbuild/protobuf": { "version": "2.10.2", "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.10.2.tgz", @@ -1669,26 +1575,26 @@ } }, "node_modules/@cacheable/memory/node_modules/@keyv/bigmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.1.tgz", - "integrity": "sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.0.tgz", + "integrity": "sha512-KT01GjzV6AQD5+IYrcpoYLkCu1Jod3nau1Z7EsEuViO3TZGRacSbO9MfHmbJ1WaOXFtWLxPVj169cn2WNKPkIg==", "dev": true, "license": "MIT", "dependencies": { - "hashery": "^1.4.0", - "hookified": "^1.15.0" + "hashery": "^1.2.0", + "hookified": "^1.13.0" }, "engines": { "node": ">= 18" }, "peerDependencies": { - "keyv": "^5.6.0" + "keyv": "^5.5.4" } }, "node_modules/@cacheable/memory/node_modules/keyv": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", - "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "version": "5.5.5", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.5.5.tgz", + "integrity": "sha512-FA5LmZVF1VziNc0bIdCSA1IoSVnDCqE8HJIZZv2/W8YmoAM50+tnUgJR/gQZwEeIMleuIOnRnHA/UaZRNeV4iQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1707,9 +1613,9 @@ } }, "node_modules/@cacheable/utils/node_modules/keyv": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", - "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "version": "5.5.5", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.5.5.tgz", + "integrity": "sha512-FA5LmZVF1VziNc0bIdCSA1IoSVnDCqE8HJIZZv2/W8YmoAM50+tnUgJR/gQZwEeIMleuIOnRnHA/UaZRNeV4iQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1729,16 +1635,6 @@ "node": ">=18" } }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.1.90" - } - }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -1978,9 +1874,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", - "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.26.0.tgz", + "integrity": "sha512-hj0sKNCQOOo2fgyII3clmJXP28VhgDfU5iy3GNHlWO76KG6N7x4D9ezH5lJtQTG+1J6MFDAJXC1qsI+W+LvZoA==", "cpu": [ "ppc64" ], @@ -1995,9 +1891,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", - "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.26.0.tgz", + "integrity": "sha512-C0hkDsYNHZkBtPxxDx177JN90/1MiCpvBNjz1f5yWJo1+5+c5zr8apjastpEG+wtPjo9FFtGG7owSsAxyKiHxA==", "cpu": [ "arm" ], @@ -2012,9 +1908,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", - "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.26.0.tgz", + "integrity": "sha512-DDnoJ5eoa13L8zPh87PUlRd/IyFaIKOlRbxiwcSbeumcJ7UZKdtuMCHa1Q27LWQggug6W4m28i4/O2qiQQ5NZQ==", "cpu": [ "arm64" ], @@ -2029,9 +1925,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", - "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.26.0.tgz", + "integrity": "sha512-bKDkGXGZnj0T70cRpgmv549x38Vr2O3UWLbjT2qmIkdIWcmlg8yebcFWoT9Dku7b5OV3UqPEuNKRzlNhjwUJ9A==", "cpu": [ "x64" ], @@ -2046,9 +1942,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", - "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.26.0.tgz", + "integrity": "sha512-6Z3naJgOuAIB0RLlJkYc81An3rTlQ/IeRdrU3dOea8h/PvZSgitZV+thNuIccw0MuK1GmIAnAmd5TrMZad8FTQ==", "cpu": [ "arm64" ], @@ -2063,9 +1959,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", - "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.26.0.tgz", + "integrity": "sha512-OPnYj0zpYW0tHusMefyaMvNYQX5pNQuSsHFTHUBNp3vVXupwqpxofcjVsUx11CQhGVkGeXjC3WLjh91hgBG2xw==", "cpu": [ "x64" ], @@ -2080,9 +1976,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", - "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.26.0.tgz", + "integrity": "sha512-jix2fa6GQeZhO1sCKNaNMjfj5hbOvoL2F5t+w6gEPxALumkpOV/wq7oUBMHBn2hY2dOm+mEV/K+xfZy3mrsxNQ==", "cpu": [ "arm64" ], @@ -2097,9 +1993,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", - "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.26.0.tgz", + "integrity": "sha512-tccJaH5xHJD/239LjbVvJwf6T4kSzbk6wPFerF0uwWlkw/u7HL+wnAzAH5GB2irGhYemDgiNTp8wJzhAHQ64oA==", "cpu": [ "x64" ], @@ -2114,9 +2010,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", - "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.26.0.tgz", + "integrity": "sha512-JY8NyU31SyRmRpuc5W8PQarAx4TvuYbyxbPIpHAZdr/0g4iBr8KwQBS4kiiamGl2f42BBecHusYCsyxi7Kn8UQ==", "cpu": [ "arm" ], @@ -2131,9 +2027,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", - "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.26.0.tgz", + "integrity": "sha512-IMJYN7FSkLttYyTbsbme0Ra14cBO5z47kpamo16IwggzzATFY2lcZAwkbcNkWiAduKrTgFJP7fW5cBI7FzcuNQ==", "cpu": [ "arm64" ], @@ -2148,9 +2044,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", - "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.26.0.tgz", + "integrity": "sha512-XITaGqGVLgk8WOHw8We9Z1L0lbLFip8LyQzKYFKO4zFo1PFaaSKsbNjvkb7O8kEXytmSGRkYpE8LLVpPJpsSlw==", "cpu": [ "ia32" ], @@ -2165,9 +2061,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", - "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.26.0.tgz", + "integrity": "sha512-MkggfbDIczStUJwq9wU7gQ7kO33d8j9lWuOCDifN9t47+PeI+9m2QVh51EI/zZQ1spZtFMC1nzBJ+qNGCjJnsg==", "cpu": [ "loong64" ], @@ -2182,9 +2078,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", - "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.26.0.tgz", + "integrity": "sha512-fUYup12HZWAeccNLhQ5HwNBPr4zXCPgUWzEq2Rfw7UwqwfQrFZ0SR/JljaURR8xIh9t+o1lNUFTECUTmaP7yKA==", "cpu": [ "mips64el" ], @@ -2199,9 +2095,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", - "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.26.0.tgz", + "integrity": "sha512-MzRKhM0Ip+//VYwC8tialCiwUQ4G65WfALtJEFyU0GKJzfTYoPBw5XNWf0SLbCUYQbxTKamlVwPmcw4DgZzFxg==", "cpu": [ "ppc64" ], @@ -2216,9 +2112,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", - "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.26.0.tgz", + "integrity": "sha512-QhCc32CwI1I4Jrg1enCv292sm3YJprW8WHHlyxJhae/dVs+KRWkbvz2Nynl5HmZDW/m9ZxrXayHzjzVNvQMGQA==", "cpu": [ "riscv64" ], @@ -2233,9 +2129,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", - "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.26.0.tgz", + "integrity": "sha512-1D6vi6lfI18aNT1aTf2HV+RIlm6fxtlAp8eOJ4mmnbYmZ4boz8zYDar86sIYNh0wmiLJEbW/EocaKAX6Yso2fw==", "cpu": [ "s390x" ], @@ -2250,9 +2146,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", - "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.26.0.tgz", + "integrity": "sha512-rnDcepj7LjrKFvZkx+WrBv6wECeYACcFjdNPvVPojCPJD8nHpb3pv3AuR9CXgdnjH1O23btICj0rsp0L9wAnHA==", "cpu": [ "x64" ], @@ -2267,9 +2163,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", - "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.26.0.tgz", + "integrity": "sha512-FSWmgGp0mDNjEXXFcsf12BmVrb+sZBBBlyh3LwB/B9ac3Kkc8x5D2WimYW9N7SUkolui8JzVnVlWh7ZmjCpnxw==", "cpu": [ "arm64" ], @@ -2284,9 +2180,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", - "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.26.0.tgz", + "integrity": "sha512-0QfciUDFryD39QoSPUDshj4uNEjQhp73+3pbSAaxjV2qGOEDsM67P7KbJq7LzHoVl46oqhIhJ1S+skKGR7lMXA==", "cpu": [ "x64" ], @@ -2301,9 +2197,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", - "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.26.0.tgz", + "integrity": "sha512-vmAK+nHhIZWImwJ3RNw9hX3fU4UGN/OqbSE0imqljNbUQC3GvVJ1jpwYoTfD6mmXmQaxdJY6Hn4jQbLGJKg5Yw==", "cpu": [ "arm64" ], @@ -2318,9 +2214,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", - "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.26.0.tgz", + "integrity": "sha512-GPXF7RMkJ7o9bTyUsnyNtrFMqgM3X+uM/LWw4CeHIjqc32fm0Ir6jKDnWHpj8xHFstgWDUYseSABK9KCkHGnpg==", "cpu": [ "x64" ], @@ -2335,9 +2231,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", - "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.26.0.tgz", + "integrity": "sha512-nUHZ5jEYqbBthbiBksbmHTlbb5eElyVfs/s1iHQ8rLBq1eWsd5maOnDpCocw1OM8kFK747d1Xms8dXJHtduxSw==", "cpu": [ "arm64" ], @@ -2352,9 +2248,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", - "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.26.0.tgz", + "integrity": "sha512-TMg3KCTCYYaVO+R6P5mSORhcNDDlemUVnUbb8QkboUtOhb5JWKAzd5uMIMECJQOxHZ/R+N8HHtDF5ylzLfMiLw==", "cpu": [ "x64" ], @@ -2369,9 +2265,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", - "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.26.0.tgz", + "integrity": "sha512-apqYgoAUd6ZCb9Phcs8zN32q6l0ZQzQBdVXOofa6WvHDlSOhwCWgSfVQabGViThS40Y1NA4SCvQickgZMFZRlA==", "cpu": [ "arm64" ], @@ -2386,9 +2282,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", - "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.26.0.tgz", + "integrity": "sha512-FGJAcImbJNZzLWu7U6WB0iKHl4RuY4TsXEwxJPl9UZLS47agIZuILZEX3Pagfw7I4J3ddflomt9f0apfaJSbaw==", "cpu": [ "ia32" ], @@ -2403,9 +2299,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", - "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.26.0.tgz", + "integrity": "sha512-WAckBKaVnmFqbEhbymrPK7M086DQMpL1XoRbpmN0iW8k5JSXjDRQBhcZNa0VweItknLq9eAeCL34jK7/CDcw7A==", "cpu": [ "x64" ], @@ -2866,9 +2762,9 @@ } }, "node_modules/@hono/node-server": { - "version": "1.19.9", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz", - "integrity": "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==", + "version": "1.19.8", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.8.tgz", + "integrity": "sha512-0/g2lIOPzX8f3vzW1ggQgvG5mjtFBDBHFAzI5SFAi2DzSqS9luJwqg9T6O/gKYLi+inS7eNxBeIFkkghIPvrMA==", "dev": true, "license": "MIT", "engines": { @@ -3463,14 +3359,14 @@ } }, "node_modules/@inquirer/confirm": { - "version": "5.1.21", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", - "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", + "version": "5.1.19", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.19.tgz", + "integrity": "sha512-wQNz9cfcxrtEnUyG5PndC8g3gZ7lGDBzmWiXZkX8ot3vfZ+/BLjR8EvyGX4YzQLeVqtAlY/YScZpW7CW8qMoDQ==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^10.3.2", - "@inquirer/type": "^3.0.10" + "@inquirer/core": "^10.3.0", + "@inquirer/type": "^3.0.9" }, "engines": { "node": ">=18" @@ -3658,22 +3554,22 @@ } }, "node_modules/@inquirer/prompts": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.10.1.tgz", - "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.9.0.tgz", + "integrity": "sha512-X7/+dG9SLpSzRkwgG5/xiIzW0oMrV3C0HOa7YHG1WnrLK+vCQHfte4k/T80059YBdei29RBC3s+pSMvPJDU9/A==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/checkbox": "^4.3.2", - "@inquirer/confirm": "^5.1.21", - "@inquirer/editor": "^4.2.23", - "@inquirer/expand": "^4.0.23", - "@inquirer/input": "^4.3.1", - "@inquirer/number": "^3.0.23", - "@inquirer/password": "^4.0.23", - "@inquirer/rawlist": "^4.1.11", - "@inquirer/search": "^3.2.2", - "@inquirer/select": "^4.4.2" + "@inquirer/checkbox": "^4.3.0", + "@inquirer/confirm": "^5.1.19", + "@inquirer/editor": "^4.2.21", + "@inquirer/expand": "^4.0.21", + "@inquirer/input": "^4.2.5", + "@inquirer/number": "^3.0.21", + "@inquirer/password": "^4.0.21", + "@inquirer/rawlist": "^4.1.9", + "@inquirer/search": "^3.2.0", + "@inquirer/select": "^4.4.0" }, "engines": { "node": ">=18" @@ -3800,80 +3696,6 @@ "node": "20 || >=22" } }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/@isaacs/fs-minipass": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", @@ -4021,9 +3843,9 @@ } }, "node_modules/@lmdb/lmdb-darwin-arm64": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.4.4.tgz", - "integrity": "sha512-XaKL705gDWd6XVls3ATDj13ZdML/LqSIxwgnYpG8xTzH2ifArx8fMMDdvqGE/Emd+W6R90W2fveZcJ0AyS8Y0w==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.4.3.tgz", + "integrity": "sha512-zR6Y45VNtW5s+A+4AyhrJk0VJKhXdkLhrySCpCu7PSdnakebsOzNxf58p5Xoq66vOSuueGAxlqDAF49HwdrSTQ==", "cpu": [ "arm64" ], @@ -4035,9 +3857,9 @@ ] }, "node_modules/@lmdb/lmdb-darwin-x64": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.4.4.tgz", - "integrity": "sha512-GPHGEVcwJlkD01GmIr7B4kvbIcUDS2+kBadVEd7lU4can1RZaZQLDDBJRrrNfS2Kavvl0VLI/cMv7UASAXGrww==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.4.3.tgz", + "integrity": "sha512-nfGm5pQksBGfaj9uMbjC0YyQreny/Pl7mIDtHtw6g7WQuCgeLullr9FNRsYyKplaEJBPrCVpEjpAznxTBIrXBw==", "cpu": [ "x64" ], @@ -4049,9 +3871,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-arm": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.4.4.tgz", - "integrity": "sha512-cmev5/dZr5ACKri9f6GU6lZCXTjMhV72xujlbOhFCgFXrt4W0TxGsmY8kA1BITvH60JBKE50cSxsiulybAbrrw==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.4.3.tgz", + "integrity": "sha512-Kjqomp7i0rgSbYSUmv9JnXpS55zYT/YcW3Bdf9oqOTjcH0/8tFAP8MLhu/i9V2pMKIURDZk63Ww49DTK0T3c/Q==", "cpu": [ "arm" ], @@ -4063,9 +3885,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-arm64": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.4.4.tgz", - "integrity": "sha512-mALqr7DE42HsiwVTKpQWxacjHoJk+e9p00RWIJqTACh/hpucxp/0lK/XMh5XzWnU/TDCZLukq1+vNqnNumTP/Q==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.4.3.tgz", + "integrity": "sha512-uX9eaPqWb740wg5D3TCvU/js23lSRSKT7lJrrQ8IuEG/VLgpPlxO3lHDywU44yFYdGS7pElBn6ioKFKhvALZlw==", "cpu": [ "arm64" ], @@ -4077,9 +3899,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-x64": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.4.4.tgz", - "integrity": "sha512-QjLs8OcmCNcraAcLoZyFlo0atzBJniQLLwhtR+ymQqS5kLYpV5RqwriL87BW+ZiR9ZiGgZx3evrz5vnWPtJ1fQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.4.3.tgz", + "integrity": "sha512-7/8l20D55CfwdMupkc3fNxNJdn4bHsti2X0cp6PwiXlLeSFvAfWs5kCCx+2Cyje4l4GtN//LtKWjTru/9hDJQg==", "cpu": [ "x64" ], @@ -4091,9 +3913,9 @@ ] }, "node_modules/@lmdb/lmdb-win32-arm64": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-arm64/-/lmdb-win32-arm64-3.4.4.tgz", - "integrity": "sha512-tr/pwHDlZ33forLGAr0tI04cRmP4SgF93yHbb+2zvZiDEyln5yMHhbKDySxY66aUOkhvBvTuHq9q/3YmTj6ZHQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-arm64/-/lmdb-win32-arm64-3.4.3.tgz", + "integrity": "sha512-yWVR0e5Gl35EGJBsAuqPOdjtUYuN8CcTLKrqpQFoM+KsMadViVCulhKNhkcjSGJB88Am5bRPjMro4MBB9FS23Q==", "cpu": [ "arm64" ], @@ -4105,9 +3927,9 @@ ] }, "node_modules/@lmdb/lmdb-win32-x64": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.4.4.tgz", - "integrity": "sha512-KRzfocJzB/mgoTCqnMawuLSKheHRVTqWfSmouIgYpFs6Hx4zvZSvsZKSCEb5gHmICy7qsx9l06jk3MFTtiFVAQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.4.3.tgz", + "integrity": "sha512-1JdBkcO0Vrua4LUgr4jAe4FUyluwCeq/pDkBrlaVjX3/BBWP1TzVjCL+TibWNQtPAL1BITXPAhlK5Ru4FBd/hg==", "cpu": [ "x64" ], @@ -4707,8 +4529,31 @@ "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/@npmcli/git/node_modules/isexe": { - "version": "3.1.1", + "node_modules/@npmcli/git/node_modules/@npmcli/promise-spawn": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-9.0.1.tgz", + "integrity": "sha512-OLUaoqBuyxeTqUvjA3FZFiXUfYC1alp3Sa99gW3EUDz3tZ3CbXDdcZ7qWKBzicrJleIgucoWamWH1saAmH/l2Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "which": "^6.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/git/node_modules/ini": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz", + "integrity": "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/@npmcli/git/node_modules/isexe": { + "version": "3.1.1", "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", "dev": true, @@ -4727,6 +4572,16 @@ "node": "20 || >=22" } }, + "node_modules/@npmcli/git/node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/@npmcli/git/node_modules/which": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/which/-/which-6.0.0.tgz", @@ -4744,20 +4599,20 @@ } }, "node_modules/@npmcli/installed-package-contents": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-4.0.0.tgz", - "integrity": "sha512-yNyAdkBxB72gtZ4GrwXCM0ZUedo9nIbOMKfGjt6Cu6DXf0p8y1PViZAKDC8q8kv/fufx0WTjRBdSlyrvnP7hmA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-3.0.0.tgz", + "integrity": "sha512-fkxoPuFGvxyrH+OQzyTkX2LUEamrF4jZSmxjAtPPHHGO0dqsQ8tTKjnIS8SAnPHdk2I03BDtSMR5K/4loKg79Q==", "dev": true, "license": "ISC", "dependencies": { - "npm-bundled": "^5.0.0", - "npm-normalize-package-bin": "^5.0.0" + "npm-bundled": "^4.0.0", + "npm-normalize-package-bin": "^4.0.0" }, "bin": { "installed-package-contents": "bin/index.js" }, "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/node-gyp": { @@ -4850,17 +4705,27 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@npmcli/package-json/node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/@npmcli/promise-spawn": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-9.0.1.tgz", - "integrity": "sha512-OLUaoqBuyxeTqUvjA3FZFiXUfYC1alp3Sa99gW3EUDz3tZ3CbXDdcZ7qWKBzicrJleIgucoWamWH1saAmH/l2Q==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-8.0.3.tgz", + "integrity": "sha512-Yb00SWaL4F8w+K8YGhQ55+xE4RUNdMHV43WZGsiTM92gS+lC0mGsn7I4hLug7pbao035S6bj3Y3w0cUNGLfmkg==", "dev": true, "license": "ISC", "dependencies": { - "which": "^6.0.0" + "which": "^5.0.0" }, "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/promise-spawn/node_modules/isexe": { @@ -4874,9 +4739,9 @@ } }, "node_modules/@npmcli/promise-spawn/node_modules/which": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-6.0.0.tgz", - "integrity": "sha512-f+gEpIKMR9faW/JgAgPK1D7mekkFoqbmiwvNzuhsHetni20QSgzg9Vhn0g2JSJkkfehQnqdUAx7/e15qS1lPxg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "dev": true, "license": "ISC", "dependencies": { @@ -4886,7 +4751,7 @@ "node-which": "bin/which.js" }, "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/redact": { @@ -4917,6 +4782,19 @@ "node": "^20.17.0 || >=22.9.0" } }, + "node_modules/@npmcli/run-script/node_modules/@npmcli/promise-spawn": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-9.0.1.tgz", + "integrity": "sha512-OLUaoqBuyxeTqUvjA3FZFiXUfYC1alp3Sa99gW3EUDz3tZ3CbXDdcZ7qWKBzicrJleIgucoWamWH1saAmH/l2Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "which": "^6.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/@npmcli/run-script/node_modules/isexe": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", @@ -4927,6 +4805,16 @@ "node": ">=16" } }, + "node_modules/@npmcli/run-script/node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/@npmcli/run-script/node_modules/which": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/which/-/which-6.0.0.tgz", @@ -4951,9 +4839,9 @@ "license": "MIT" }, "node_modules/@oxc-project/types": { - "version": "0.106.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.106.0.tgz", - "integrity": "sha512-QdsH3rZq480VnOHSHgPYOhjL8O8LBdcnSjM408BpPCCUc0JYYZPG9Gafl9i3OcGk/7137o+gweb4cCv3WAUykg==", + "version": "0.96.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.96.0.tgz", + "integrity": "sha512-r/xkmoXA0xEpU6UGtn18CNVjXH6erU3KCpCDbpLmbVxBFor1U9MqN5Z2uMmCHJuXjJzlnDR+hWY+yPoLo8oHDw==", "dev": true, "license": "MIT", "funding": { @@ -5369,17 +5257,6 @@ "license": "MIT", "optional": true }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@polka/url": { "version": "1.0.0-next.29", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", @@ -5485,9 +5362,9 @@ } }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.0-beta.58", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-beta.58.tgz", - "integrity": "sha512-mWj5eE4Qc8TbPdGGaaLvBb9XfDPvE1EmZkJQgiGKwchkWH4oAJcRAKMTw7ZHnb1L+t7Ah41sBkAecaIsuUgsug==", + "version": "1.0.0-beta.47", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-beta.47.tgz", + "integrity": "sha512-vPP9/MZzESh9QtmvQYojXP/midjgkkc1E4AdnPPAzQXo668ncHJcVLKjJKzoBdsQmaIvNjrMdsCwES8vTQHRQw==", "cpu": [ "arm64" ], @@ -5502,9 +5379,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.0-beta.58", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-beta.58.tgz", - "integrity": "sha512-wFxUymI/5R8bH8qZFYDfAxAN9CyISEIYke+95oZPiv6EWo88aa5rskjVcCpKA532R+klFmdqjbbaD56GNmTF4Q==", + "version": "1.0.0-beta.47", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-beta.47.tgz", + "integrity": "sha512-Lc3nrkxeaDVCVl8qR3qoxh6ltDZfkQ98j5vwIr5ALPkgjZtDK4BGCrrBoLpGVMg+csWcaqUbwbKwH5yvVa0oOw==", "cpu": [ "arm64" ], @@ -5519,9 +5396,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.0-beta.58", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-beta.58.tgz", - "integrity": "sha512-ybp3MkPj23VDV9PhtRwdU5qrGhlViWRV5BjKwO6epaSlUD5lW0WyY+roN3ZAzbma/9RrMTgZ/a/gtQq8YXOcqw==", + "version": "1.0.0-beta.47", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-beta.47.tgz", + "integrity": "sha512-eBYxQDwP0O33plqNVqOtUHqRiSYVneAknviM5XMawke3mwMuVlAsohtOqEjbCEl/Loi/FWdVeks5WkqAkzkYWQ==", "cpu": [ "x64" ], @@ -5536,9 +5413,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.0-beta.58", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-beta.58.tgz", - "integrity": "sha512-Evxj3yh7FWvyklUYZa0qTVT9N2zX9TPDqGF056hl8hlCZ9/ndQ2xMv6uw9PD1VlLpukbsqL+/C6M0qwipL0QMg==", + "version": "1.0.0-beta.47", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-beta.47.tgz", + "integrity": "sha512-Ns+kgp2+1Iq/44bY/Z30DETUSiHY7ZuqaOgD5bHVW++8vme9rdiWsN4yG4rRPXkdgzjvQ9TDHmZZKfY4/G11AA==", "cpu": [ "x64" ], @@ -5553,9 +5430,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.0-beta.58", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-beta.58.tgz", - "integrity": "sha512-tYeXprDOrEgVHUbPXH6MPso4cM/c6RTkmJNICMQlYdki4hGMh92aj3yU6CKs+4X5gfG0yj5kVUw/L4M685SYag==", + "version": "1.0.0-beta.47", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-beta.47.tgz", + "integrity": "sha512-4PecgWCJhTA2EFOlptYJiNyVP2MrVP4cWdndpOu3WmXqWqZUmSubhb4YUAIxAxnXATlGjC1WjxNPhV7ZllNgdA==", "cpu": [ "arm" ], @@ -5570,9 +5447,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.0-beta.58", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-beta.58.tgz", - "integrity": "sha512-N78vmZzP6zG967Ohr+MasCjmKtis0geZ1SOVmxrA0/bklTQSzH5kHEjW5Qn+i1taFno6GEre1E40v0wuWsNOQw==", + "version": "1.0.0-beta.47", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-beta.47.tgz", + "integrity": "sha512-CyIunZ6D9U9Xg94roQI1INt/bLkOpPsZjZZkiaAZ0r6uccQdICmC99M9RUPlMLw/qg4yEWLlQhG73W/mG437NA==", "cpu": [ "arm64" ], @@ -5587,9 +5464,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.0-beta.58", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-beta.58.tgz", - "integrity": "sha512-l+p4QVtG72C7wI2SIkNQw/KQtSjuYwS3rV6AKcWrRBF62ClsFUcif5vLaZIEbPrCXu5OFRXigXFJnxYsVVZqdQ==", + "version": "1.0.0-beta.47", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-beta.47.tgz", + "integrity": "sha512-doozc/Goe7qRCSnzfJbFINTHsMktqmZQmweull6hsZZ9sjNWQ6BWQnbvOlfZJe4xE5NxM1NhPnY5Giqnl3ZrYQ==", "cpu": [ "arm64" ], @@ -5604,9 +5481,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.0-beta.58", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-beta.58.tgz", - "integrity": "sha512-urzJX0HrXxIh0FfxwWRjfPCMeInU9qsImLQxHBgLp5ivji1EEUnOfux8KxPPnRQthJyneBrN2LeqUix9DYrNaQ==", + "version": "1.0.0-beta.47", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-beta.47.tgz", + "integrity": "sha512-fodvSMf6Aqwa0wEUSTPewmmZOD44rc5Tpr5p9NkwQ6W1SSpUKzD3SwpJIgANDOhwiYhDuiIaYPGB7Ujkx1q0UQ==", "cpu": [ "x64" ], @@ -5621,9 +5498,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.0-beta.58", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-beta.58.tgz", - "integrity": "sha512-7ijfVK3GISnXIwq/1FZo+KyAUJjL3kWPJ7rViAL6MWeEBhEgRzJ0yEd9I8N9aut8Y8ab+EKFJyRNMWZuUBwQ0A==", + "version": "1.0.0-beta.47", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-beta.47.tgz", + "integrity": "sha512-Rxm5hYc0mGjwLh5sjlGmMygxAaV2gnsx7CNm2lsb47oyt5UQyPDZf3GP/ct8BEcwuikdqzsrrlIp8+kCSvMFNQ==", "cpu": [ "x64" ], @@ -5638,9 +5515,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.0-beta.58", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-beta.58.tgz", - "integrity": "sha512-/m7sKZCS+cUULbzyJTIlv8JbjNohxbpAOA6cM+lgWgqVzPee3U6jpwydrib328JFN/gF9A99IZEnuGYqEDJdww==", + "version": "1.0.0-beta.47", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-beta.47.tgz", + "integrity": "sha512-YakuVe+Gc87jjxazBL34hbr8RJpRuFBhun7NEqoChVDlH5FLhLXjAPHqZd990TVGVNkemourf817Z8u2fONS8w==", "cpu": [ "arm64" ], @@ -5655,9 +5532,9 @@ } }, "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.0-beta.58", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-beta.58.tgz", - "integrity": "sha512-6SZk7zMgv+y3wFFQ9qE5P9NnRHcRsptL1ypmudD26PDY+PvFCvfHRkJNfclWnvacVGxjowr7JOL3a9fd1wWhUw==", + "version": "1.0.0-beta.47", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-beta.47.tgz", + "integrity": "sha512-ak2GvTFQz3UAOw8cuQq8pWE+TNygQB6O47rMhvevvTzETh7VkHRFtRUwJynX5hwzFvQMP6G0az5JrBGuwaMwYQ==", "cpu": [ "wasm32" ], @@ -5665,16 +5542,16 @@ "license": "MIT", "optional": true, "dependencies": { - "@napi-rs/wasm-runtime": "^1.1.1" + "@napi-rs/wasm-runtime": "^1.0.7" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.0-beta.58", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-beta.58.tgz", - "integrity": "sha512-sFqfYPnBZ6xBhMkadB7UD0yjEDRvs7ipR3nCggblN+N4ODCXY6qhg/bKL39+W+dgQybL7ErD4EGERVbW9DAWvg==", + "version": "1.0.0-beta.47", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-beta.47.tgz", + "integrity": "sha512-o5BpmBnXU+Cj+9+ndMcdKjhZlPb79dVPBZnWwMnI4RlNSSq5yOvFZqvfPYbyacvnW03Na4n5XXQAPhu3RydZ0w==", "cpu": [ "arm64" ], @@ -5688,10 +5565,27 @@ "node": "^20.19.0 || >=22.12.0" } }, + "node_modules/@rolldown/binding-win32-ia32-msvc": { + "version": "1.0.0-beta.47", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.0.0-beta.47.tgz", + "integrity": "sha512-FVOmfyYehNE92IfC9Kgs913UerDog2M1m+FADJypKz0gmRg3UyTt4o1cZMCAl7MiR89JpM9jegNO1nXuP1w1vw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.0-beta.58", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-beta.58.tgz", - "integrity": "sha512-AnFWJdAqB8+IDPcGrATYs67Kik/6tnndNJV2jGRmwlbeNiQQ8GhRJU8ETRlINfII0pqi9k4WWLnb00p1QCxw/Q==", + "version": "1.0.0-beta.47", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-beta.47.tgz", + "integrity": "sha512-by/70F13IUE101Bat0oeH8miwWX5mhMFPk1yjCdxoTNHTyTdLgb0THNaebRM6AP7Kz+O3O2qx87sruYuF5UxHg==", "cpu": [ "x64" ], @@ -5706,9 +5600,9 @@ } }, "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.58", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.58.tgz", - "integrity": "sha512-qWhDs6yFGR5xDfdrwiSa3CWGIHxD597uGE/A9xGqytBjANvh4rLCTTkq7szhMV4+Ygh+PMS90KVJ8xWG/TkX4w==", + "version": "1.0.0-beta.47", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.47.tgz", + "integrity": "sha512-8QagwMH3kNCuzD8EWL8R2YPW5e4OrHNSAHRFDdmFqEwEaD/KcNKjVoumo+gP2vW5eKB2UPbM6vTYiGZX0ixLnw==", "dev": true, "license": "MIT" }, @@ -5764,9 +5658,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.3.tgz", - "integrity": "sha512-qyX8+93kK/7R5BEXPC2PjUt0+fS/VO2BVHjEHyIEWiYn88rcRBHmdLgoJjktBltgAf+NY7RfCGB1SoyKS/p9kg==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz", + "integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==", "cpu": [ "arm" ], @@ -5778,9 +5672,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.3.tgz", - "integrity": "sha512-6sHrL42bjt5dHQzJ12Q4vMKfN+kUnZ0atHHnv4V0Wd9JMTk7FDzSY35+7qbz3ypQYMBPANbpGK7JpnWNnhGt8g==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz", + "integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==", "cpu": [ "arm64" ], @@ -5792,9 +5686,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.3.tgz", - "integrity": "sha512-1ht2SpGIjEl2igJ9AbNpPIKzb1B5goXOcmtD0RFxnwNuMxqkR6AUaaErZz+4o+FKmzxcSNBOLrzsICZVNYa1Rw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz", + "integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==", "cpu": [ "arm64" ], @@ -5806,9 +5700,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.3.tgz", - "integrity": "sha512-FYZ4iVunXxtT+CZqQoPVwPhH7549e/Gy7PIRRtq4t5f/vt54pX6eG9ebttRH6QSH7r/zxAFA4EZGlQ0h0FvXiA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz", + "integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==", "cpu": [ "x64" ], @@ -5820,9 +5714,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.3.tgz", - "integrity": "sha512-M/mwDCJ4wLsIgyxv2Lj7Len+UMHd4zAXu4GQ2UaCdksStglWhP61U3uowkaYBQBhVoNpwx5Hputo8eSqM7K82Q==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz", + "integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==", "cpu": [ "arm64" ], @@ -5834,9 +5728,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.3.tgz", - "integrity": "sha512-5jZT2c7jBCrMegKYTYTpni8mg8y3uY8gzeq2ndFOANwNuC/xJbVAoGKR9LhMDA0H3nIhvaqUoBEuJoICBudFrA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz", + "integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==", "cpu": [ "x64" ], @@ -5848,9 +5742,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.3.tgz", - "integrity": "sha512-YeGUhkN1oA+iSPzzhEjVPS29YbViOr8s4lSsFaZKLHswgqP911xx25fPOyE9+khmN6W4VeM0aevbDp4kkEoHiA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz", + "integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==", "cpu": [ "arm" ], @@ -5862,9 +5756,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.3.tgz", - "integrity": "sha512-eo0iOIOvcAlWB3Z3eh8pVM8hZ0oVkK3AjEM9nSrkSug2l15qHzF3TOwT0747omI6+CJJvl7drwZepT+re6Fy/w==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz", + "integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==", "cpu": [ "arm" ], @@ -5876,9 +5770,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.3.tgz", - "integrity": "sha512-DJay3ep76bKUDImmn//W5SvpjRN5LmK/ntWyeJs/dcnwiiHESd3N4uteK9FDLf0S0W8E6Y0sVRXpOCoQclQqNg==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz", + "integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==", "cpu": [ "arm64" ], @@ -5890,9 +5784,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.3.tgz", - "integrity": "sha512-BKKWQkY2WgJ5MC/ayvIJTHjy0JUGb5efaHCUiG/39sSUvAYRBaO3+/EK0AZT1RF3pSj86O24GLLik9mAYu0IJg==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz", + "integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==", "cpu": [ "arm64" ], @@ -5904,9 +5798,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.3.tgz", - "integrity": "sha512-Q9nVlWtKAG7ISW80OiZGxTr6rYtyDSkauHUtvkQI6TNOJjFvpj4gcH+KaJihqYInnAzEEUetPQubRwHef4exVg==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz", + "integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==", "cpu": [ "loong64" ], @@ -5918,9 +5812,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.3.tgz", - "integrity": "sha512-2H5LmhzrpC4fFRNwknzmmTvvyJPHwESoJgyReXeFoYYuIDfBhP29TEXOkCJE/KxHi27mj7wDUClNq78ue3QEBQ==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz", + "integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==", "cpu": [ "loong64" ], @@ -5932,9 +5826,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.3.tgz", - "integrity": "sha512-9S542V0ie9LCTznPYlvaeySwBeIEa7rDBgLHKZ5S9DBgcqdJYburabm8TqiqG6mrdTzfV5uttQRHcbKff9lWtA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz", + "integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==", "cpu": [ "ppc64" ], @@ -5946,9 +5840,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.3.tgz", - "integrity": "sha512-ukxw+YH3XXpcezLgbJeasgxyTbdpnNAkrIlFGDl7t+pgCxZ89/6n1a+MxlY7CegU+nDgrgdqDelPRNQ/47zs0g==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz", + "integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==", "cpu": [ "ppc64" ], @@ -5960,9 +5854,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.3.tgz", - "integrity": "sha512-Iauw9UsTTvlF++FhghFJjqYxyXdggXsOqGpFBylaRopVpcbfyIIsNvkf9oGwfgIcf57z3m8+/oSYTo6HutBFNw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz", + "integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==", "cpu": [ "riscv64" ], @@ -5974,9 +5868,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.3.tgz", - "integrity": "sha512-3OqKAHSEQXKdq9mQ4eajqUgNIK27VZPW3I26EP8miIzuKzCJ3aW3oEn2pzF+4/Hj/Moc0YDsOtBgT5bZ56/vcA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz", + "integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==", "cpu": [ "riscv64" ], @@ -5988,9 +5882,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.3.tgz", - "integrity": "sha512-0CM8dSVzVIaqMcXIFej8zZrSFLnGrAE8qlNbbHfTw1EEPnFTg1U1ekI0JdzjPyzSfUsHWtodilQQG/RA55berA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz", + "integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==", "cpu": [ "s390x" ], @@ -6002,9 +5896,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.3.tgz", - "integrity": "sha512-+fgJE12FZMIgBaKIAGd45rxf+5ftcycANJRWk8Vz0NnMTM5rADPGuRFTYar+Mqs560xuART7XsX2lSACa1iOmQ==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz", + "integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==", "cpu": [ "x64" ], @@ -6016,9 +5910,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.3.tgz", - "integrity": "sha512-tMD7NnbAolWPzQlJQJjVFh/fNH3K/KnA7K8gv2dJWCwwnaK6DFCYST1QXYWfu5V0cDwarWC8Sf/cfMHniNq21A==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz", + "integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==", "cpu": [ "x64" ], @@ -6030,9 +5924,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.3.tgz", - "integrity": "sha512-u5KsqxOxjEeIbn7bUK1MPM34jrnPwjeqgyin4/N6e/KzXKfpE9Mi0nCxcQjaM9lLmPcHmn/xx1yOjgTMtu1jWQ==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz", + "integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==", "cpu": [ "x64" ], @@ -6044,9 +5938,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.3.tgz", - "integrity": "sha512-vo54aXwjpTtsAnb3ca7Yxs9t2INZg7QdXN/7yaoG7nPGbOBXYXQY41Km+S1Ov26vzOAzLcAjmMdjyEqS1JkVhw==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz", + "integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==", "cpu": [ "arm64" ], @@ -6058,9 +5952,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.3.tgz", - "integrity": "sha512-HI+PIVZ+m+9AgpnY3pt6rinUdRYrGHvmVdsNQ4odNqQ/eRF78DVpMR7mOq7nW06QxpczibwBmeQzB68wJ+4W4A==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz", + "integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==", "cpu": [ "arm64" ], @@ -6072,9 +5966,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.3.tgz", - "integrity": "sha512-vRByotbdMo3Wdi+8oC2nVxtc3RkkFKrGaok+a62AT8lz/YBuQjaVYAS5Zcs3tPzW43Vsf9J0wehJbUY5xRSekA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz", + "integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==", "cpu": [ "ia32" ], @@ -6086,9 +5980,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.3.tgz", - "integrity": "sha512-POZHq7UeuzMJljC5NjKi8vKMFN6/5EOqcX1yGntNLp7rUTpBAXQ1hW8kWPFxYLv07QMcNM75xqVLGPWQq6TKFA==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz", + "integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==", "cpu": [ "x64" ], @@ -6100,9 +5994,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.3.tgz", - "integrity": "sha512-aPFONczE4fUFKNXszdvnd2GqKEYQdV5oEsIbKPujJmWlCI9zEsv1Otig8RKK+X9bed9gFUN6LAeN4ZcNuu4zjg==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz", + "integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==", "cpu": [ "x64" ], @@ -6114,9 +6008,9 @@ ] }, "node_modules/@rollup/wasm-node": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/@rollup/wasm-node/-/wasm-node-4.55.3.tgz", - "integrity": "sha512-np0RxhlXyapxBvMTf/FLlCn/Aw9HIoXBIFholBKmRUmmjlFl1IHgI8T9SKQPCeDdsa0xCFvhcSFSwTHTbiXFvg==", + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/@rollup/wasm-node/-/wasm-node-4.55.1.tgz", + "integrity": "sha512-GD+BSGH7+hVtNreVwv2JVxKImAdaDDrT9Ev0Bbr9CTATPjXjp7pQlRAqyZqNW3RGY37qL/RkF0HyO9ptJDU2pQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6134,14 +6028,14 @@ } }, "node_modules/@schematics/angular": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-21.1.0.tgz", - "integrity": "sha512-gXf3gO5SeU+tiPHxXeQvdbua4C4/V+KH43JH2PYPxaNCD2HGo1uV0pfyNSNgcVF21voKlbAQ13YRrNDh7z5Kig==", + "version": "21.0.5", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-21.0.5.tgz", + "integrity": "sha512-uNBIilq5bGnln3D7Nbm3/K+Ot++eGj4rygU0DCw//IZiTQU/iSyF3UAsN++iRetu/OMs+97T/RoGPjD22ryiZg==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "21.1.0", - "@angular-devkit/schematics": "21.1.0", + "@angular-devkit/core": "21.0.5", + "@angular-devkit/schematics": "21.0.5", "jsonc-parser": "3.3.1" }, "engines": { @@ -6268,6 +6162,16 @@ "node": "^20.17.0 || >=22.9.0" } }, + "node_modules/@sigstore/sign/node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/@sigstore/tuf": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-4.0.1.tgz", @@ -6314,13 +6218,6 @@ "node": ">=6" } }, - "node_modules/@socket.io/component-emitter": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", - "dev": true, - "license": "MIT" - }, "node_modules/@standard-schema/spec": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", @@ -6437,20 +6334,21 @@ "@types/node": "*" } }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*" + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" } }, - "node_modules/@types/cors": { - "version": "2.8.19", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", - "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", "dev": true, "license": "MIT", "dependencies": { @@ -6467,10 +6365,10 @@ "@types/ms": "*" } }, - "node_modules/@types/esrecurse": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", - "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "dev": true, "license": "MIT" }, @@ -6529,23 +6427,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/jasmine": { - "version": "5.1.15", - "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-5.1.15.tgz", - "integrity": "sha512-ZAC8KjmV2MJxbNTrwXFN+HKeajpXQZp6KpPiR6Aa4XvaEnjP6qh23lL/Rqb7AYzlp3h/rcwDrQ7Gg7q28cQTQg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/jasminewd2": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.13.tgz", - "integrity": "sha512-aJ3wj8tXMpBrzQ5ghIaqMisD8C3FIrcO6sDKHqFbuqAsI7yOxj0fA7MrRCPLZHIVUjERIwsMmGn/vB0UQ9u0Hg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/jasmine": "*" - } - }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -6580,9 +6461,9 @@ } }, "node_modules/@types/node": { - "version": "20.19.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", - "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "version": "20.19.28", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.28.tgz", + "integrity": "sha512-VyKBr25BuFDzBFCK5sUM6ZXiWfqgCTwTAOK8qzGV/m9FCirXYDlmczJ+d5dXBAQALGCdRRdbteKYfJ84NGEusw==", "dev": true, "license": "MIT", "dependencies": { @@ -6685,17 +6566,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.53.1.tgz", - "integrity": "sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.52.0.tgz", + "integrity": "sha512-okqtOgqu2qmZJ5iN4TWlgfF171dZmx2FzdOv2K/ixL2LZWDStL8+JgQerI2sa8eAEfoydG9+0V96m7V+P8yE1Q==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.53.1", - "@typescript-eslint/type-utils": "8.53.1", - "@typescript-eslint/utils": "8.53.1", - "@typescript-eslint/visitor-keys": "8.53.1", + "@typescript-eslint/scope-manager": "8.52.0", + "@typescript-eslint/type-utils": "8.52.0", + "@typescript-eslint/utils": "8.52.0", + "@typescript-eslint/visitor-keys": "8.52.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" @@ -6708,22 +6589,22 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.53.1", + "@typescript-eslint/parser": "^8.52.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.53.1.tgz", - "integrity": "sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.52.0.tgz", + "integrity": "sha512-iIACsx8pxRnguSYhHiMn2PvhvfpopO9FXHyn1mG5txZIsAaB6F0KwbFnUQN3KCiG3Jcuad/Cao2FAs1Wp7vAyg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.53.1", - "@typescript-eslint/types": "8.53.1", - "@typescript-eslint/typescript-estree": "8.53.1", - "@typescript-eslint/visitor-keys": "8.53.1", + "@typescript-eslint/scope-manager": "8.52.0", + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/typescript-estree": "8.52.0", + "@typescript-eslint/visitor-keys": "8.52.0", "debug": "^4.4.3" }, "engines": { @@ -6739,14 +6620,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.53.1.tgz", - "integrity": "sha512-WYC4FB5Ra0xidsmlPb+1SsnaSKPmS3gsjIARwbEkHkoWloQmuzcfypljaJcR78uyLA1h8sHdWWPHSLDI+MtNog==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.52.0.tgz", + "integrity": "sha512-xD0MfdSdEmeFa3OmVqonHi+Cciab96ls1UhIF/qX/O/gPu5KXD0bY9lu33jj04fjzrXHcuvjBcBC+D3SNSadaw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.53.1", - "@typescript-eslint/types": "^8.53.1", + "@typescript-eslint/tsconfig-utils": "^8.52.0", + "@typescript-eslint/types": "^8.52.0", "debug": "^4.4.3" }, "engines": { @@ -6761,14 +6642,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.53.1.tgz", - "integrity": "sha512-Lu23yw1uJMFY8cUeq7JlrizAgeQvWugNQzJp8C3x8Eo5Jw5Q2ykMdiiTB9vBVOOUBysMzmRRmUfwFrZuI2C4SQ==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.52.0.tgz", + "integrity": "sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.1", - "@typescript-eslint/visitor-keys": "8.53.1" + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/visitor-keys": "8.52.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6779,9 +6660,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.53.1.tgz", - "integrity": "sha512-qfvLXS6F6b1y43pnf0pPbXJ+YoXIC7HKg0UGZ27uMIemKMKA6XH2DTxsEDdpdN29D+vHV07x/pnlPNVLhdhWiA==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.52.0.tgz", + "integrity": "sha512-jl+8fzr/SdzdxWJznq5nvoI7qn2tNYV/ZBAEcaFMVXf+K6jmXvAFrgo/+5rxgnL152f//pDEAYAhhBAZGrVfwg==", "dev": true, "license": "MIT", "engines": { @@ -6796,15 +6677,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.53.1.tgz", - "integrity": "sha512-MOrdtNvyhy0rHyv0ENzub1d4wQYKb2NmIqG7qEqPWFW7Mpy2jzFC3pQ2yKDvirZB7jypm5uGjF2Qqs6OIqu47w==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.52.0.tgz", + "integrity": "sha512-JD3wKBRWglYRQkAtsyGz1AewDu3mTc7NtRjR/ceTyGoPqmdS5oCdx/oZMWD5Zuqmo6/MpsYs0wp6axNt88/2EQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.1", - "@typescript-eslint/typescript-estree": "8.53.1", - "@typescript-eslint/utils": "8.53.1", + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/typescript-estree": "8.52.0", + "@typescript-eslint/utils": "8.52.0", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, @@ -6821,9 +6702,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.1.tgz", - "integrity": "sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.52.0.tgz", + "integrity": "sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg==", "dev": true, "license": "MIT", "engines": { @@ -6835,16 +6716,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.53.1.tgz", - "integrity": "sha512-RGlVipGhQAG4GxV1s34O91cxQ/vWiHJTDHbXRr0li2q/BGg3RR/7NM8QDWgkEgrwQYCvmJV9ichIwyoKCQ+DTg==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.52.0.tgz", + "integrity": "sha512-XP3LClsCc0FsTK5/frGjolyADTh3QmsLp6nKd476xNI9CsSsLnmn4f0jrzNoAulmxlmNIpeXuHYeEQv61Q6qeQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.53.1", - "@typescript-eslint/tsconfig-utils": "8.53.1", - "@typescript-eslint/types": "8.53.1", - "@typescript-eslint/visitor-keys": "8.53.1", + "@typescript-eslint/project-service": "8.52.0", + "@typescript-eslint/tsconfig-utils": "8.52.0", + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/visitor-keys": "8.52.0", "debug": "^4.4.3", "minimatch": "^9.0.5", "semver": "^7.7.3", @@ -6863,16 +6744,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.53.1.tgz", - "integrity": "sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.52.0.tgz", + "integrity": "sha512-wYndVMWkweqHpEpwPhwqE2lnD2DxC6WVLupU/DOt/0/v+/+iQbbzO3jOHjmBMnhu0DgLULvOaU4h4pwHYi2oRQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.53.1", - "@typescript-eslint/types": "8.53.1", - "@typescript-eslint/typescript-estree": "8.53.1" + "@typescript-eslint/scope-manager": "8.52.0", + "@typescript-eslint/types": "8.52.0", + "@typescript-eslint/typescript-estree": "8.52.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6887,13 +6768,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.53.1.tgz", - "integrity": "sha512-oy+wV7xDKFPRyNggmXuZQSBzvoLnpmJs+GhzRhPjrxl2b/jIlyjVokzm47CZCDUdXKr2zd7ZLodPfOBpOPyPlg==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.52.0.tgz", + "integrity": "sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/types": "8.52.0", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -6936,124 +6817,358 @@ "vite": "^6.0.0 || ^7.0.0" } }, - "node_modules/@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/a-sync-waterfall": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", - "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", - "dev": true, - "license": "MIT" - }, - "node_modules/abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==", - "dev": true, - "license": "ISC" - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "node_modules/@vitest/browser": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-4.0.17.tgz", + "integrity": "sha512-cgf2JZk2fv5or3efmOrRJe1V9Md89BPgz4ntzbf84yAb+z2hW6niaGFinl9aFzPZ1q3TGfWZQWZ9gXTFThs2Qw==", "dev": true, "license": "MIT", "dependencies": { - "event-target-shim": "^5.0.0" + "@vitest/mocker": "4.0.17", + "@vitest/utils": "4.0.17", + "magic-string": "^0.30.21", + "pixelmatch": "7.1.0", + "pngjs": "^7.0.0", + "sirv": "^3.0.2", + "tinyrainbow": "^3.0.3", + "ws": "^8.18.3" }, - "engines": { - "node": ">=6.5" + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": "4.0.17" } }, - "node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "node_modules/@vitest/browser-playwright": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-4.0.17.tgz", + "integrity": "sha512-CE9nlzslHX6Qz//MVrjpulTC9IgtXTbJ+q7Rx1HD+IeSOWv4NHIRNHPA6dB4x01d9paEqt+TvoqZfmgq40DxEQ==", + "dev": true, "license": "MIT", "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" + "@vitest/browser": "4.0.17", + "@vitest/mocker": "4.0.17", + "tinyrainbow": "^3.0.3" }, - "engines": { - "node": ">= 0.6" + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "playwright": "*", + "vitest": "4.0.17" + }, + "peerDependenciesMeta": { + "playwright": { + "optional": false + } } }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "node_modules/@vitest/browser/node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/@vitest/browser/node_modules/ws": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", "dev": true, "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "node_modules/@vitest/coverage-v8": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.0.17.tgz", + "integrity": "sha512-/6zU2FLGg0jsd+ePZcwHRy3+WpNTBBhDY56P4JTRqUN/Dp6CvOEa9HrikcQ4KfV2b2kAHUFB4dl1SuocWXSFEw==", "dev": true, "license": "MIT", "dependencies": { - "acorn": "^8.11.0" + "@bcoe/v8-coverage": "^1.0.2", + "@vitest/utils": "4.0.17", + "ast-v8-to-istanbul": "^0.3.10", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.2.0", + "magicast": "^0.5.1", + "obug": "^2.1.1", + "std-env": "^3.10.0", + "tinyrainbow": "^3.0.3" }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14" + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "4.0.17", + "vitest": "4.0.17" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "node_modules/@vitest/expect": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.17.tgz", + "integrity": "sha512-mEoqP3RqhKlbmUmntNDDCJeTDavDR+fVYkSOw8qRwJFaW/0/5zA9zFeTrHqNtcmwh6j26yMmwx2PqUDPzt5ZAQ==", "dev": true, "license": "MIT", "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" + "@standard-schema/spec": "^1.0.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.0.17", + "@vitest/utils": "4.0.17", + "chai": "^6.2.1", + "tinyrainbow": "^3.0.3" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "node_modules/@vitest/mocker": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.17.tgz", + "integrity": "sha512-+ZtQhLA3lDh1tI2wxe3yMsGzbp7uuJSWBM1iTIKCbppWTSBN09PUC+L+fyNlQApQoR+Ps8twt2pbSSXg2fQVEQ==", "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" + "@vitest/spy": "4.0.17", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/mocker/node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.17.tgz", + "integrity": "sha512-Ah3VAYmjcEdHg6+MwFE17qyLqBHZ+ni2ScKCiW2XrlSBV4H3Z7vYfPfz7CWQ33gyu76oc0Ai36+kgLU3rfF4nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.17.tgz", + "integrity": "sha512-JmuQyf8aMWoo/LmNFppdpkfRVHJcsgzkbCA+/Bk7VfNH7RE6Ut2qxegeyx2j3ojtJtKIbIGy3h+KxGfYfk28YQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.0.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.17.tgz", + "integrity": "sha512-npPelD7oyL+YQM2gbIYvlavlMVWUfNNGZPcu0aEUQXt7FXTuqhmgiYupPnAanhKvyP6Srs2pIbWo30K0RbDtRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.17", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot/node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/@vitest/spy": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.17.tgz", + "integrity": "sha512-I1bQo8QaP6tZlTomQNWKJE6ym4SHf3oLS7ceNjozxxgzavRAgZDc06T7kD8gb9bXKEgcLNt00Z+kZO6KaJ62Ew==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.17.tgz", + "integrity": "sha512-RG6iy+IzQpa9SB8HAFHJ9Y+pTzI+h8553MrciN9eC6TFBErqrQaTas4vG+MVj8S4uKk8uTT2p0vgZPnTdxd96w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.17", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/a-sync-waterfall": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -7079,42 +7194,31 @@ } }, "node_modules/algoliasearch": { - "version": "5.46.2", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.46.2.tgz", - "integrity": "sha512-qqAXW9QvKf2tTyhpDA4qXv1IfBwD2eduSW6tUEBFIfCeE9gn9HQ9I5+MaKoenRuHrzk5sQoNh1/iof8mY7uD6Q==", + "version": "5.40.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.40.1.tgz", + "integrity": "sha512-iUNxcXUNg9085TJx0HJLjqtDE0r1RZ0GOGrt8KNQqQT5ugu8lZsHuMUYW/e0lHhq6xBvmktU9Bw4CXP9VQeKrg==", "dev": true, "license": "MIT", "dependencies": { - "@algolia/abtesting": "1.12.2", - "@algolia/client-abtesting": "5.46.2", - "@algolia/client-analytics": "5.46.2", - "@algolia/client-common": "5.46.2", - "@algolia/client-insights": "5.46.2", - "@algolia/client-personalization": "5.46.2", - "@algolia/client-query-suggestions": "5.46.2", - "@algolia/client-search": "5.46.2", - "@algolia/ingestion": "1.46.2", - "@algolia/monitoring": "1.46.2", - "@algolia/recommend": "5.46.2", - "@algolia/requester-browser-xhr": "5.46.2", - "@algolia/requester-fetch": "5.46.2", - "@algolia/requester-node-http": "5.46.2" + "@algolia/abtesting": "1.6.1", + "@algolia/client-abtesting": "5.40.1", + "@algolia/client-analytics": "5.40.1", + "@algolia/client-common": "5.40.1", + "@algolia/client-insights": "5.40.1", + "@algolia/client-personalization": "5.40.1", + "@algolia/client-query-suggestions": "5.40.1", + "@algolia/client-search": "5.40.1", + "@algolia/ingestion": "1.40.1", + "@algolia/monitoring": "1.40.1", + "@algolia/recommend": "5.40.1", + "@algolia/requester-browser-xhr": "5.40.1", + "@algolia/requester-fetch": "5.40.1", + "@algolia/requester-node-http": "5.40.1" }, "engines": { "node": ">= 14.0.0" } }, - "node_modules/amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", - "dev": true, - "license": "BSD-3-Clause OR MIT", - "optional": true, - "engines": { - "node": ">=0.4.2" - } - }, "node_modules/ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -7385,6 +7489,16 @@ "dev": true, "license": "MIT" }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -7408,6 +7522,25 @@ "node": ">=4" } }, + "node_modules/ast-v8-to-istanbul": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.10.tgz", + "integrity": "sha512-p4K7vMz2ZSk3wN8l5o3y2bJAoZXT3VuJI5OLTATY/01CYWumWvwkUw0SqDBnNq6IiTO3qDa1eSQDibAV8g7XOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.31", + "estree-walker": "^3.0.3", + "js-tokens": "^9.0.1" + } + }, + "node_modules/ast-v8-to-istanbul/node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" + }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -7419,9 +7552,9 @@ } }, "node_modules/astro": { - "version": "5.16.11", - "resolved": "https://registry.npmjs.org/astro/-/astro-5.16.11.tgz", - "integrity": "sha512-Z7kvkTTT5n6Hn5lCm6T3WU6pkxx84Hn25dtQ6dR7ATrBGq9eVa8EuB/h1S8xvaoVyCMZnIESu99Z9RJfdLRLDA==", + "version": "5.16.8", + "resolved": "https://registry.npmjs.org/astro/-/astro-5.16.8.tgz", + "integrity": "sha512-gzZE+epuCrNuxOa8/F1dzkllDOFvxWhGeobQKeBRIAef5sUpUKMHZo/8clse+02rYnKJCgwXBgjW4uTu9mqUUw==", "dev": true, "license": "MIT", "dependencies": { @@ -7443,8 +7576,8 @@ "cssesc": "^3.0.0", "debug": "^4.4.3", "deterministic-object-hash": "^2.0.2", - "devalue": "^5.6.2", - "diff": "^8.0.3", + "devalue": "^5.6.1", + "diff": "^5.2.0", "dlv": "^1.1.3", "dset": "^3.1.4", "es-module-lexer": "^1.7.0", @@ -8063,6 +8196,16 @@ "@esbuild/win32-x64": "0.25.12" } }, + "node_modules/astro/node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, "node_modules/astro/node_modules/vite": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", @@ -8443,20 +8586,10 @@ ], "license": "MIT" }, - "node_modules/base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^4.5.0 || >= 5.9" - } - }, "node_modules/baseline-browser-mapping": { - "version": "2.9.16", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.16.tgz", - "integrity": "sha512-KeUZdBuxngy825i8xvzaK1Ncnkx0tBmb3k8DkEuqjKRkmtvNTjey2ZsNeh8Dw4lfKvbCOu9oeNx2TKm2vHqcRw==", + "version": "2.9.14", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz", + "integrity": "sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -8877,18 +9010,31 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/cacache/node_modules/ssri": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-13.0.0.tgz", + "integrity": "sha512-yizwGBpbCn4YomB2lzhZqrHLJoqFGXihNbib3ozhqF/cIp5ue+xSmOQrjNasEE62hFxsCcg/V/z23t4n8jMEng==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/cacheable": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.3.2.tgz", - "integrity": "sha512-w+ZuRNmex9c1TR9RcsxbfTKCjSL0rh1WA5SABbrWprIHeNBdmyQLSYonlDy9gpD+63XT8DgZ/wNh1Smvc9WnJA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.3.1.tgz", + "integrity": "sha512-yr+FSHWn1ZUou5LkULX/S+jhfgfnLbuKQjE40tyEd4fxGZVMbBL5ifno0J0OauykS8UiCSgHi+DV/YD+rjFxFg==", "dev": true, "license": "MIT", "dependencies": { - "@cacheable/memory": "^2.0.7", - "@cacheable/utils": "^2.3.3", - "hookified": "^1.15.0", + "@cacheable/memory": "^2.0.6", + "@cacheable/utils": "^2.3.2", + "hookified": "^1.14.0", "keyv": "^5.5.5", - "qified": "^0.6.0" + "qified": "^0.5.3" } }, "node_modules/cacheable-request": { @@ -8938,9 +9084,9 @@ } }, "node_modules/cacheable/node_modules/keyv": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", - "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "version": "5.5.5", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.5.5.tgz", + "integrity": "sha512-FA5LmZVF1VziNc0bIdCSA1IoSVnDCqE8HJIZZv2/W8YmoAM50+tnUgJR/gQZwEeIMleuIOnRnHA/UaZRNeV4iQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9030,9 +9176,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001765", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001765.tgz", - "integrity": "sha512-LWcNtSyZrakjECqmpP4qdg0MMGdN368D7X8XvvAqOcqMv0RxnlqVKZl2V6/mBR68oYMxOZPLw/gO7DuisMHUvQ==", + "version": "1.0.30001764", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001764.tgz", + "integrity": "sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==", "dev": true, "funding": [ { @@ -9118,6 +9264,16 @@ "node": ">=0.10.0" } }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -9174,16 +9330,16 @@ "license": "MIT" }, "node_modules/chokidar": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", - "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "license": "MIT", "dependencies": { - "readdirp": "^5.0.0" + "readdirp": "^4.0.1" }, "engines": { - "node": ">= 20.19.0" + "node": ">= 14.16.0" }, "funding": { "url": "https://paulmillr.com/funding/" @@ -9298,9 +9454,9 @@ } }, "node_modules/cli-spinners": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-3.4.0.tgz", - "integrity": "sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-3.3.0.tgz", + "integrity": "sha512-/+40ljC3ONVnYIttjMWrlL51nItDAbBrq2upN8BPyvGU/2n5Oxw3tbNwORCaNuNqLJnxGqOfjUuhsv7l5Q4IsQ==", "dev": true, "license": "MIT", "engines": { @@ -9571,16 +9727,6 @@ "dev": true, "license": "MIT" }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.1.90" - } - }, "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", @@ -9722,95 +9868,10 @@ "typedarray-to-buffer": "^3.1.5" } }, - "node_modules/connect": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", - "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/connect/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/connect/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/connect/node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/connect/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT" - }, - "node_modules/connect/node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", - "dev": true, - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/connect/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-disposition": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", - "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", + "node_modules/content-disposition": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", "license": "MIT", "engines": { "node": ">=18" @@ -10134,13 +10195,6 @@ "node": ">=18" } }, - "node_modules/custom-event": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", - "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==", - "dev": true, - "license": "MIT" - }, "node_modules/dargs": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-4.1.0.tgz", @@ -10178,16 +10232,6 @@ "node": ">=18" } }, - "node_modules/date-format": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", - "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4.0" - } - }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -10213,9 +10257,9 @@ "license": "MIT" }, "node_modules/decode-named-character-reference": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", - "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", + "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", "dev": true, "license": "MIT", "dependencies": { @@ -10457,17 +10501,6 @@ "dev": true, "license": "MIT" }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, "node_modules/detect-file": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", @@ -10503,9 +10536,9 @@ } }, "node_modules/devalue": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.2.tgz", - "integrity": "sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg==", + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.1.tgz", + "integrity": "sha512-jDwizj+IlEZBunHcOuuFVBnIMPAEHvTsJj0BcIp94xYguLRVBcXO853px/MyIJvbVzWdsGvrRweIUWJw8hBP7A==", "dev": true, "license": "MIT" }, @@ -10529,17 +10562,10 @@ "dev": true, "license": "BSD-3-Clause" }, - "node_modules/di": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", - "integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==", - "dev": true, - "license": "MIT" - }, "node_modules/diff": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz", - "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -10599,19 +10625,6 @@ "node": ">=0.10.0" } }, - "node_modules/dom-serialize": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", - "integrity": "sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" - } - }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -10827,13 +10840,6 @@ "node": ">= 10.13.0" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -10914,122 +10920,6 @@ "node": ">=0.10.0" } }, - "node_modules/engine.io": { - "version": "6.6.5", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.5.tgz", - "integrity": "sha512-2RZdgEbXmp5+dVbRm0P7HQUImZpICccJy7rN7Tv+SFa55pH+lxnuw6/K1ZxxBfHoYpSkHLAO92oa8O4SwFXA2A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.7.2", - "cors": "~2.8.5", - "debug": "~4.4.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.18.3" - }, - "engines": { - "node": ">=10.2.0" - } - }, - "node_modules/engine.io-parser": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", - "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/engine.io/node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/engine.io/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/engine.io/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/engine.io/node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/engine.io/node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/ent": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.2.tgz", - "integrity": "sha512-kKvD1tO6BM+oK9HzCPpUdRb4vKFQY/FPTFmurMvh6LlN68VMrdj77w8yp51/kDbpkFOS9J8w5W6zIzgM2H8/hw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "punycode": "^1.4.1", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -11149,9 +11039,9 @@ "license": "MIT" }, "node_modules/esbuild": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", - "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.26.0.tgz", + "integrity": "sha512-3Hq7jri+tRrVWha+ZeIVhl4qJRha/XjRNSopvTsOaCvfPHrflTYTcUFcEjMKdxofsXXsdc4zjg5NOTnL4Gl57Q==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -11162,32 +11052,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.2", - "@esbuild/android-arm": "0.27.2", - "@esbuild/android-arm64": "0.27.2", - "@esbuild/android-x64": "0.27.2", - "@esbuild/darwin-arm64": "0.27.2", - "@esbuild/darwin-x64": "0.27.2", - "@esbuild/freebsd-arm64": "0.27.2", - "@esbuild/freebsd-x64": "0.27.2", - "@esbuild/linux-arm": "0.27.2", - "@esbuild/linux-arm64": "0.27.2", - "@esbuild/linux-ia32": "0.27.2", - "@esbuild/linux-loong64": "0.27.2", - "@esbuild/linux-mips64el": "0.27.2", - "@esbuild/linux-ppc64": "0.27.2", - "@esbuild/linux-riscv64": "0.27.2", - "@esbuild/linux-s390x": "0.27.2", - "@esbuild/linux-x64": "0.27.2", - "@esbuild/netbsd-arm64": "0.27.2", - "@esbuild/netbsd-x64": "0.27.2", - "@esbuild/openbsd-arm64": "0.27.2", - "@esbuild/openbsd-x64": "0.27.2", - "@esbuild/openharmony-arm64": "0.27.2", - "@esbuild/sunos-x64": "0.27.2", - "@esbuild/win32-arm64": "0.27.2", - "@esbuild/win32-ia32": "0.27.2", - "@esbuild/win32-x64": "0.27.2" + "@esbuild/aix-ppc64": "0.26.0", + "@esbuild/android-arm": "0.26.0", + "@esbuild/android-arm64": "0.26.0", + "@esbuild/android-x64": "0.26.0", + "@esbuild/darwin-arm64": "0.26.0", + "@esbuild/darwin-x64": "0.26.0", + "@esbuild/freebsd-arm64": "0.26.0", + "@esbuild/freebsd-x64": "0.26.0", + "@esbuild/linux-arm": "0.26.0", + "@esbuild/linux-arm64": "0.26.0", + "@esbuild/linux-ia32": "0.26.0", + "@esbuild/linux-loong64": "0.26.0", + "@esbuild/linux-mips64el": "0.26.0", + "@esbuild/linux-ppc64": "0.26.0", + "@esbuild/linux-riscv64": "0.26.0", + "@esbuild/linux-s390x": "0.26.0", + "@esbuild/linux-x64": "0.26.0", + "@esbuild/netbsd-arm64": "0.26.0", + "@esbuild/netbsd-x64": "0.26.0", + "@esbuild/openbsd-arm64": "0.26.0", + "@esbuild/openbsd-x64": "0.26.0", + "@esbuild/openharmony-arm64": "0.26.0", + "@esbuild/sunos-x64": "0.26.0", + "@esbuild/win32-arm64": "0.26.0", + "@esbuild/win32-ia32": "0.26.0", + "@esbuild/win32-x64": "0.26.0" } }, "node_modules/escalade": { @@ -11229,105 +11119,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=0.12.0" - }, - "optionalDependencies": { - "source-map": "~0.2.0" - } - }, - "node_modules/escodegen/node_modules/estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/escodegen/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==", - "dev": true, - "optional": true, - "dependencies": { - "amdefine": ">=0.0.4" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escodegen/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/eslint": { "version": "9.39.2", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", @@ -11389,14 +11180,12 @@ } }, "node_modules/eslint-scope": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.0.tgz", - "integrity": "sha512-CkWE42hOJsNj9FJRaoMX9waUFYhqY4jmyLFdAdzZr6VaCg3ynLYx4WnOdkaIifGfH4gsUcBTn4OZbHXkpLD0FQ==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.0.0.tgz", + "integrity": "sha512-+Yh0LeQKq+mW/tQArNj67tljR3L1HajDTQPuZOEwC00oBdoIDQrr89yBgjAlzAwRrY/5zDkM3v99iGHwz9y0dw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@types/esrecurse": "^4.3.1", - "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, @@ -11539,20 +11328,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/esquery": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", @@ -11628,13 +11403,6 @@ "node": ">=6" } }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true, - "license": "MIT" - }, "node_modules/events-universal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", @@ -11678,6 +11446,16 @@ "node": ">=0.10.0" } }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/exponential-backoff": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", @@ -12192,27 +11970,6 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, "node_modules/fontace": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.4.0.tgz", @@ -12224,9 +11981,9 @@ } }, "node_modules/fontkitten": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fontkitten/-/fontkitten-1.0.2.tgz", - "integrity": "sha512-piJxbLnkD9Xcyi7dWJRnqszEURixe7CrF/efBfbffe2DPyabmuIuqraruY8cXTs19QoM8VJzx47BDRVNXETM7Q==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fontkitten/-/fontkitten-1.0.0.tgz", + "integrity": "sha512-b0RdzQeztiiUFWEDzq6Ka26qkNVNLCehoRtifOIGNbQ4CfxyYRh73fyWaQX/JshPVcueITOEeoSWPy5XQv8FUg==", "dev": true, "license": "MIT", "dependencies": { @@ -12259,23 +12016,6 @@ "node": ">=0.10.0" } }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -12499,27 +12239,6 @@ "dev": true, "license": "ISC" }, - "node_modules/glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -13555,9 +13274,9 @@ } }, "node_modules/h3": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.5.tgz", - "integrity": "sha512-xEyq3rSl+dhGX2Lm0+eFQIAzlDN6Fs0EcC4f7BNUmzaRX/PTzeuM+Tr2lHB8FoXggsQIeXLj8EDVgs5ywxyxmg==", + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.4.tgz", + "integrity": "sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13566,9 +13285,9 @@ "defu": "^6.1.4", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", - "node-mock-http": "^1.0.4", + "node-mock-http": "^1.0.2", "radix3": "^1.1.2", - "ufo": "^1.6.3", + "ufo": "^1.6.1", "uncrypto": "^0.1.3" } }, @@ -13589,38 +13308,6 @@ "node": ">=0.8.0" } }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/handlebars/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -13679,22 +13366,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-yarn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", @@ -13995,9 +13666,9 @@ } }, "node_modules/hono": { - "version": "4.11.4", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.4.tgz", - "integrity": "sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==", + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.11.3.tgz", + "integrity": "sha512-PmQi306+M/ct/m5s66Hrg+adPnkD5jiO6IjA7WhWw0gSBSo1EcRegwuI1deZ+wd5pzCGynCcn2DprnE4/yEV4w==", "dev": true, "license": "MIT", "peer": true, @@ -14215,21 +13886,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/http-proxy-agent": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", @@ -14561,13 +14217,13 @@ "license": "ISC" }, "node_modules/ini": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz", - "integrity": "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-5.0.0.tgz", + "integrity": "sha512-+N0ngpO3e7cRUWOJAS7qw0IZIVc6XPrW4MlFBdD066F2L4k1L6ker3hLqSq7iXxU5tgS4WGkIUElWn5vogAEnw==", "dev": true, "license": "ISC", "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/injection-js": { @@ -14928,25 +14584,6 @@ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "license": "MIT" }, - "node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-relative": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", @@ -15057,19 +14694,6 @@ "dev": true, "license": "MIT" }, - "node_modules/isbinaryfile": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", - "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/gjtorikian/" - } - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -15087,33 +14711,6 @@ "node": ">=0.10.0" } }, - "node_modules/istanbul": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", - "integrity": "sha512-nMtdn4hvK0HjUlzr1DrKSUY8ychprt8dzHOgY2KXsIhHu5PuQQEOTM27gV9Xblyon7aUH/TSFIjRHEODF/FRPg==", - "deprecated": "This module is no longer maintained, try this instead:\n npm i nyc\nVisit https://istanbul.js.org/integrations for other alternatives.", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "istanbul": "lib/cli.js" - } - }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", @@ -15156,31 +14753,6 @@ "node": ">=10" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/istanbul-reports": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", @@ -15202,233 +14774,66 @@ "dev": true, "license": "MIT" }, - "node_modules/istanbul/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/istanbul/node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", - "dev": true, - "license": "MIT" - }, - "node_modules/istanbul/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/istanbul/node_modules/glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": "*" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/istanbul/node_modules/has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==", + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/istanbul/node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "node_modules/jose": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz", + "integrity": "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==", "dev": true, "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "funding": { + "url": "https://github.com/sponsors/panva" } }, - "node_modules/istanbul/node_modules/js-yaml/node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } + "license": "MIT" }, - "node_modules/istanbul/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "argparse": "^2.0.1" }, - "engines": { - "node": "*" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/istanbul/node_modules/resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==", - "dev": true, - "license": "MIT" - }, - "node_modules/istanbul/node_modules/supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^1.0.0" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/istanbul/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jasmine": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-5.13.0.tgz", - "integrity": "sha512-oLCXIhEb5e0zzjn9GyuvcuisvLBwUjmgz7a0RNGWKwQtJCDld4m+vwKUpAIJVLB5vbmQFdtKhT86/tIZlJ5gYw==", - "dev": true, - "license": "MIT", - "dependencies": { - "glob": "^10.2.2", - "jasmine-core": "~5.13.0" - }, - "bin": { - "jasmine": "bin/jasmine.js" - } - }, - "node_modules/jasmine-core": { - "version": "5.13.0", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-5.13.0.tgz", - "integrity": "sha512-vsYjfh7lyqvZX5QgqKc4YH8phs7g96Z8bsdIFNEU3VqXhlHaq+vov/Fgn/sr6MiUczdZkyXRC3TX369Ll4Nzbw==", - "dev": true, - "license": "MIT" - }, - "node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jose": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz", - "integrity": "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsdom": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", - "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", + "node_modules/jsdom": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", + "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", "dev": true, "license": "MIT", "dependencies": { @@ -15611,791 +15016,704 @@ "html2canvas": "^1.0.0-rc.5" } }, - "node_modules/karma": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.4.tgz", - "integrity": "sha512-LrtUxbdvt1gOpo3gxG+VAJlJAEMhbWlM4YrFQgql98FwF7+K8K12LYO4hnDdUkNjeztYrOXEMqgTajSWgmtI/w==", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "license": "MIT", "dependencies": { - "@colors/colors": "1.5.0", - "body-parser": "^1.19.0", - "braces": "^3.0.2", - "chokidar": "^3.5.1", - "connect": "^3.7.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.1", - "glob": "^7.1.7", - "graceful-fs": "^4.2.6", - "http-proxy": "^1.18.1", - "isbinaryfile": "^4.0.8", - "lodash": "^4.17.21", - "log4js": "^6.4.1", - "mime": "^2.5.2", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.5", - "qjobs": "^1.2.0", - "range-parser": "^1.2.1", - "rimraf": "^3.0.2", - "socket.io": "^4.7.2", - "source-map": "^0.6.1", - "tmp": "^0.2.1", - "ua-parser-js": "^0.7.30", - "yargs": "^16.1.1" - }, - "bin": { - "karma": "bin/karma" - }, - "engines": { - "node": ">= 10" + "json-buffer": "3.0.1" } }, - "node_modules/karma-chrome-launcher": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.2.0.tgz", - "integrity": "sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q==", + "node_modules/kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha512-aUH6ElPnMGon2/YkxRIigV32MOpTVcoXQ1Oo8aYn40s+sJ3j+0gFZsT8HKDcxNy7Fi9zuquWtGaGAahOdv5p/g==", "dev": true, "license": "MIT", - "dependencies": { - "which": "^1.2.1" - } - }, - "node_modules/karma-chrome-launcher/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/karma-coverage": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.2.1.tgz", - "integrity": "sha512-yj7hbequkQP2qOSb20GuNSIyE//PgJWHwC2IydLE6XRtsnaflv+/OSGNssPjobYUlhVVagy99TQpqUt3vAUG7A==", + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true, "license": "MIT", - "dependencies": { - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.1", - "istanbul-reports": "^3.0.5", - "minimatch": "^3.0.4" - }, "engines": { - "node": ">=10.0.0" + "node": ">=6" } }, - "node_modules/karma-coverage/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/known-css-properties": { + "version": "0.37.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.37.0.tgz", + "integrity": "sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/last-run": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-2.0.0.tgz", + "integrity": "sha512-j+y6WhTLN4Itnf9j5ZQos1BGPCS8DAwmgMroR3OzfxAsBxam0hMw7J8M3KqZl0pLQJ1jNnwIexg5DYpC/ctwEQ==", "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">= 10.13.0" } }, - "node_modules/karma-coverage/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "node_modules/latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" + "package-json": "^6.3.0" }, "engines": { "node": ">=8" } }, - "node_modules/karma-coverage/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "readable-stream": "^2.0.5" }, "engines": { - "node": "*" - } - }, - "node_modules/karma-coverage/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node": ">= 0.6.3" } }, - "node_modules/karma-jasmine": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-5.1.0.tgz", - "integrity": "sha512-i/zQLFrfEpRyQoJF9fsCdTMOF5c2dK7C7OmsuKg2D0YSsuZSfQDiLuaiktbuio6F2wiCsZSnSnieIQ0ant/uzQ==", + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "license": "MIT", "dependencies": { - "jasmine-core": "^4.1.0" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "karma": "^6.0.0" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/karma-jasmine/node_modules/jasmine-core": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.6.1.tgz", - "integrity": "sha512-VYz/BjjmC3klLJlLwA4Kw8ytk0zDSmbbDLNs794VnWmkcCB7I9aAL/D48VNQtmITyPvea2C3jdUMfc3kAoy0PQ==", + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, "license": "MIT" }, - "node_modules/karma-junit-reporter": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/karma-junit-reporter/-/karma-junit-reporter-2.0.1.tgz", - "integrity": "sha512-VtcGfE0JE4OE1wn0LK8xxDKaTP7slN8DO3I+4xg6gAi1IoAHAXOJ1V9G/y45Xg6sxdxPOR3THCFtDlAfBo9Afw==", + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "license": "MIT", "dependencies": { - "path-is-absolute": "^1.0.0", - "xmlbuilder": "12.0.0" - }, - "engines": { - "node": ">= 8" - }, - "peerDependencies": { - "karma": ">=0.9" + "safe-buffer": "~5.1.0" } }, - "node_modules/karma-parallel": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/karma-parallel/-/karma-parallel-0.3.1.tgz", - "integrity": "sha512-64jxNYamYi/9Y67h4+FfViSYhwDgod3rLuq+ZdZ0c3XeZFp/3q3v3HVkd8b5Czp3hCB+LLF8DIv4zlR4xFqbRw==", + "node_modules/lead": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-4.0.0.tgz", + "integrity": "sha512-DpMa59o5uGUWWjruMp71e6knmwKU3jRBBn1kjuLWN9EeIOxNeSAwvHf03WIl8g/ZMR2oSQC9ej3yeLBwdDc/pg==", "dev": true, "license": "MIT", - "dependencies": { - "istanbul": "^0.4.5", - "lodash": "^4.17.11" - }, "engines": { - "node": ">=6" - }, - "peerDependencies": { - "karma": ">= 1.0.0" + "node": ">=10.13.0" } }, - "node_modules/karma-spec-reporter": { - "version": "0.0.36", - "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.36.tgz", - "integrity": "sha512-11bvOl1x6ryKZph7kmbmMpbi8vsngEGxGOoeTlIcDaH3ab3j8aPJnZ+r+K/SS0sBSGy5VGkGYO2+hLct7hw/6w==", + "node_modules/less": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/less/-/less-4.5.1.tgz", + "integrity": "sha512-UKgI3/KON4u6ngSsnDADsUERqhZknsVZbnuzlRZXLQCmfC/MDld42fTydUE9B+Mla1AL6SJ/Pp6SlEFi/AVGfw==", "dev": true, - "license": "MIT", + "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { - "colors": "1.4.0" + "copy-anything": "^2.0.1", + "parse-node-version": "^1.0.1", + "tslib": "^2.3.0" + }, + "bin": { + "lessc": "bin/lessc" }, - "peerDependencies": { - "karma": ">=0.9" - } - }, - "node_modules/karma/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", "engines": { - "node": ">=8" + "node": ">=14" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "source-map": "~0.6.0" } }, - "node_modules/karma/node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "node_modules/less/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "bytes": "~3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "~1.2.0", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "on-finished": "~2.4.1", - "qs": "~6.14.0", - "raw-body": "~2.5.3", - "type-is": "~1.6.18", - "unpipe": "~1.0.0" + "pify": "^4.0.1", + "semver": "^5.6.0" }, "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/karma/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node": ">=6" } }, - "node_modules/karma/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "node_modules/less/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true, "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "optional": true, + "bin": { + "mime": "cli.js" }, "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "node": ">=4" } }, - "node_modules/karma/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "node_modules/less/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/karma/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" + "optional": true, + "bin": { + "semver": "bin/semver" } }, - "node_modules/karma/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/less/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, + "license": "BSD-3-Clause", + "optional": true, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=0.10.0" } }, - "node_modules/karma/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, "engines": { - "node": ">= 6" + "node": ">= 0.8.0" } }, - "node_modules/karma/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/liftoff": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-5.0.1.tgz", + "integrity": "sha512-wwLXMbuxSF8gMvubFcFRp56lkFV69twvbU5vDPbaw+Q+/rF8j0HKjGbIdlSi+LuJm9jf7k9PB+nTxnsLMPcv2Q==", "dev": true, "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "extend": "^3.0.2", + "findup-sync": "^5.0.0", + "fined": "^2.0.0", + "flagged-respawn": "^2.0.0", + "is-plain-object": "^5.0.0", + "rechoir": "^0.8.0", + "resolve": "^1.20.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10.13.0" } }, - "node_modules/karma/node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } + "license": "MIT" }, - "node_modules/karma/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.6" + "dependencies": { + "uc.micro": "^2.0.0" } }, - "node_modules/karma/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/listr2": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz", + "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", "dev": true, "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "cli-truncate": "^5.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">=20.0.0" } }, - "node_modules/karma/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", "engines": { - "node": "*" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/karma/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", "dev": true, "license": "MIT" }, - "node_modules/karma/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/listr2/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } + "license": "MIT" }, - "node_modules/karma/node_modules/raw-body": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", - "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "node_modules/listr2/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "license": "MIT", "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.4.24", - "unpipe": "~1.0.0" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">= 0.8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/karma/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", "dev": true, "license": "MIT", "dependencies": { - "picomatch": "^2.2.1" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8.10.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/karma/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, + "node_modules/lit": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.2.tgz", + "integrity": "sha512-NF9zbsP79l4ao2SNrH3NkfmFgN/hBYSQo90saIVI1o5GpjAdCPVstVzO1MrLOakHoEhYkrtRjPK6Ob521aoYWQ==", "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/karma/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" + "@lit/reactive-element": "^2.1.0", + "lit-element": "^4.2.0", + "lit-html": "^3.3.0" } }, - "node_modules/karma/node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" + "node_modules/lit-element": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.2.tgz", + "integrity": "sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==", + "license": "BSD-3-Clause", + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.5.0", + "@lit/reactive-element": "^2.1.0", + "lit-html": "^3.3.0" } }, - "node_modules/karma/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/lit-html": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.2.tgz", + "integrity": "sha512-Qy9hU88zcmaxBXcc10ZpdK7cOLXvXpRoBxERdtqV9QOrfpMZZ6pSYP91LhpPtap3sFMUiL7Tw2RImbe0Al2/kw==", + "license": "BSD-3-Clause", + "dependencies": { + "@types/trusted-types": "^2.0.2" + } + }, + "node_modules/lmdb": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.4.3.tgz", + "integrity": "sha512-GWV1kVi6uhrXWqe+3NXWO73OYe8fto6q8JMo0HOpk1vf8nEyFWgo4CSNJpIFzsOxOrysVUlcO48qRbQfmKd1gA==", "dev": true, + "hasInstallScript": true, "license": "MIT", + "optional": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "msgpackr": "^1.11.2", + "node-addon-api": "^6.1.0", + "node-gyp-build-optional-packages": "5.2.2", + "ordered-binary": "^1.5.3", + "weak-lru-cache": "^1.2.2" }, - "engines": { - "node": ">=10" + "bin": { + "download-lmdb-prebuilds": "bin/download-prebuilds.js" }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "optionalDependencies": { + "@lmdb/lmdb-darwin-arm64": "3.4.3", + "@lmdb/lmdb-darwin-x64": "3.4.3", + "@lmdb/lmdb-linux-arm": "3.4.3", + "@lmdb/lmdb-linux-arm64": "3.4.3", + "@lmdb/lmdb-linux-x64": "3.4.3", + "@lmdb/lmdb-win32-arm64": "3.4.3", + "@lmdb/lmdb-win32-x64": "3.4.3" } }, - "node_modules/karma/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "p-locate": "^5.0.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/karma/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } + "license": "MIT" }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "node_modules/lodash-es": { + "version": "4.17.22", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.22.tgz", + "integrity": "sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q==", + "license": "MIT" + }, + "node_modules/lodash._basebind": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._basebind/-/lodash._basebind-2.4.1.tgz", + "integrity": "sha512-VGHm6DH+1UiuafQdE/DNMqxOcSyhRu0xO9+jPDq7xITRn5YOorGrHVQmavMVXCYmTm80YRTZZCn/jTW7MokwLg==", "dev": true, "license": "MIT", "dependencies": { - "json-buffer": "3.0.1" + "lodash._basecreate": "~2.4.1", + "lodash._setbinddata": "~2.4.1", + "lodash._slice": "~2.4.1", + "lodash.isobject": "~2.4.1" } }, - "node_modules/kind-of": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", - "integrity": "sha512-aUH6ElPnMGon2/YkxRIigV32MOpTVcoXQ1Oo8aYn40s+sJ3j+0gFZsT8HKDcxNy7Fi9zuquWtGaGAahOdv5p/g==", + "node_modules/lodash._basecreate": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-2.4.1.tgz", + "integrity": "sha512-8JJ3FnMPm54t3BwPLk8q8mPyQKQXm/rt9df+awr4NGtyJrtcCXM3Of1I86S6jVy1b4yAyFBb8wbKPEauuqzRmQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "lodash._isnative": "~2.4.1", + "lodash.isobject": "~2.4.1", + "lodash.noop": "~2.4.1" } }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "node_modules/lodash._basecreatecallback": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._basecreatecallback/-/lodash._basecreatecallback-2.4.1.tgz", + "integrity": "sha512-SLczhg860fGW7AKlYcuOFstDtJuQhaANlJ4Y/jrOoRxhmVtK41vbJDH3OefVRSRkSCQo4HI82QVkAVsoGa5gSw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "lodash._setbinddata": "~2.4.1", + "lodash.bind": "~2.4.1", + "lodash.identity": "~2.4.1", + "lodash.support": "~2.4.1" } }, - "node_modules/known-css-properties": { - "version": "0.37.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.37.0.tgz", - "integrity": "sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/last-run": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-2.0.0.tgz", - "integrity": "sha512-j+y6WhTLN4Itnf9j5ZQos1BGPCS8DAwmgMroR3OzfxAsBxam0hMw7J8M3KqZl0pLQJ1jNnwIexg5DYpC/ctwEQ==", + "node_modules/lodash._basecreatewrapper": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._basecreatewrapper/-/lodash._basecreatewrapper-2.4.1.tgz", + "integrity": "sha512-x2ja1fa/qmzbizuXgVM4QAP9svtMbdxjG8Anl9bCeDAwLOVQ1vLrA0hLb/NkpbGi9evjtkl0aWLTEoOlUdBPQA==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 10.13.0" + "dependencies": { + "lodash._basecreate": "~2.4.1", + "lodash._setbinddata": "~2.4.1", + "lodash._slice": "~2.4.1", + "lodash.isobject": "~2.4.1" } }, - "node_modules/latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "node_modules/lodash._createwrapper": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._createwrapper/-/lodash._createwrapper-2.4.1.tgz", + "integrity": "sha512-5TCfLt1haQpsa7bgLYRKNNE4yqhO4ZxIayN1btQmazMchO6Q8JYFRMqbJ3W+uNmMm4R0Jw7KGkZX5YfDDnywuw==", "dev": true, "license": "MIT", "dependencies": { - "package-json": "^6.3.0" - }, - "engines": { - "node": ">=8" + "lodash._basebind": "~2.4.1", + "lodash._basecreatewrapper": "~2.4.1", + "lodash._slice": "~2.4.1", + "lodash.isfunction": "~2.4.1" } }, - "node_modules/lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "node_modules/lodash._isnative": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "integrity": "sha512-BOlKGKNHhCHswGOWtmVb5zBygyxN7EmTuzVOSQI6QSoGhG+kvv71gICFS1TBpnqvT1n53txK8CDK3u5D2/GZxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash._objecttypes": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "integrity": "sha512-XpqGh1e7hhkOzftBfWE7zt+Yn9mVHFkDhicVttvKLsoCMLVVL+xTQjfjB4X4vtznauxv0QZ5ZAeqjvat0dh62Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash._setbinddata": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._setbinddata/-/lodash._setbinddata-2.4.1.tgz", + "integrity": "sha512-Vx0XKzpg2DFbQw4wrp1xSWd2sfl3W/BG6bucSRZmftS1AzbWRemCmBQDxyQTNhlLNec428PXkuuja+VNBZgu2A==", "dev": true, "license": "MIT", "dependencies": { - "readable-stream": "^2.0.5" - }, - "engines": { - "node": ">= 0.6.3" + "lodash._isnative": "~2.4.1", + "lodash.noop": "~2.4.1" } }, - "node_modules/lazystream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/lodash._shimkeys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", + "integrity": "sha512-lBrglYxLD/6KAJ8IEa5Lg+YHgNAL7FyKqXg4XOUI+Du/vtniLs1ZqS+yHNKPkK54waAgkdUnDOYaWf+rv4B+AA==", "dev": true, "license": "MIT", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "lodash._objecttypes": "~2.4.1" } }, - "node_modules/lazystream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "node_modules/lodash._slice": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._slice/-/lodash._slice-2.4.1.tgz", + "integrity": "sha512-+odPJa4PE2UgYnQgJgkLs0UD03QU78R2ivhrFnG9GdtYOZdE6ObxOj7KiUEUlqOOgatFT+ZqSypFjDSduTigKg==", "dev": true, "license": "MIT" }, - "node_modules/lazystream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/lodash.assign": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-2.4.1.tgz", + "integrity": "sha512-AqQ4AJz5buSx9ELXWt5dONwJyVPd4NTADMKhoVYWCugjoVf172/LpvVhwmSJn4g8/Dc0S8hxTe8rt5Dob3X9KQ==", "dev": true, "license": "MIT", "dependencies": { - "safe-buffer": "~5.1.0" + "lodash._basecreatecallback": "~2.4.1", + "lodash._objecttypes": "~2.4.1", + "lodash.keys": "~2.4.1" } }, - "node_modules/lead": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-4.0.0.tgz", - "integrity": "sha512-DpMa59o5uGUWWjruMp71e6knmwKU3jRBBn1kjuLWN9EeIOxNeSAwvHf03WIl8g/ZMR2oSQC9ej3yeLBwdDc/pg==", + "node_modules/lodash.bind": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-2.4.1.tgz", + "integrity": "sha512-hn2VWYZ+N9aYncRad4jORvlGgpFrn+axnPIWRvFxjk6CWcZH5b5alI8EymYsHITI23Z9wrW/+ORq+azrVFpOfw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=10.13.0" + "dependencies": { + "lodash._createwrapper": "~2.4.1", + "lodash._slice": "~2.4.1" } }, - "node_modules/less": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/less/-/less-4.5.1.tgz", - "integrity": "sha512-UKgI3/KON4u6ngSsnDADsUERqhZknsVZbnuzlRZXLQCmfC/MDld42fTydUE9B+Mla1AL6SJ/Pp6SlEFi/AVGfw==", + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "copy-anything": "^2.0.1", - "parse-node-version": "^1.0.1", - "tslib": "^2.3.0" - }, - "bin": { - "lessc": "bin/lessc" - }, - "engines": { - "node": ">=14" - }, - "optionalDependencies": { - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "make-dir": "^2.1.0", - "mime": "^1.4.1", - "needle": "^3.1.0", - "source-map": "~0.6.0" - } + "license": "MIT" }, - "node_modules/less/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "node_modules/lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.identity": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.identity/-/lodash.identity-2.4.1.tgz", + "integrity": "sha512-VRYX+8XipeLjorag5bz3YBBRJ+5kj8hVBzfnaHgXPZAVTYowBdY5l0M5ZnOmlAMCOXBFabQtm7f5VqjMKEji0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isfunction": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-2.4.1.tgz", + "integrity": "sha512-6XcAB3izeQxPOQQNAJbbdjXbvWEt2Pn9ezPrjr4CwoLwmqsLVbsiEXD19cmmt4mbzOCOCdHzOQiUivUOJLra7w==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isobject": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", + "integrity": "sha512-sTebg2a1PoicYEZXD5PBdQcTlIJ6hUslrlWr7iV0O7n+i4596s2NQ9I5CaZ5FbXSfya/9WQsrYLANUJv9paYVA==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" + "lodash._objecttypes": "~2.4.1" } }, - "node_modules/less/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "node_modules/lodash.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha512-ZpJhwvUXHSNL5wYd1RM6CUa2ZuqorG9ngoJ9Ix5Cce+uX7I5O/E06FCJdhSZ33b5dVyeQDnIlWH7B2s5uByZ7g==", "dev": true, "license": "MIT", - "optional": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" + "dependencies": { + "lodash._isnative": "~2.4.1", + "lodash._shimkeys": "~2.4.1", + "lodash.isobject": "~2.4.1" } }, - "node_modules/less/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, - "license": "ISC", - "optional": true, - "bin": { - "semver": "bin/semver" - } + "license": "MIT" }, - "node_modules/less/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/lodash.noop": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.noop/-/lodash.noop-2.4.1.tgz", + "integrity": "sha512-uNcV98/blRhInPUGQEnj9ekXXfG+q+rfoNSFZgl/eBfog9yBDW9gfUv2AHX/rAF7zZRlzWhbslGhbGQFZlCkZA==", "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "engines": { - "node": ">=0.10.0" + "license": "MIT" + }, + "node_modules/lodash.support": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.support/-/lodash.support-2.4.1.tgz", + "integrity": "sha512-6SwqWwGFHhTXEiqB/yQgu8FYd//tm786d49y7kizHVCJH7zdzs191UQn3ES3tkkDbUddNRfkCRYqJFHtbLnbCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash._isnative": "~2.4.1" } }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "node_modules/lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "deprecated": "This package is deprecated. Use https://socket.dev/npm/package/eta instead.", "dev": true, "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" } }, - "node_modules/liftoff": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-5.0.1.tgz", - "integrity": "sha512-wwLXMbuxSF8gMvubFcFRp56lkFV69twvbU5vDPbaw+Q+/rF8j0HKjGbIdlSi+LuJm9jf7k9PB+nTxnsLMPcv2Q==", + "node_modules/lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", "dev": true, "license": "MIT", "dependencies": { - "extend": "^3.0.2", - "findup-sync": "^5.0.0", - "fined": "^2.0.0", - "flagged-respawn": "^2.0.0", - "is-plain-object": "^5.0.0", - "rechoir": "^0.8.0", - "resolve": "^1.20.0" - }, - "engines": { - "node": ">=10.13.0" + "lodash._reinterpolate": "^3.0.0" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", "dev": true, "license": "MIT" }, - "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-7.0.1.tgz", + "integrity": "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==", "dev": true, "license": "MIT", "dependencies": { - "uc.micro": "^2.0.0" + "is-unicode-supported": "^2.0.0", + "yoctocolors": "^2.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/listr2": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz", - "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==", + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", "dev": true, "license": "MIT", "dependencies": { - "cli-truncate": "^5.0.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", - "log-update": "^6.1.0", - "rfdc": "^1.4.1", + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=20.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/listr2/node_modules/ansi-styles": { + "node_modules/log-update/node_modules/ansi-styles": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", @@ -16408,21 +15726,14 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/listr2/node_modules/emoji-regex": { + "node_modules/log-update/node_modules/emoji-regex": { "version": "10.6.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", "dev": true, "license": "MIT" }, - "node_modules/listr2/node_modules/eventemitter3": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", - "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/listr2/node_modules/string-width": { + "node_modules/log-update/node_modules/string-width": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", @@ -16440,7 +15751,7 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/listr2/node_modules/wrap-ansi": { + "node_modules/log-update/node_modules/wrap-ansi": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", @@ -16458,973 +15769,903 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/lit": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.2.tgz", - "integrity": "sha512-NF9zbsP79l4ao2SNrH3NkfmFgN/hBYSQo90saIVI1o5GpjAdCPVstVzO1MrLOakHoEhYkrtRjPK6Ob521aoYWQ==", - "license": "BSD-3-Clause", - "dependencies": { - "@lit/reactive-element": "^2.1.0", - "lit-element": "^4.2.0", - "lit-html": "^3.3.0" - } - }, - "node_modules/lit-element": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.2.2.tgz", - "integrity": "sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w==", - "license": "BSD-3-Clause", - "dependencies": { - "@lit-labs/ssr-dom-shim": "^1.5.0", - "@lit/reactive-element": "^2.1.0", - "lit-html": "^3.3.0" + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/lit-html": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.3.2.tgz", - "integrity": "sha512-Qy9hU88zcmaxBXcc10ZpdK7cOLXvXpRoBxERdtqV9QOrfpMZZ6pSYP91LhpPtap3sFMUiL7Tw2RImbe0Al2/kw==", - "license": "BSD-3-Clause", - "dependencies": { - "@types/trusted-types": "^2.0.2" - } + "node_modules/lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==", + "dev": true, + "license": "MIT" }, - "node_modules/lmdb": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.4.4.tgz", - "integrity": "sha512-+Y2DqovevLkb6DrSQ6SXTYLEd6kvlRbhsxzgJrk7BUfOVA/mt21ak6pFDZDKxiAczHMWxrb02kXBTSTIA0O94A==", + "node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", "dev": true, - "hasInstallScript": true, "license": "MIT", - "optional": true, - "dependencies": { - "msgpackr": "^1.11.2", - "node-addon-api": "^6.1.0", - "node-gyp-build-optional-packages": "5.2.2", - "ordered-binary": "^1.5.3", - "weak-lru-cache": "^1.2.2" - }, - "bin": { - "download-lmdb-prebuilds": "bin/download-prebuilds.js" - }, - "optionalDependencies": { - "@lmdb/lmdb-darwin-arm64": "3.4.4", - "@lmdb/lmdb-darwin-x64": "3.4.4", - "@lmdb/lmdb-linux-arm": "3.4.4", - "@lmdb/lmdb-linux-arm64": "3.4.4", - "@lmdb/lmdb-linux-x64": "3.4.4", - "@lmdb/lmdb-win32-arm64": "3.4.4", - "@lmdb/lmdb-win32-x64": "3.4.4" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "yallist": "^3.0.2" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", "dev": true, "license": "MIT" }, - "node_modules/lodash-es": { - "version": "4.17.22", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.22.tgz", - "integrity": "sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q==", - "license": "MIT" - }, - "node_modules/lodash._basebind": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._basebind/-/lodash._basebind-2.4.1.tgz", - "integrity": "sha512-VGHm6DH+1UiuafQdE/DNMqxOcSyhRu0xO9+jPDq7xITRn5YOorGrHVQmavMVXCYmTm80YRTZZCn/jTW7MokwLg==", + "node_modules/magic-string": { + "version": "0.30.19", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", + "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==", "dev": true, "license": "MIT", "dependencies": { - "lodash._basecreate": "~2.4.1", - "lodash._setbinddata": "~2.4.1", - "lodash._slice": "~2.4.1", - "lodash.isobject": "~2.4.1" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/lodash._basecreate": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-2.4.1.tgz", - "integrity": "sha512-8JJ3FnMPm54t3BwPLk8q8mPyQKQXm/rt9df+awr4NGtyJrtcCXM3Of1I86S6jVy1b4yAyFBb8wbKPEauuqzRmQ==", + "node_modules/magicast": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.1.tgz", + "integrity": "sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==", "dev": true, "license": "MIT", "dependencies": { - "lodash._isnative": "~2.4.1", - "lodash.isobject": "~2.4.1", - "lodash.noop": "~2.4.1" + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "source-map-js": "^1.2.1" } }, - "node_modules/lodash._basecreatecallback": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._basecreatecallback/-/lodash._basecreatecallback-2.4.1.tgz", - "integrity": "sha512-SLczhg860fGW7AKlYcuOFstDtJuQhaANlJ4Y/jrOoRxhmVtK41vbJDH3OefVRSRkSCQo4HI82QVkAVsoGa5gSw==", + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "license": "MIT", "dependencies": { - "lodash._setbinddata": "~2.4.1", - "lodash.bind": "~2.4.1", - "lodash.identity": "~2.4.1", - "lodash.support": "~2.4.1" + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash._basecreatewrapper": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._basecreatewrapper/-/lodash._basecreatewrapper-2.4.1.tgz", - "integrity": "sha512-x2ja1fa/qmzbizuXgVM4QAP9svtMbdxjG8Anl9bCeDAwLOVQ1vLrA0hLb/NkpbGi9evjtkl0aWLTEoOlUdBPQA==", + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true, - "license": "MIT", - "dependencies": { - "lodash._basecreate": "~2.4.1", - "lodash._setbinddata": "~2.4.1", - "lodash._slice": "~2.4.1", - "lodash.isobject": "~2.4.1" - } + "license": "ISC" }, - "node_modules/lodash._createwrapper": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._createwrapper/-/lodash._createwrapper-2.4.1.tgz", - "integrity": "sha512-5TCfLt1haQpsa7bgLYRKNNE4yqhO4ZxIayN1btQmazMchO6Q8JYFRMqbJ3W+uNmMm4R0Jw7KGkZX5YfDDnywuw==", + "node_modules/make-error-cause": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", + "integrity": "sha512-4TO2Y3HkBnis4c0dxhAgD/jprySYLACf7nwN6V0HAHDx59g12WlRpUmFy1bRHamjGUEEBrEvCq6SUpsEE2lhUg==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "lodash._basebind": "~2.4.1", - "lodash._basecreatewrapper": "~2.4.1", - "lodash._slice": "~2.4.1", - "lodash.isfunction": "~2.4.1" + "make-error": "^1.2.0" } }, - "node_modules/lodash._isnative": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", - "integrity": "sha512-BOlKGKNHhCHswGOWtmVb5zBygyxN7EmTuzVOSQI6QSoGhG+kvv71gICFS1TBpnqvT1n53txK8CDK3u5D2/GZxQ==", + "node_modules/make-fetch-happen": { + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.3.tgz", + "integrity": "sha512-iyyEpDty1mwW3dGlYXAJqC/azFn5PPvgKVwXayOGBSmKLxhKZ9fg4qIan2ePpp1vJIwfFiO34LAPZgq9SZW9Aw==", "dev": true, - "license": "MIT" + "license": "ISC", + "dependencies": { + "@npmcli/agent": "^4.0.0", + "cacache": "^20.0.1", + "http-cache-semantics": "^4.1.1", + "minipass": "^7.0.2", + "minipass-fetch": "^5.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^1.0.0", + "proc-log": "^6.0.0", + "promise-retry": "^2.0.1", + "ssri": "^13.0.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } }, - "node_modules/lodash._objecttypes": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", - "integrity": "sha512-XpqGh1e7hhkOzftBfWE7zt+Yn9mVHFkDhicVttvKLsoCMLVVL+xTQjfjB4X4vtznauxv0QZ5ZAeqjvat0dh62Q==", + "node_modules/make-fetch-happen/node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", "dev": true, - "license": "MIT" + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } }, - "node_modules/lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==", + "node_modules/make-fetch-happen/node_modules/ssri": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-13.0.0.tgz", + "integrity": "sha512-yizwGBpbCn4YomB2lzhZqrHLJoqFGXihNbib3ozhqF/cIp5ue+xSmOQrjNasEE62hFxsCcg/V/z23t4n8jMEng==", "dev": true, - "license": "MIT" + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } }, - "node_modules/lodash._setbinddata": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._setbinddata/-/lodash._setbinddata-2.4.1.tgz", - "integrity": "sha512-Vx0XKzpg2DFbQw4wrp1xSWd2sfl3W/BG6bucSRZmftS1AzbWRemCmBQDxyQTNhlLNec428PXkuuja+VNBZgu2A==", + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", "dev": true, "license": "MIT", - "dependencies": { - "lodash._isnative": "~2.4.1", - "lodash.noop": "~2.4.1" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/lodash._shimkeys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", - "integrity": "sha512-lBrglYxLD/6KAJ8IEa5Lg+YHgNAL7FyKqXg4XOUI+Du/vtniLs1ZqS+yHNKPkK54waAgkdUnDOYaWf+rv4B+AA==", + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", "dev": true, "license": "MIT", "dependencies": { - "lodash._objecttypes": "~2.4.1" + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" } }, - "node_modules/lodash._slice": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._slice/-/lodash._slice-2.4.1.tgz", - "integrity": "sha512-+odPJa4PE2UgYnQgJgkLs0UD03QU78R2ivhrFnG9GdtYOZdE6ObxOj7KiUEUlqOOgatFT+ZqSypFjDSduTigKg==", + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", "dev": true, - "license": "MIT" + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } }, - "node_modules/lodash.assign": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-2.4.1.tgz", - "integrity": "sha512-AqQ4AJz5buSx9ELXWt5dONwJyVPd4NTADMKhoVYWCugjoVf172/LpvVhwmSJn4g8/Dc0S8hxTe8rt5Dob3X9KQ==", - "dev": true, + "node_modules/marked": { + "version": "17.0.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-17.0.1.tgz", + "integrity": "sha512-boeBdiS0ghpWcSwoNm/jJBwdpFaMnZWRzjA6SkUMYb40SVaN1x7mmfGKp0jvexGcx+7y2La5zRZsYFZI6Qpypg==", "license": "MIT", - "dependencies": { - "lodash._basecreatecallback": "~2.4.1", - "lodash._objecttypes": "~2.4.1", - "lodash.keys": "~2.4.1" + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" } }, - "node_modules/lodash.bind": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-2.4.1.tgz", - "integrity": "sha512-hn2VWYZ+N9aYncRad4jORvlGgpFrn+axnPIWRvFxjk6CWcZH5b5alI8EymYsHITI23Z9wrW/+ORq+azrVFpOfw==", - "dev": true, + "node_modules/marked-shiki": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/marked-shiki/-/marked-shiki-1.2.1.tgz", + "integrity": "sha512-yHxYQhPY5oYaIRnROn98foKhuClark7M373/VpLxiy5TrDu9Jd/LsMwo8w+U91Up4oDb9IXFrP0N1MFRz8W/DQ==", "license": "MIT", - "dependencies": { - "lodash._createwrapper": "~2.4.1", - "lodash._slice": "~2.4.1" + "peerDependencies": { + "marked": ">=7.0.0", + "shiki": ">=1.0.0" } }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.difference": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", - "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.identity": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.identity/-/lodash.identity-2.4.1.tgz", - "integrity": "sha512-VRYX+8XipeLjorag5bz3YBBRJ+5kj8hVBzfnaHgXPZAVTYowBdY5l0M5ZnOmlAMCOXBFabQtm7f5VqjMKEji0w==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.isfunction": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-2.4.1.tgz", - "integrity": "sha512-6XcAB3izeQxPOQQNAJbbdjXbvWEt2Pn9ezPrjr4CwoLwmqsLVbsiEXD19cmmt4mbzOCOCdHzOQiUivUOJLra7w==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.isobject": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", - "integrity": "sha512-sTebg2a1PoicYEZXD5PBdQcTlIJ6hUslrlWr7iV0O7n+i4596s2NQ9I5CaZ5FbXSfya/9WQsrYLANUJv9paYVA==", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash._objecttypes": "~2.4.1" - } - }, - "node_modules/lodash.keys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha512-ZpJhwvUXHSNL5wYd1RM6CUa2ZuqorG9ngoJ9Ix5Cce+uX7I5O/E06FCJdhSZ33b5dVyeQDnIlWH7B2s5uByZ7g==", - "dev": true, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "license": "MIT", - "dependencies": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" + "engines": { + "node": ">= 0.4" } }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.noop": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.noop/-/lodash.noop-2.4.1.tgz", - "integrity": "sha512-uNcV98/blRhInPUGQEnj9ekXXfG+q+rfoNSFZgl/eBfog9yBDW9gfUv2AHX/rAF7zZRlzWhbslGhbGQFZlCkZA==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.support": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.support/-/lodash.support-2.4.1.tgz", - "integrity": "sha512-6SwqWwGFHhTXEiqB/yQgu8FYd//tm786d49y7kizHVCJH7zdzs191UQn3ES3tkkDbUddNRfkCRYqJFHtbLnbCw==", + "node_modules/mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", "dev": true, "license": "MIT", - "dependencies": { - "lodash._isnative": "~2.4.1" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/lodash.template": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", - "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", - "deprecated": "This package is deprecated. Use https://socket.dev/npm/package/eta instead.", + "node_modules/mdast-util-definitions": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-6.0.0.tgz", + "integrity": "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==", "dev": true, "license": "MIT", "dependencies": { - "lodash._reinterpolate": "^3.0.0", - "lodash.templatesettings": "^4.0.0" + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/lodash.templatesettings": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", - "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", "dev": true, "license": "MIT", "dependencies": { - "lodash._reinterpolate": "^3.0.0" + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/log-symbols": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-7.0.1.tgz", - "integrity": "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg==", + "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "dev": true, "license": "MIT", - "dependencies": { - "is-unicode-supported": "^2.0.0", - "yoctocolors": "^2.1.1" - }, "engines": { - "node": ">=18" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", - "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "node_modules/mdast-util-from-markdown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", "dev": true, "license": "MIT", "dependencies": { - "ansi-escapes": "^7.0.0", - "cli-cursor": "^5.0.0", - "slice-ansi": "^7.1.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/log-update/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true, - "license": "MIT" - }, - "node_modules/log-update/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/log4js": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", - "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "flatted": "^3.2.7", - "rfdc": "^1.3.0", - "streamroller": "^3.1.5" + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" }, - "engines": { - "node": ">=8.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/longest-streak": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", "dev": true, "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==", - "dev": true, - "license": "MIT" - }, - "node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "yallist": "^3.0.2" + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true, - "license": "MIT" - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/magicast": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.1.tgz", - "integrity": "sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==", + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.5", - "@babel/types": "^7.28.5", - "source-map-js": "^1.2.1" + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/make-dir": { + "node_modules/mdast-util-to-string": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", "dev": true, "license": "MIT", "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" + "@types/mdast": "^4.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true, - "license": "ISC" - }, - "node_modules/make-error-cause": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", - "integrity": "sha512-4TO2Y3HkBnis4c0dxhAgD/jprySYLACf7nwN6V0HAHDx59g12WlRpUmFy1bRHamjGUEEBrEvCq6SUpsEE2lhUg==", + "node_modules/mdn-data": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", + "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "make-error": "^1.2.0" - } + "license": "CC0-1.0" }, - "node_modules/make-fetch-happen": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-15.0.3.tgz", - "integrity": "sha512-iyyEpDty1mwW3dGlYXAJqC/azFn5PPvgKVwXayOGBSmKLxhKZ9fg4qIan2ePpp1vJIwfFiO34LAPZgq9SZW9Aw==", + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/agent": "^4.0.0", - "cacache": "^20.0.1", - "http-cache-semantics": "^4.1.1", - "minipass": "^7.0.2", - "minipass-fetch": "^5.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^1.0.0", - "proc-log": "^6.0.0", - "promise-retry": "^2.0.1", - "ssri": "^13.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } + "license": "MIT" }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", - "dev": true, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "node_modules/memoize-decorator": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/memoize-decorator/-/memoize-decorator-1.0.2.tgz", + "integrity": "sha512-G2vHcq4c+EwnBAOeWCH1mNz99QPCgm4ECjhHOd3SFZm66jVlwhBLdqhCvnHxptaRyZfm8ap3igoeDfrO92+uHQ==", "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" - }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" - } + "license": "MIT" }, - "node_modules/markdown-table": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", - "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "node_modules/meow": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", + "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", "dev": true, "license": "MIT", + "engines": { + "node": ">=18" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/marked": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-17.0.1.tgz", - "integrity": "sha512-boeBdiS0ghpWcSwoNm/jJBwdpFaMnZWRzjA6SkUMYb40SVaN1x7mmfGKp0jvexGcx+7y2La5zRZsYFZI6Qpypg==", + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", "license": "MIT", - "bin": { - "marked": "bin/marked.js" - }, "engines": { - "node": ">= 20" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/marked-shiki": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/marked-shiki/-/marked-shiki-1.2.1.tgz", - "integrity": "sha512-yHxYQhPY5oYaIRnROn98foKhuClark7M373/VpLxiy5TrDu9Jd/LsMwo8w+U91Up4oDb9IXFrP0N1MFRz8W/DQ==", + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, "license": "MIT", - "peerDependencies": { - "marked": ">=7.0.0", - "shiki": ">=1.0.0" + "engines": { + "node": ">= 8" } }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/mathml-tag-names": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", - "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/mdast-util-definitions": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-6.0.0.tgz", - "integrity": "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==", + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "unist-util-visit": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/mdast-util-find-and-replace": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", - "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "escape-string-regexp": "^5.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mdast-util-from-markdown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", - "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-gfm": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", - "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", "dev": true, "license": "MIT", "dependencies": { - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-gfm-autolink-literal": "^2.0.0", - "mdast-util-gfm-footnote": "^2.0.0", - "mdast-util-gfm-strikethrough": "^2.0.0", - "mdast-util-gfm-table": "^2.0.0", - "mdast-util-gfm-task-list-item": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-gfm-autolink-literal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", - "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "ccount": "^2.0.0", "devlop": "^1.0.0", - "mdast-util-find-and-replace": "^3.0.0", - "micromark-util-character": "^2.0.0" + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0" + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-gfm-strikethrough": { + "node_modules/micromark-extension-gfm-tagfilter": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", - "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-gfm-table": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", - "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", "devlop": "^1.0.0", - "markdown-table": "^3.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-gfm-task-list-item": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", - "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/mdast-util-phrasing": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", - "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast": { - "version": "13.2.1", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", - "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/mdast-util-to-markdown": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", - "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/mdast-util-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", - "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdn-data": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", - "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "dev": true, - "license": "MIT" - }, - "node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/memoize-decorator": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/memoize-decorator/-/memoize-decorator-1.0.2.tgz", - "integrity": "sha512-G2vHcq4c+EwnBAOeWCH1mNz99QPCgm4ECjhHOd3SFZm66jVlwhBLdqhCvnHxptaRyZfm8ap3igoeDfrO92+uHQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/meow": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", - "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" } }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], "license": "MIT", - "engines": { - "node": ">= 8" + "dependencies": { + "micromark-util-symbol": "^2.0.0" } }, - "node_modules/micromark": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", - "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", "dev": true, "funding": [ { @@ -17438,29 +16679,15 @@ ], "license": "MIT", "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, - "node_modules/micromark-core-commonmark": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", - "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", "dev": true, "funding": [ { @@ -17474,156 +16701,14 @@ ], "license": "MIT", "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, - "node_modules/micromark-extension-gfm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", - "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "micromark-extension-gfm-autolink-literal": "^2.0.0", - "micromark-extension-gfm-footnote": "^2.0.0", - "micromark-extension-gfm-strikethrough": "^2.0.0", - "micromark-extension-gfm-table": "^2.0.0", - "micromark-extension-gfm-tagfilter": "^2.0.0", - "micromark-extension-gfm-task-list-item": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-autolink-literal": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", - "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", - "dev": true, - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", - "dev": true, - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-strikethrough": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", - "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", - "dev": true, - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-table": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", - "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", - "dev": true, - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-tagfilter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", - "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-task-list-item": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", - "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-factory-destination": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", - "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", "dev": true, "funding": [ { @@ -17637,15 +16722,13 @@ ], "license": "MIT", "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "micromark-util-symbol": "^2.0.0" } }, - "node_modules/micromark-factory-label": { + "node_modules/micromark-util-decode-string": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", - "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", "dev": true, "funding": [ { @@ -17659,17 +16742,16 @@ ], "license": "MIT", "dependencies": { - "devlop": "^1.0.0", + "decode-named-character-reference": "^1.0.0", "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" } }, - "node_modules/micromark-factory-space": { + "node_modules/micromark-util-encode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", - "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", - "dev": true, + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", "funding": [ { "type": "GitHub Sponsors", @@ -17680,16 +16762,12 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } + "license": "MIT" }, - "node_modules/micromark-factory-title": { + "node_modules/micromark-util-html-tag-name": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", - "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", "dev": true, "funding": [ { @@ -17701,18 +16779,12 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } + "license": "MIT" }, - "node_modules/micromark-factory-whitespace": { + "node_modules/micromark-util-normalize-identifier": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", - "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", "dev": true, "funding": [ { @@ -17726,16 +16798,14 @@ ], "license": "MIT", "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" + "micromark-util-symbol": "^2.0.0" } }, - "node_modules/micromark-util-character": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", - "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "dev": true, "funding": [ { "type": "GitHub Sponsors", @@ -17748,15 +16818,13 @@ ], "license": "MIT", "dependencies": { - "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, - "node_modules/micromark-util-chunked": { + "node_modules/micromark-util-sanitize-uri": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", - "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", - "dev": true, + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", "funding": [ { "type": "GitHub Sponsors", @@ -17769,13 +16837,15 @@ ], "license": "MIT", "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, - "node_modules/micromark-util-classify-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", - "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", "dev": true, "funding": [ { @@ -17789,16 +16859,16 @@ ], "license": "MIT", "dependencies": { - "micromark-util-character": "^2.0.0", + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, - "node_modules/micromark-util-combine-extensions": { + "node_modules/micromark-util-symbol": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", - "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", - "dev": true, + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -17809,17 +16879,12 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", - "dependencies": { - "micromark-util-chunked": "^2.0.0", - "micromark-util-types": "^2.0.0" - } + "license": "MIT" }, - "node_modules/micromark-util-decode-numeric-character-reference": { + "node_modules/micromark-util-types": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", - "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", - "dev": true, + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", "funding": [ { "type": "GitHub Sponsors", @@ -17830,195 +16895,20 @@ "url": "https://opencollective.com/unified" } ], + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, "license": "MIT", "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-string": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", - "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-encode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", - "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-html-tag-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", - "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-normalize-identifier": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", - "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-resolve-all": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", - "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", - "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-subtokenize": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", - "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-symbol": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", - "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", - "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" } }, "node_modules/micromatch/node_modules/picomatch": { @@ -18034,19 +16924,6 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/mime-db": { "version": "1.54.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", @@ -18291,19 +17168,6 @@ "dev": true, "license": "MIT" }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, "node_modules/mrmime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", @@ -18452,13 +17316,6 @@ "node": ">= 0.6" } }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true, - "license": "MIT" - }, "node_modules/neotraverse": { "version": "0.6.18", "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.18.tgz", @@ -18480,9 +17337,9 @@ } }, "node_modules/ng-packagr": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/ng-packagr/-/ng-packagr-21.1.0.tgz", - "integrity": "sha512-UlQOhH8DRlaYsBGQMjOYvg70J70hD4i/55NV9vAsYvsxEskmp86xjUtZgEeVKeoLq8tYMjMXDgaYjYde153sZQ==", + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/ng-packagr/-/ng-packagr-21.0.1.tgz", + "integrity": "sha512-IZGxuF226GF0d8FOZIfPvHsyBl53PrDEg/IB2+CVamsm3r4+gUw3mBp27eygpowBpdVLG0Sm2IbUiH4aSspzyA==", "dev": true, "license": "MIT", "dependencies": { @@ -18492,7 +17349,7 @@ "ajv": "^8.17.1", "ansi-colors": "^4.1.3", "browserslist": "^4.26.0", - "chokidar": "^5.0.0", + "chokidar": "^4.0.1", "commander": "^14.0.0", "dependency-graph": "^1.0.0", "esbuild": "^0.27.0", @@ -18518,7 +17375,7 @@ "rollup": "^4.24.0" }, "peerDependencies": { - "@angular/compiler-cli": "^21.0.0 || ^21.1.0-next", + "@angular/compiler-cli": "^21.0.0-next || ^21.0.0", "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0", "tslib": "^2.3.0", "typescript": ">=5.9 <6.0" @@ -18529,3450 +17386,3468 @@ } } }, - "node_modules/ng-packagr/node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "node_modules/ng-packagr/node_modules/@esbuild/aix-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", + "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=6" + "node": ">=18" } }, - "node_modules/nlcst-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz", - "integrity": "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==", + "node_modules/ng-packagr/node_modules/@esbuild/android-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", + "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "@types/nlcst": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" } }, - "node_modules/no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "node_modules/ng-packagr/node_modules/@esbuild/android-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", + "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "lower-case": "^1.1.1" - } - }, - "node_modules/node-addon-api": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", - "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", - "dev": true, - "license": "MIT", - "optional": true + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "node_modules/ng-packagr/node_modules/@esbuild/android-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "node": ">=18" } }, - "node_modules/node-fetch-native": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", - "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "node_modules/ng-packagr/node_modules/@esbuild/darwin-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "node_modules/ng-packagr/node_modules/@esbuild/darwin-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", + "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "node_modules/ng-packagr/node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", + "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "BSD-2-Clause" + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "node_modules/ng-packagr/node_modules/@esbuild/freebsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", + "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" } }, - "node_modules/node-gyp": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-12.1.0.tgz", - "integrity": "sha512-W+RYA8jBnhSr2vrTtlPYPc1K+CSjGpVDRZxcqJcERZ8ND3A1ThWPHRwctTx3qC3oW99jt726jhdz3Y6ky87J4g==", + "node_modules/ng-packagr/node_modules/@esbuild/linux-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", + "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^15.0.0", - "nopt": "^9.0.0", - "proc-log": "^6.0.0", - "semver": "^7.3.5", - "tar": "^7.5.2", - "tinyglobby": "^0.2.12", - "which": "^6.0.0" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=18" } }, - "node_modules/node-gyp-build-optional-packages": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", - "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", + "node_modules/ng-packagr/node_modules/@esbuild/linux-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", "optional": true, - "dependencies": { - "detect-libc": "^2.0.1" - }, - "bin": { - "node-gyp-build-optional-packages": "bin.js", - "node-gyp-build-optional-packages-optional": "optional.js", - "node-gyp-build-optional-packages-test": "build-test.js" + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/node-gyp/node_modules/abbrev": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-4.0.0.tgz", - "integrity": "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==", + "node_modules/ng-packagr/node_modules/@esbuild/linux-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", + "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "cpu": [ + "ia32" + ], "dev": true, - "license": "ISC", + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=18" } }, - "node_modules/node-gyp/node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "node_modules/ng-packagr/node_modules/@esbuild/linux-loong64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", + "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "cpu": [ + "loong64" + ], "dev": true, - "license": "ISC", + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=16" + "node": ">=18" } }, - "node_modules/node-gyp/node_modules/nopt": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-9.0.0.tgz", - "integrity": "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==", + "node_modules/ng-packagr/node_modules/@esbuild/linux-mips64el": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", + "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "cpu": [ + "mips64el" + ], "dev": true, - "license": "ISC", - "dependencies": { - "abbrev": "^4.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=18" } }, - "node_modules/node-gyp/node_modules/which": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-6.0.0.tgz", - "integrity": "sha512-f+gEpIKMR9faW/JgAgPK1D7mekkFoqbmiwvNzuhsHetni20QSgzg9Vhn0g2JSJkkfehQnqdUAx7/e15qS1lPxg==", + "node_modules/ng-packagr/node_modules/@esbuild/linux-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "cpu": [ + "ppc64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=18" } }, - "node_modules/node-mock-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.4.tgz", - "integrity": "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==", + "node_modules/ng-packagr/node_modules/@esbuild/linux-riscv64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "cpu": [ + "riscv64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "node_modules/ng-packagr/node_modules/@esbuild/linux-s390x": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "cpu": [ + "s390x" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "node_modules/ng-packagr/node_modules/@esbuild/linux-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", + "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/now-and-later": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-3.0.0.tgz", - "integrity": "sha512-pGO4pzSdaxhWTGkfSfHx3hVzJVslFPwBp2Myq9MYN/ChfJZF87ochMAXnvz6/58RJSf5ik2q9tXprBBrk2cpcg==", + "node_modules/ng-packagr/node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", + "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "once": "^1.4.0" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">= 10.13.0" + "node": ">=18" } }, - "node_modules/npm-bundled": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-5.0.0.tgz", - "integrity": "sha512-JLSpbzh6UUXIEoqPsYBvVNVmyrjVZ1fzEFbqxKkTJQkWBO3xFzFT+KDnSKQWwOQNbuWRwt5LSD6HOTLGIWzfrw==", + "node_modules/ng-packagr/node_modules/@esbuild/netbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", + "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "npm-normalize-package-bin": "^5.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=18" } }, - "node_modules/npm-install-checks": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-8.0.0.tgz", - "integrity": "sha512-ScAUdMpyzkbpxoNekQ3tNRdFI8SJ86wgKZSQZdUxT+bj0wVFpsEMWnkXP0twVe1gJyNF5apBWDJhhIbgrIViRA==", + "node_modules/ng-packagr/node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", + "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "semver": "^7.1.1" - }, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=18" } }, - "node_modules/npm-normalize-package-bin": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz", - "integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==", + "node_modules/ng-packagr/node_modules/@esbuild/openbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", + "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC", + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=18" } }, - "node_modules/npm-package-arg": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-13.0.2.tgz", - "integrity": "sha512-IciCE3SY3uE84Ld8WZU23gAPPV9rIYod4F+rc+vJ7h7cwAJt9Vk6TVsK60ry7Uj3SRS3bqRRIGuTp9YVlk6WNA==", + "node_modules/ng-packagr/node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", + "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "hosted-git-info": "^9.0.0", - "proc-log": "^6.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^7.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=18" } }, - "node_modules/npm-packlist": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-10.0.3.tgz", - "integrity": "sha512-zPukTwJMOu5X5uvm0fztwS5Zxyvmk38H/LfidkOMt3gbZVCyro2cD/ETzwzVPcWZA3JOyPznfUN/nkyFiyUbxg==", + "node_modules/ng-packagr/node_modules/@esbuild/sunos-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "ignore-walk": "^8.0.0", - "proc-log": "^6.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=18" } }, - "node_modules/npm-pick-manifest": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-11.0.3.tgz", - "integrity": "sha512-buzyCfeoGY/PxKqmBqn1IUJrZnUi1VVJTdSSRPGI60tJdUhUoSQFhs0zycJokDdOznQentgrpf8LayEHyyYlqQ==", + "node_modules/ng-packagr/node_modules/@esbuild/win32-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", + "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "npm-install-checks": "^8.0.0", - "npm-normalize-package-bin": "^5.0.0", - "npm-package-arg": "^13.0.0", - "semver": "^7.3.5" - }, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=18" } }, - "node_modules/npm-registry-fetch": { - "version": "19.1.1", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-19.1.1.tgz", - "integrity": "sha512-TakBap6OM1w0H73VZVDf44iFXsOS3h+L4wVMXmbWOQroZgFhMch0juN6XSzBNlD965yIKvWg2dfu7NSiaYLxtw==", + "node_modules/ng-packagr/node_modules/@esbuild/win32-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", + "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "cpu": [ + "ia32" + ], "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/redact": "^4.0.0", - "jsonparse": "^1.3.1", - "make-fetch-happen": "^15.0.0", - "minipass": "^7.0.2", - "minipass-fetch": "^5.0.0", - "minizlib": "^3.0.1", - "npm-package-arg": "^13.0.0", - "proc-log": "^6.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=18" } }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "node_modules/ng-packagr/node_modules/@esbuild/win32-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", + "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "cpu": [ + "x64" + ], "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "node_modules/ng-packagr/node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/nwsapi": { - "version": "2.2.23", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.23.tgz", - "integrity": "sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "node_modules/ng-packagr/node_modules/esbuild": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", "dev": true, + "hasInstallScript": true, "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, "engines": { - "node": ">=0.10.0" + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.2", + "@esbuild/android-arm": "0.27.2", + "@esbuild/android-arm64": "0.27.2", + "@esbuild/android-x64": "0.27.2", + "@esbuild/darwin-arm64": "0.27.2", + "@esbuild/darwin-x64": "0.27.2", + "@esbuild/freebsd-arm64": "0.27.2", + "@esbuild/freebsd-x64": "0.27.2", + "@esbuild/linux-arm": "0.27.2", + "@esbuild/linux-arm64": "0.27.2", + "@esbuild/linux-ia32": "0.27.2", + "@esbuild/linux-loong64": "0.27.2", + "@esbuild/linux-mips64el": "0.27.2", + "@esbuild/linux-ppc64": "0.27.2", + "@esbuild/linux-riscv64": "0.27.2", + "@esbuild/linux-s390x": "0.27.2", + "@esbuild/linux-x64": "0.27.2", + "@esbuild/netbsd-arm64": "0.27.2", + "@esbuild/netbsd-x64": "0.27.2", + "@esbuild/openbsd-arm64": "0.27.2", + "@esbuild/openbsd-x64": "0.27.2", + "@esbuild/openharmony-arm64": "0.27.2", + "@esbuild/sunos-x64": "0.27.2", + "@esbuild/win32-arm64": "0.27.2", + "@esbuild/win32-ia32": "0.27.2", + "@esbuild/win32-x64": "0.27.2" } }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "node_modules/nlcst-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz", + "integrity": "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==", + "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "@types/nlcst": "^2.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "node_modules/no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "lower-case": "^1.1.1" } }, - "node_modules/object.assign": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "node_modules/node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0", - "has-symbols": "^1.1.0", - "object-keys": "^1.1.1" + "whatwg-url": "^5.0.0" }, "engines": { - "node": ">= 0.4" + "node": "4.x || >=6.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, - "node_modules/object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==", + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "dev": true, "license": "MIT", "dependencies": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" } }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "node_modules/node-gyp": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-12.1.0.tgz", + "integrity": "sha512-W+RYA8jBnhSr2vrTtlPYPc1K+CSjGpVDRZxcqJcERZ8ND3A1ThWPHRwctTx3qC3oW99jt726jhdz3Y6ky87J4g==", "dev": true, "license": "MIT", "dependencies": { - "isobject": "^3.0.1" + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^15.0.0", + "nopt": "^9.0.0", + "proc-log": "^6.0.0", + "semver": "^7.3.5", + "tar": "^7.5.2", + "tinyglobby": "^0.2.12", + "which": "^6.0.0" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" }, "engines": { - "node": ">=0.10.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/ofetch": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz", - "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==", + "node_modules/node-gyp-build-optional-packages": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", + "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "destr": "^2.0.5", - "node-fetch-native": "^1.6.7", - "ufo": "^1.6.1" + "detect-libc": "^2.0.1" + }, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" } }, - "node_modules/ohash": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", - "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "node_modules/node-gyp/node_modules/abbrev": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-4.0.0.tgz", + "integrity": "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==", "dev": true, - "license": "MIT" - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, + "license": "ISC", "engines": { - "node": ">= 0.8" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "node_modules/node-gyp/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, "license": "ISC", - "dependencies": { - "wrappy": "1" + "engines": { + "node": ">=16" } }, - "node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "node_modules/node-gyp/node_modules/nopt": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-9.0.0.tgz", + "integrity": "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "mimic-function": "^5.0.0" + "abbrev": "^4.0.0" }, - "engines": { - "node": ">=18" + "bin": { + "nopt": "bin/nopt.js" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/oniguruma-parser": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz", - "integrity": "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==", - "license": "MIT" - }, - "node_modules/oniguruma-to-es": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.4.tgz", - "integrity": "sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA==", - "license": "MIT", - "dependencies": { - "oniguruma-parser": "^0.12.1", - "regex": "^6.0.1", - "regex-recursion": "^6.0.2" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "node_modules/node-gyp/node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, + "license": "ISC", "engines": { - "node": ">= 0.8.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/ora": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-9.0.0.tgz", - "integrity": "sha512-m0pg2zscbYgWbqRR6ABga5c3sZdEon7bSgjnlXC64kxtxLOyjRcbbUkLj7HFyy/FTD+P2xdBWu8snGhYI0jc4A==", + "node_modules/node-gyp/node_modules/which": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.0.tgz", + "integrity": "sha512-f+gEpIKMR9faW/JgAgPK1D7mekkFoqbmiwvNzuhsHetni20QSgzg9Vhn0g2JSJkkfehQnqdUAx7/e15qS1lPxg==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "chalk": "^5.6.2", - "cli-cursor": "^5.0.0", - "cli-spinners": "^3.2.0", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^2.1.0", - "log-symbols": "^7.0.1", - "stdin-discarder": "^0.2.2", - "string-width": "^8.1.0", - "strip-ansi": "^7.1.2" - }, - "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "isexe": "^3.1.1" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ora/node_modules/string-width": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.0.tgz", - "integrity": "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-east-asian-width": "^1.3.0", - "strip-ansi": "^7.1.0" + "bin": { + "node-which": "bin/which.js" }, "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ordered-binary": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.6.1.tgz", - "integrity": "sha512-QkCdPooczexPLiXIrbVOPYkR3VO3T6v2OyKRkR1Xbhpy7/LAVXwahnRCgRp78Oe/Ehf0C/HATAxfSr6eA1oX+w==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw==", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "^2.0.1" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/ordered-read-streams/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/node-mock-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.4.tgz", + "integrity": "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==", "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } + "license": "MIT" }, - "node_modules/ordered-read-streams/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", "dev": true, "license": "MIT" }, - "node_modules/ordered-read-streams/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/p-limit": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.2.0.tgz", - "integrity": "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==", + "node_modules/now-and-later": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-3.0.0.tgz", + "integrity": "sha512-pGO4pzSdaxhWTGkfSfHx3hVzJVslFPwBp2Myq9MYN/ChfJZF87ochMAXnvz6/58RJSf5ik2q9tXprBBrk2cpcg==", "dev": true, "license": "MIT", "dependencies": { - "yocto-queue": "^1.1.1" + "once": "^1.4.0" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 10.13.0" } }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/npm-bundled": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-4.0.0.tgz", + "integrity": "sha512-IxaQZDMsqfQ2Lz37VvyyEtKLe8FsRZuysmedy/N06TU1RyVppYKXrO4xIhR0F+7ubIBox6Q7nir6fQI3ej39iA==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "p-limit": "^3.0.2" + "npm-normalize-package-bin": "^4.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/npm-install-checks": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-8.0.0.tgz", + "integrity": "sha512-ScAUdMpyzkbpxoNekQ3tNRdFI8SJ86wgKZSQZdUxT+bj0wVFpsEMWnkXP0twVe1gJyNF5apBWDJhhIbgrIViRA==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "yocto-queue": "^0.1.0" + "semver": "^7.1.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/p-locate/node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "node_modules/npm-normalize-package-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", + "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==", "dev": true, - "license": "MIT", + "license": "ISC", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "node_modules/npm-package-arg": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-13.0.1.tgz", + "integrity": "sha512-6zqls5xFvJbgFjB1B2U6yITtyGBjDBORB7suI4zA4T/sZ1OmkMFlaQSNB/4K0LtXNA1t4OprAFxPisadK5O2ag==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "aggregate-error": "^3.0.0" + "hosted-git-info": "^9.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^6.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/p-queue": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.1.tgz", - "integrity": "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==", + "node_modules/npm-packlist": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-10.0.3.tgz", + "integrity": "sha512-zPukTwJMOu5X5uvm0fztwS5Zxyvmk38H/LfidkOMt3gbZVCyro2cD/ETzwzVPcWZA3JOyPznfUN/nkyFiyUbxg==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "eventemitter3": "^5.0.1", - "p-timeout": "^6.1.2" + "ignore-walk": "^8.0.0", + "proc-log": "^6.0.0" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/p-queue/node_modules/eventemitter3": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", - "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "node_modules/npm-packlist/node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", "dev": true, - "license": "MIT" - }, - "node_modules/p-timeout": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.4.tgz", - "integrity": "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==", - "dev": true, - "license": "MIT", + "license": "ISC", "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/pac-proxy-agent": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", - "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", + "node_modules/npm-pick-manifest": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-11.0.3.tgz", + "integrity": "sha512-buzyCfeoGY/PxKqmBqn1IUJrZnUi1VVJTdSSRPGI60tJdUhUoSQFhs0zycJokDdOznQentgrpf8LayEHyyYlqQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@tootallnate/quickjs-emscripten": "^0.23.0", - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "get-uri": "^6.0.1", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.6", - "pac-resolver": "^7.0.1", - "socks-proxy-agent": "^8.0.5" + "npm-install-checks": "^8.0.0", + "npm-normalize-package-bin": "^5.0.0", + "npm-package-arg": "^13.0.0", + "semver": "^7.3.5" }, "engines": { - "node": ">= 14" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/pac-resolver": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", - "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-5.0.0.tgz", + "integrity": "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag==", "dev": true, - "license": "MIT", - "dependencies": { - "degenerator": "^5.0.0", - "netmask": "^2.0.2" - }, + "license": "ISC", "engines": { - "node": ">= 14" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "node_modules/npm-registry-fetch": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-19.1.1.tgz", + "integrity": "sha512-TakBap6OM1w0H73VZVDf44iFXsOS3h+L4wVMXmbWOQroZgFhMch0juN6XSzBNlD965yIKvWg2dfu7NSiaYLxtw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" + "@npmcli/redact": "^4.0.0", + "jsonparse": "^1.3.1", + "make-fetch-happen": "^15.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^5.0.0", + "minizlib": "^3.0.1", + "npm-package-arg": "^13.0.0", + "proc-log": "^6.0.0" }, "engines": { - "node": ">=8" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "node_modules/npm-registry-fetch/node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", "dev": true, - "license": "BlueOak-1.0.0" + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } }, - "node_modules/package-json/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/package-manager-detector": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", - "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nwsapi": { + "version": "2.2.23", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.23.tgz", + "integrity": "sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==", "dev": true, "license": "MIT" }, - "node_modules/pacote": { - "version": "21.0.4", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-21.0.4.tgz", - "integrity": "sha512-RplP/pDW0NNNDh3pnaoIWYPvNenS7UqMbXyvMqJczosiFWTeGGwJC2NQBLqKf4rGLFfwCOnntw1aEp9Jiqm1MA==", + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^7.0.0", - "@npmcli/installed-package-contents": "^4.0.0", - "@npmcli/package-json": "^7.0.0", - "@npmcli/promise-spawn": "^9.0.0", - "@npmcli/run-script": "^10.0.0", - "cacache": "^20.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^7.0.2", - "npm-package-arg": "^13.0.0", - "npm-packlist": "^10.0.1", - "npm-pick-manifest": "^11.0.1", - "npm-registry-fetch": "^19.0.0", - "proc-log": "^6.0.0", - "promise-retry": "^2.0.1", - "sigstore": "^4.0.0", - "ssri": "^13.0.0", - "tar": "^7.4.3" - }, - "bin": { - "pacote": "bin/index.js" - }, + "license": "MIT", "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=0.10.0" } }, - "node_modules/pagefind": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/pagefind/-/pagefind-1.4.0.tgz", - "integrity": "sha512-z2kY1mQlL4J8q5EIsQkLzQjilovKzfNVhX8De6oyE6uHpfFtyBaqUpcl/XzJC/4fjD8vBDyh1zolimIcVrCn9g==", - "dev": true, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "license": "MIT", - "bin": { - "pagefind": "lib/runner/bin.cjs" + "engines": { + "node": ">= 0.4" }, - "optionalDependencies": { - "@pagefind/darwin-arm64": "1.4.0", - "@pagefind/darwin-x64": "1.4.0", - "@pagefind/freebsd-x64": "1.4.0", - "@pagefind/linux-arm64": "1.4.0", - "@pagefind/linux-x64": "1.4.0", - "@pagefind/windows-x64": "1.4.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pako": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", - "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", - "license": "(MIT AND Zlib)" - }, - "node_modules/param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==", + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, "license": "MIT", - "dependencies": { - "no-case": "^2.2.0" + "engines": { + "node": ">= 0.4" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, "license": "MIT", "dependencies": { - "callsites": "^3.0.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", + "node_modules/object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==", "dev": true, "license": "MIT", "dependencies": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" }, "engines": { - "node": ">=0.8" + "node": ">=0.10.0" } }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" + "isobject": "^3.0.1" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/parse-json/node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], "license": "MIT" }, - "node_modules/parse-latin": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz", - "integrity": "sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==", + "node_modules/ofetch": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz", + "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==", "dev": true, "license": "MIT", "dependencies": { - "@types/nlcst": "^2.0.0", - "@types/unist": "^3.0.0", - "nlcst-to-string": "^4.0.0", - "unist-util-modify-children": "^4.0.0", - "unist-util-visit-children": "^3.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "destr": "^2.0.5", + "node-fetch-native": "^1.6.7", + "ufo": "^1.6.1" } }, - "node_modules/parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } + "license": "MIT" }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", - "dev": true, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/parse5": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", - "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", - "dev": true, - "license": "MIT", + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", "dependencies": { - "entities": "^6.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "wrappy": "1" } }, - "node_modules/parse5-html-rewriting-stream": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-8.0.0.tgz", - "integrity": "sha512-wzh11mj8KKkno1pZEu+l2EVeWsuKDfR5KNWZOTsslfUX8lPDZx77m9T0kIoAVkFtD1nx6YF8oh4BnPHvxMtNMw==", + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, "license": "MIT", "dependencies": { - "entities": "^6.0.0", - "parse5": "^8.0.0", - "parse5-sax-parser": "^8.0.0" + "mimic-function": "^5.0.0" }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5-html-rewriting-stream/node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "dev": true, - "license": "BSD-2-Clause", "engines": { - "node": ">=0.12" + "node": ">=18" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse5-html-rewriting-stream/node_modules/parse5": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", - "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", + "node_modules/oniguruma-parser": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz", + "integrity": "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==", + "license": "MIT" + }, + "node_modules/oniguruma-to-es": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.4.tgz", + "integrity": "sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA==", + "license": "MIT", + "dependencies": { + "oniguruma-parser": "^0.12.1", + "regex": "^6.0.1", + "regex-recursion": "^6.0.2" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "license": "MIT", "dependencies": { - "entities": "^6.0.0" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/parse5-sax-parser": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-8.0.0.tgz", - "integrity": "sha512-/dQ8UzHZwnrzs3EvDj6IkKrD/jIZyTlB+8XrHJvcjNgRdmWruNdN9i9RK/JtxakmlUdPwKubKPTCqvbTgzGhrw==", + "node_modules/ora": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-9.0.0.tgz", + "integrity": "sha512-m0pg2zscbYgWbqRR6ABga5c3sZdEon7bSgjnlXC64kxtxLOyjRcbbUkLj7HFyy/FTD+P2xdBWu8snGhYI0jc4A==", "dev": true, "license": "MIT", "dependencies": { - "parse5": "^8.0.0" + "chalk": "^5.6.2", + "cli-cursor": "^5.0.0", + "cli-spinners": "^3.2.0", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.1.0", + "log-symbols": "^7.0.1", + "stdin-discarder": "^0.2.2", + "string-width": "^8.1.0", + "strip-ansi": "^7.1.2" + }, + "engines": { + "node": ">=20" }, "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse5-sax-parser/node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "node_modules/ora/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "engines": { - "node": ">=0.12" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/parse5-sax-parser/node_modules/parse5": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", - "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", + "node_modules/ora/node_modules/string-width": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.0.tgz", + "integrity": "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==", "dev": true, "license": "MIT", "dependencies": { - "entities": "^6.0.0" + "get-east-asian-width": "^1.3.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=20" }, "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse5/node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "node_modules/ordered-binary": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.6.1.tgz", + "integrity": "sha512-QkCdPooczexPLiXIrbVOPYkR3VO3T6v2OyKRkR1Xbhpy7/LAVXwahnRCgRp78Oe/Ehf0C/HATAxfSr6eA1oX+w==", "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "license": "MIT", + "optional": true + }, + "node_modules/ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "^2.0.1" } }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "node_modules/ordered-read-streams/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.8" + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==", + "node_modules/ordered-read-streams/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, "license": "MIT" }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "node_modules/ordered-read-streams/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "safe-buffer": "~5.1.0" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/p-limit": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.2.0.tgz", + "integrity": "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==", "dev": true, "license": "MIT", + "dependencies": { + "yocto-queue": "^1.1.1" + }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", "dependencies": { - "path-root-regex": "^0.1.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==", + "node_modules/p-locate/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "license": "BlueOak-1.0.0", "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=16 || 14 >=14.18" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "node_modules/p-locate/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, - "license": "ISC" - }, - "node_modules/path-to-regexp": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", - "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", "license": "MIT", + "engines": { + "node": ">=10" + }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-type": { + "node_modules/p-map": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true, - "license": "MIT" - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", - "license": "MIT", - "optional": true - }, - "node_modules/piccolore": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/piccolore/-/piccolore-0.1.3.tgz", - "integrity": "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==", - "dev": true, - "license": "ISC" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, "engines": { - "node": ">=12" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=6" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/piscina": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-5.1.4.tgz", - "integrity": "sha512-7uU4ZnKeQq22t9AsmHGD2w4OYQGonwFnTypDypaWi7Qr2EvQIFVtG8J5D/3bE7W123Wdc9+v4CZDu5hJXVCtBg==", + "node_modules/p-queue": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.1.tgz", + "integrity": "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==", "dev": true, "license": "MIT", + "dependencies": { + "eventemitter3": "^5.0.1", + "p-timeout": "^6.1.2" + }, "engines": { - "node": ">=20.x" + "node": ">=18" }, - "optionalDependencies": { - "@napi-rs/nice": "^1.0.4" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pkce-challenge": { + "node_modules/p-queue/node_modules/eventemitter3": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz", - "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=16.20.0" - } + "license": "MIT" }, - "node_modules/pkg-dir": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-8.0.0.tgz", - "integrity": "sha512-4peoBq4Wks0riS0z8741NVv+/8IiTvqnZAr8QGgtdifrtpdXbNw/FxRS1l6NFqm4EMzuS0EDqNNx4XGaz8cuyQ==", + "node_modules/p-timeout": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.4.tgz", + "integrity": "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==", "dev": true, "license": "MIT", - "dependencies": { - "find-up-simple": "^1.0.0" - }, "engines": { - "node": ">=18" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/plugin-error": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", - "integrity": "sha512-WzZHcm4+GO34sjFMxQMqZbsz3xiNEgonCskQ9v+IroMmYgk/tas8dG+Hr2D6IbRPybZ12oWpzE/w3cGJ6FJzOw==", + "node_modules/pac-proxy-agent": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", + "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", "dev": true, "license": "MIT", "dependencies": { - "ansi-cyan": "^0.1.1", - "ansi-red": "^0.1.1", - "arr-diff": "^1.0.1", - "arr-union": "^2.0.1", - "extend-shallow": "^1.1.2" + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.6", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.5" }, "engines": { - "node": ">=0.10.0" + "node": ">= 14" } }, - "node_modules/plugin-error/node_modules/extend-shallow": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", - "integrity": "sha512-L7AGmkO6jhDkEBBGWlLtftA80Xq8DipnrRPr0pyi7GQLXkaq9JYA4xF4z6qnadIC6euiTDKco0cGSU9muw+WTw==", + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", "dev": true, "license": "MIT", "dependencies": { - "kind-of": "^1.1.0" + "degenerator": "^5.0.0", + "netmask": "^2.0.2" }, "engines": { - "node": ">=0.10.0" + "node": ">= 14" } }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "node_modules/package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": ">=8" } }, - "node_modules/postcss-media-query-parser": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", - "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", + "node_modules/package-json/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/package-manager-detector": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", + "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", "dev": true, "license": "MIT" }, - "node_modules/postcss-nested": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", - "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "node_modules/pacote": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-21.0.3.tgz", + "integrity": "sha512-itdFlanxO0nmQv4ORsvA9K1wv40IPfB9OmWqfaJWvoJ30VKyHsqNgDVeG+TVhI7Gk7XW8slUy7cA9r6dF5qohw==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", + "license": "ISC", "dependencies": { - "postcss-selector-parser": "^6.1.1" + "@npmcli/git": "^7.0.0", + "@npmcli/installed-package-contents": "^3.0.0", + "@npmcli/package-json": "^7.0.0", + "@npmcli/promise-spawn": "^8.0.0", + "@npmcli/run-script": "^10.0.0", + "cacache": "^20.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^13.0.0", + "npm-packlist": "^10.0.1", + "npm-pick-manifest": "^11.0.1", + "npm-registry-fetch": "^19.0.0", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", + "sigstore": "^4.0.0", + "ssri": "^12.0.0", + "tar": "^7.4.3" + }, + "bin": { + "pacote": "bin/index.js" }, "engines": { - "node": ">=12.0" + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/pagefind": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/pagefind/-/pagefind-1.4.0.tgz", + "integrity": "sha512-z2kY1mQlL4J8q5EIsQkLzQjilovKzfNVhX8De6oyE6uHpfFtyBaqUpcl/XzJC/4fjD8vBDyh1zolimIcVrCn9g==", + "dev": true, + "license": "MIT", + "bin": { + "pagefind": "lib/runner/bin.cjs" }, - "peerDependencies": { - "postcss": "^8.2.14" + "optionalDependencies": { + "@pagefind/darwin-arm64": "1.4.0", + "@pagefind/darwin-x64": "1.4.0", + "@pagefind/freebsd-x64": "1.4.0", + "@pagefind/linux-arm64": "1.4.0", + "@pagefind/linux-x64": "1.4.0", + "@pagefind/windows-x64": "1.4.0" } }, - "node_modules/postcss-resolve-nested-selector": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", - "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "license": "(MIT AND Zlib)" + }, + "node_modules/param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "no-case": "^2.2.0" + } }, - "node_modules/postcss-safe-parser": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz", - "integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", - "engines": { - "node": ">=18.0" + "dependencies": { + "callsites": "^3.0.0" }, - "peerDependencies": { - "postcss": "^8.4.31" + "engines": { + "node": ">=6" } }, - "node_modules/postcss-scss": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", - "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", + "node_modules/parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss-scss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", - "engines": { - "node": ">=12.0" + "dependencies": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" }, - "peerDependencies": { - "postcss": "^8.4.29" + "engines": { + "node": ">=0.8" } }, - "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "license": "MIT", "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "node_modules/parse-json/node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true, "license": "MIT" }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "node_modules/parse-latin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz", + "integrity": "sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.8.0" + "dependencies": { + "@types/nlcst": "^2.0.0", + "@types/unist": "^3.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-modify-children": "^4.0.0", + "unist-util-visit-children": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">= 0.10" } }, - "node_modules/prettier": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.0.tgz", - "integrity": "sha512-yEPsovQfpxYfgWNhCfECjG5AQaO+K3dp6XERmOepyPDVqcJm+bjyCVO3pmU+nAPe0N5dDvekfGezt/EIiRe1TA==", + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", "dev": true, "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", - "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", "dev": true, "license": "MIT", "dependencies": { - "fast-diff": "^1.1.2" + "entities": "^6.0.0" }, - "engines": { - "node": ">=6.0.0" + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "node_modules/parse5-html-rewriting-stream": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-8.0.0.tgz", + "integrity": "sha512-wzh11mj8KKkno1pZEu+l2EVeWsuKDfR5KNWZOTsslfUX8lPDZx77m9T0kIoAVkFtD1nx6YF8oh4BnPHvxMtNMw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "entities": "^6.0.0", + "parse5": "^8.0.0", + "parse5-sax-parser": "^8.0.0" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/parse5-html-rewriting-stream/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "engines": { - "node": ">=10" + "node": ">=0.12" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/prismjs": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", - "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "node_modules/parse5-html-rewriting-stream/node_modules/parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", + "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/proc-log": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz", - "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==", + "node_modules/parse5-sax-parser": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-8.0.0.tgz", + "integrity": "sha512-/dQ8UzHZwnrzs3EvDj6IkKrD/jIZyTlB+8XrHJvcjNgRdmWruNdN9i9RK/JtxakmlUdPwKubKPTCqvbTgzGhrw==", "dev": true, - "license": "ISC", - "engines": { - "node": "^20.17.0 || >=22.9.0" + "license": "MIT", + "dependencies": { + "parse5": "^8.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "license": "MIT" - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "node_modules/parse5-sax-parser/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "engines": { - "node": ">=0.4.0" + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "node_modules/parse5-sax-parser/node_modules/parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz", + "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==", "dev": true, "license": "MIT", "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" + "entities": "^6.0.0" }, - "engines": { - "node": ">=10" + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "dev": true, - "license": "MIT", - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, + "license": "BSD-2-Clause", "engines": { - "node": ">= 6" + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/property-information": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", - "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "engines": { + "node": ">= 0.8" } }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "node_modules/path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "node_modules/proxy-agent": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", - "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.1", - "https-proxy-agent": "^7.0.6", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.1.0", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.5" - }, "engines": { - "node": ">= 14" + "node": ">=0.10.0" } }, - "node_modules/proxy-agent/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "license": "ISC", + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true, "license": "MIT" }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/psl": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", - "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "node_modules/path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", "dev": true, "license": "MIT", "dependencies": { - "punycode": "^2.3.1" + "path-root-regex": "^0.1.0" }, - "funding": { - "url": "https://github.com/sponsors/lupomontero" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/psl/node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "node_modules/path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/pump": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", - "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", - "dev": true, + "node_modules/path-to-regexp": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, "license": "MIT", - "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/pumpify/node_modules/pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } + "license": "MIT" }, - "node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true, "license": "MIT" }, - "node_modules/punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", - "dev": true, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", "license": "MIT", - "engines": { - "node": ">=6" - } + "optional": true }, - "node_modules/pupa": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", - "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "node_modules/piccolore": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/piccolore/-/piccolore-0.1.3.tgz", + "integrity": "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==", "dev": true, - "license": "MIT", - "dependencies": { - "escape-goat": "^2.0.0" - }, - "engines": { - "node": ">=8" + "license": "ISC" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/puppeteer": { - "version": "24.35.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.35.0.tgz", - "integrity": "sha512-sbjB5JnJ+3nwgSdRM/bqkFXqLxRz/vsz0GRIeTlCk+j+fGpqaF2dId9Qp25rXz9zfhqnN9s0krek1M/C2GDKtA==", + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/piscina": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-5.1.3.tgz", + "integrity": "sha512-0u3N7H4+hbr40KjuVn2uNhOcthu/9usKhnw5vT3J7ply79v3D3M8naI00el9Klcy16x557VsEkkUQaHCWFXC/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.x" + }, + "optionalDependencies": { + "@napi-rs/nice": "^1.0.4" + } + }, + "node_modules/pixelmatch": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-7.1.0.tgz", + "integrity": "sha512-1wrVzJ2STrpmONHKBy228LM1b84msXDUoAzVEl0R8Mz4Ce6EPr+IVtxm8+yvrqLYMHswREkjYFaMxnyGnaY3Ng==", + "dev": true, + "license": "ISC", "dependencies": { - "@puppeteer/browsers": "2.11.1", - "chromium-bidi": "12.0.1", - "cosmiconfig": "^9.0.0", - "devtools-protocol": "0.0.1534754", - "puppeteer-core": "24.35.0", - "typed-query-selector": "^2.12.0" + "pngjs": "^7.0.0" }, "bin": { - "puppeteer": "lib/cjs/puppeteer/node/cli.js" + "pixelmatch": "bin/pixelmatch" + } + }, + "node_modules/pkce-challenge": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz", + "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/pkg-dir": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-8.0.0.tgz", + "integrity": "sha512-4peoBq4Wks0riS0z8741NVv+/8IiTvqnZAr8QGgtdifrtpdXbNw/FxRS1l6NFqm4EMzuS0EDqNNx4XGaz8cuyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up-simple": "^1.0.0" }, "engines": { "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/puppeteer-core": { - "version": "24.35.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.35.0.tgz", - "integrity": "sha512-vt1zc2ME0kHBn7ZDOqLvgvrYD5bqNv5y2ZNXzYnCv8DEtZGw/zKhljlrGuImxptZ4rq+QI9dFGrUIYqG4/IQzA==", + "node_modules/playwright": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.57.0.tgz", + "integrity": "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { - "@puppeteer/browsers": "2.11.1", - "chromium-bidi": "12.0.1", - "debug": "^4.4.3", - "devtools-protocol": "0.0.1534754", - "typed-query-selector": "^2.12.0", - "webdriver-bidi-protocol": "0.3.10", - "ws": "^8.19.0" + "playwright-core": "1.57.0" + }, + "bin": { + "playwright": "cli.js" }, "engines": { "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" } }, - "node_modules/puppeteer-core/node_modules/ws": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", - "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "node_modules/playwright-core": { + "version": "1.57.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.57.0.tgz", + "integrity": "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "license": "Apache-2.0", + "peer": true, + "bin": { + "playwright-core": "cli.js" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "engines": { + "node": ">=18" } }, - "node_modules/q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", - "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, + "hasInstallScript": true, "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/qified": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/qified/-/qified-0.6.0.tgz", - "integrity": "sha512-tsSGN1x3h569ZSU1u6diwhltLyfUWDp3YbFHedapTmpBl0B3P6U3+Qptg7xu+v+1io1EwhdPyyRHYbEw0KN2FA==", + "node_modules/plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha512-WzZHcm4+GO34sjFMxQMqZbsz3xiNEgonCskQ9v+IroMmYgk/tas8dG+Hr2D6IbRPybZ12oWpzE/w3cGJ6FJzOw==", "dev": true, "license": "MIT", "dependencies": { - "hookified": "^1.14.0" + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" }, "engines": { - "node": ">=20" + "node": ">=0.10.0" } }, - "node_modules/qjobs": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", - "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "node_modules/plugin-error/node_modules/extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha512-L7AGmkO6jhDkEBBGWlLtftA80Xq8DipnrRPr0pyi7GQLXkaq9JYA4xF4z6qnadIC6euiTDKco0cGSU9muw+WTw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.9" - } - }, - "node_modules/qs": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", - "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", - "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.1.0" + "kind-of": "^1.1.0" }, "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "node_modules/pngjs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", + "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=14.19.0" + } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, "funding": [ { - "type": "github", - "url": "https://github.com/sponsors/feross" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" }, { - "type": "patreon", - "url": "https://www.patreon.com/feross" + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" }, { - "type": "consulting", - "url": "https://feross.org/support" + "type": "github", + "url": "https://github.com/sponsors/ai" } ], - "license": "MIT" - }, - "node_modules/radix3": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", - "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==", - "dev": true, - "license": "MIT" - }, - "node_modules/raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", "license": "MIT", - "optional": true, "dependencies": { - "performance-now": "^2.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, "engines": { - "node": ">= 0.6" + "node": "^10 || ^12 || >=14" } }, - "node_modules/raw-body": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", - "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "node_modules/postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", + "dev": true, + "license": "MIT" + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", "dependencies": { - "bytes": "~3.1.2", - "http-errors": "~2.0.1", - "iconv-lite": "~0.7.0", - "unpipe": "~1.0.0" + "postcss-selector-parser": "^6.1.1" }, "engines": { - "node": ">= 0.10" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "node": ">=12.0" }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, - "license": "ISC" - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" + "peerDependencies": { + "postcss": "^8.2.14" } }, - "node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "node_modules/postcss-resolve-nested-selector": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", + "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", "dev": true, "license": "MIT" }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "node_modules/postcss-safe-parser": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz", + "integrity": "sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-safe-parser" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, "engines": { - "node": ">= 6" + "node": ">=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" } }, - "node_modules/readdirp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", - "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "node_modules/postcss-scss": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", + "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss-scss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", "engines": { - "node": ">= 20.19.0" + "node": ">=12.0" }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" + "peerDependencies": { + "postcss": "^8.4.29" } }, - "node_modules/rechoir": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", - "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "dev": true, "license": "MIT", "dependencies": { - "resolve": "^1.20.0" + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" }, "engines": { - "node": ">= 10.13.0" + "node": ">=4" } }, - "node_modules/reflect-metadata": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", - "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true, - "license": "Apache-2.0" + "license": "MIT" }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, "license": "MIT", - "optional": true + "engines": { + "node": ">= 0.8.0" + } }, - "node_modules/regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", - "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", + "node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "dev": true, "license": "MIT", - "dependencies": { - "regex-utilities": "^2.3.0" + "engines": { + "node": ">=4" } }, - "node_modules/regex-recursion": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", - "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", + "node_modules/prettier": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz", + "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", + "dev": true, "license": "MIT", - "dependencies": { - "regex-utilities": "^2.3.0" + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/regex-utilities": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", - "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", - "license": "MIT" - }, - "node_modules/registry-auth-token": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", - "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", + "node_modules/prettier-linter-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", + "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", "dev": true, "license": "MIT", "dependencies": { - "rc": "1.2.8" + "fast-diff": "^1.1.2" }, "engines": { "node": ">=6.0.0" } }, - "node_modules/registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "license": "MIT", "dependencies": { - "rc": "^1.2.8" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/rehype": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.2.tgz", - "integrity": "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==", + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "rehype-parse": "^9.0.0", - "rehype-stringify": "^10.0.0", - "unified": "^11.0.0" + "engines": { + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/rehype-expressive-code": { - "version": "0.40.2", - "resolved": "https://registry.npmjs.org/rehype-expressive-code/-/rehype-expressive-code-0.40.2.tgz", - "integrity": "sha512-+kn+AMGCrGzvtH8Q5lC6Y5lnmTV/r33fdmi5QU/IH1KPHKobKr5UnLwJuqHv5jBTSN/0v2wLDS7RTM73FVzqmQ==", + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", "dev": true, "license": "MIT", - "dependencies": { - "expressive-code": "^0.40.2" + "engines": { + "node": ">=6" } }, - "node_modules/rehype-parse": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", - "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==", + "node_modules/proc-log": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz", + "integrity": "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==", "dev": true, - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-from-html": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/rehype-raw": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", - "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true, - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-raw": "^9.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } + "license": "MIT" }, - "node_modules/rehype-stringify": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", - "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==", + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true, "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-to-html": "^9.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=0.4.0" } }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "dev": true, "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, "engines": { - "node": ">= 0.10" + "node": ">=10" } }, - "node_modules/remark-gfm": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", - "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-gfm": "^3.0.0", - "micromark-extension-gfm": "^3.0.0", - "remark-parse": "^11.0.0", - "remark-stringify": "^11.0.0", - "unified": "^11.0.0" + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">= 6" } }, - "node_modules/remark-parse": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", - "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", - "dev": true, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unified": "^11.0.0" - }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/remark-rehype": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", - "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", - "dev": true, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "license": "MIT", "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "mdast-util-to-hast": "^13.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">= 0.10" } }, - "node_modules/remark-smartypants": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-3.0.2.tgz", - "integrity": "sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==", + "node_modules/proxy-agent": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", + "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", "dev": true, "license": "MIT", "dependencies": { - "retext": "^9.0.0", - "retext-smartypants": "^6.0.0", - "unified": "^11.0.4", - "unist-util-visit": "^5.0.0" + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.6", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.1.0", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.5" }, "engines": { - "node": ">=16.0.0" + "node": ">= 14" } }, - "node_modules/remark-stringify": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", - "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "node_modules/proxy-agent/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true, + "license": "MIT" + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/psl": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", "dev": true, "license": "MIT", "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-to-markdown": "^2.0.0", - "unified": "^11.0.0" + "punycode": "^2.3.1" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/lupomontero" } }, - "node_modules/remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "node_modules/psl/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", - "dependencies": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha512-wigO8/O08XHb8YPzpDDT+QmRANfW6vLqxfaXm1YXhnFf3AkSLyjfG3GEFg4McZkmgL7KvCj5u2KczkvSP6NfHA==", + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", "dev": true, "license": "MIT", "dependencies": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - }, - "engines": { - "node": ">= 0.10" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", - "dev": true, - "license": "ISC" - }, - "node_modules/replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.10" + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" } }, - "node_modules/replace-homedir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-2.0.0.tgz", - "integrity": "sha512-bgEuQQ/BHW0XkkJtawzrfzHFSN70f/3cNOiHa2QsYxqrjaC30X1k74FJ6xswVBP0sr0SpGIdVFuPwfrYziVeyw==", + "node_modules/pumpify/node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 10.13.0" + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "node_modules/pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", "dev": true, "license": "MIT", + "dependencies": { + "escape-goat": "^2.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/resolve": { - "version": "1.22.11", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "node_modules/puppeteer": { + "version": "24.35.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.35.0.tgz", + "integrity": "sha512-sbjB5JnJ+3nwgSdRM/bqkFXqLxRz/vsz0GRIeTlCk+j+fGpqaF2dId9Qp25rXz9zfhqnN9s0krek1M/C2GDKtA==", "dev": true, - "license": "MIT", + "hasInstallScript": true, + "license": "Apache-2.0", "dependencies": { - "is-core-module": "^2.16.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "@puppeteer/browsers": "2.11.1", + "chromium-bidi": "12.0.1", + "cosmiconfig": "^9.0.0", + "devtools-protocol": "0.0.1534754", + "puppeteer-core": "24.35.0", + "typed-query-selector": "^2.12.0" }, "bin": { - "resolve": "bin/resolve" + "puppeteer": "lib/cjs/puppeteer/node/cli.js" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "node_modules/puppeteer-core": { + "version": "24.35.0", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.35.0.tgz", + "integrity": "sha512-vt1zc2ME0kHBn7ZDOqLvgvrYD5bqNv5y2ZNXzYnCv8DEtZGw/zKhljlrGuImxptZ4rq+QI9dFGrUIYqG4/IQzA==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" + "@puppeteer/browsers": "2.11.1", + "chromium-bidi": "12.0.1", + "debug": "^4.4.3", + "devtools-protocol": "0.0.1534754", + "typed-query-selector": "^2.12.0", + "webdriver-bidi-protocol": "0.3.10", + "ws": "^8.19.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "node_modules/puppeteer-core/node_modules/ws": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", + "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/resolve-options": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-2.0.0.tgz", - "integrity": "sha512-/FopbmmFOQCfsCx77BRFdKOniglTiHumLgwvd6IDPihy1GKkadZbgQJBcTb2lMzSR1pndzd96b1nZrreZ7+9/A==", + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", "dev": true, "license": "MIT", - "dependencies": { - "value-or-function": "^4.0.0" - }, "engines": { - "node": ">= 10.13.0" + "node": ">=0.6.0", + "teleport": ">=0.2.0" } }, - "node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "node_modules/qified": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/qified/-/qified-0.5.3.tgz", + "integrity": "sha512-kXuQdQTB6oN3KhI6V4acnBSZx8D2I4xzZvn9+wFLLFCoBNQY/sFnCW6c43OL7pOQ2HvGV4lnWIXNmgfp7cTWhQ==", "dev": true, "license": "MIT", "dependencies": { - "lowercase-keys": "^1.0.0" + "hookified": "^1.13.0" + }, + "engines": { + "node": ">=20" } }, - "node_modules/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", - "dev": true, - "license": "MIT", + "node_modules/qs": { + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", + "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "license": "BSD-3-Clause", "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" + "side-channel": "^1.1.0" }, "engines": { - "node": ">=18" + "node": ">=0.6" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/retext": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz", - "integrity": "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==", + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/radix3": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", + "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", "license": "MIT", + "optional": true, "dependencies": { - "@types/nlcst": "^2.0.0", - "retext-latin": "^4.0.0", - "retext-stringify": "^4.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "performance-now": "^2.1.0" } }, - "node_modules/retext-latin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-4.0.0.tgz", - "integrity": "sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==", - "dev": true, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "license": "MIT", - "dependencies": { - "@types/nlcst": "^2.0.0", - "parse-latin": "^7.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">= 0.6" } }, - "node_modules/retext-smartypants": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.2.0.tgz", - "integrity": "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==", - "dev": true, + "node_modules/raw-body": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", "license": "MIT", "dependencies": { - "@types/nlcst": "^2.0.0", - "nlcst-to-string": "^4.0.0", - "unist-util-visit": "^5.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">= 0.10" } }, - "node_modules/retext-stringify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-4.0.0.tgz", - "integrity": "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==", + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, - "license": "MIT", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", "dependencies": { - "@types/nlcst": "^2.0.0", - "nlcst-to-string": "^4.0.0", - "unified": "^11.0.0" + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "bin": { + "rc": "cli.js" } }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "node_modules/rc/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } + "license": "ISC" }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true, "license": "MIT", "engines": { - "iojs": ">=1.0.0", "node": ">=0.10.0" } }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true, - "license": "MIT" - }, - "node_modules/rgbcolor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", - "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", - "license": "MIT OR SEE LICENSE IN FEEL-FREE.md", - "optional": true, - "engines": { - "node": ">= 0.8.15" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "license": "MIT" }, - "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, + "license": "MIT", "engines": { - "node": "*" + "node": ">= 14.18.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "resolve": "^1.20.0" }, "engines": { - "node": "*" + "node": ">= 10.13.0" } }, - "node_modules/rolldown": { - "version": "1.0.0-beta.58", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-beta.58.tgz", - "integrity": "sha512-v1FCjMZCan7f+xGAHBi+mqiE4MlH7I+SXEHSQSJoMOGNNB2UYtvMiejsq9YuUOiZjNeUeV/a21nSFbrUR+4ZCQ==", + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", "dev": true, + "license": "Apache-2.0" + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "license": "MIT", + "optional": true + }, + "node_modules/regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", + "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.106.0", - "@rolldown/pluginutils": "1.0.0-beta.58" - }, - "bin": { - "rolldown": "bin/cli.mjs" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.0-beta.58", - "@rolldown/binding-darwin-arm64": "1.0.0-beta.58", - "@rolldown/binding-darwin-x64": "1.0.0-beta.58", - "@rolldown/binding-freebsd-x64": "1.0.0-beta.58", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.58", - "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.58", - "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.58", - "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.58", - "@rolldown/binding-linux-x64-musl": "1.0.0-beta.58", - "@rolldown/binding-openharmony-arm64": "1.0.0-beta.58", - "@rolldown/binding-wasm32-wasi": "1.0.0-beta.58", - "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.58", - "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.58" + "regex-utilities": "^2.3.0" } }, - "node_modules/rollup": { - "version": "4.55.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.3.tgz", - "integrity": "sha512-y9yUpfQvetAjiDLtNMf1hL9NXchIJgWt6zIKeoB+tCd3npX08Eqfzg60V9DhIGVMtQ0AlMkFw5xa+AQ37zxnAA==", + "node_modules/regex-recursion": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", + "license": "MIT" + }, + "node_modules/registry-auth-token": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", + "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" + "rc": "1.2.8" }, "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.55.3", - "@rollup/rollup-android-arm64": "4.55.3", - "@rollup/rollup-darwin-arm64": "4.55.3", - "@rollup/rollup-darwin-x64": "4.55.3", - "@rollup/rollup-freebsd-arm64": "4.55.3", - "@rollup/rollup-freebsd-x64": "4.55.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.55.3", - "@rollup/rollup-linux-arm-musleabihf": "4.55.3", - "@rollup/rollup-linux-arm64-gnu": "4.55.3", - "@rollup/rollup-linux-arm64-musl": "4.55.3", - "@rollup/rollup-linux-loong64-gnu": "4.55.3", - "@rollup/rollup-linux-loong64-musl": "4.55.3", - "@rollup/rollup-linux-ppc64-gnu": "4.55.3", - "@rollup/rollup-linux-ppc64-musl": "4.55.3", - "@rollup/rollup-linux-riscv64-gnu": "4.55.3", - "@rollup/rollup-linux-riscv64-musl": "4.55.3", - "@rollup/rollup-linux-s390x-gnu": "4.55.3", - "@rollup/rollup-linux-x64-gnu": "4.55.3", - "@rollup/rollup-linux-x64-musl": "4.55.3", - "@rollup/rollup-openbsd-x64": "4.55.3", - "@rollup/rollup-openharmony-arm64": "4.55.3", - "@rollup/rollup-win32-arm64-msvc": "4.55.3", - "@rollup/rollup-win32-ia32-msvc": "4.55.3", - "@rollup/rollup-win32-x64-gnu": "4.55.3", - "@rollup/rollup-win32-x64-msvc": "4.55.3", - "fsevents": "~2.3.2" + "node": ">=6.0.0" } }, - "node_modules/rollup-plugin-dts": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-6.3.0.tgz", - "integrity": "sha512-d0UrqxYd8KyZ6i3M2Nx7WOMy708qsV/7fTHMHxCMCBOAe3V/U7OMPu5GkX8hC+cmkHhzGnfeYongl1IgiooddA==", + "node_modules/registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", "dev": true, - "license": "LGPL-3.0-only", + "license": "MIT", "dependencies": { - "magic-string": "^0.30.21" + "rc": "^1.2.8" }, "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/Swatinem" - }, - "optionalDependencies": { - "@babel/code-frame": "^7.27.1" - }, - "peerDependencies": { - "rollup": "^3.29.4 || ^4", - "typescript": "^4.5 || ^5.0" + "node": ">=8" } }, - "node_modules/router": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", - "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "node_modules/rehype": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.2.tgz", + "integrity": "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==", + "dev": true, "license": "MIT", "dependencies": { - "debug": "^4.4.0", - "depd": "^2.0.0", - "is-promise": "^4.0.0", - "parseurl": "^1.3.3", - "path-to-regexp": "^8.0.0" + "@types/hast": "^3.0.0", + "rehype-parse": "^9.0.0", + "rehype-stringify": "^10.0.0", + "unified": "^11.0.0" }, - "engines": { - "node": ">= 18" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/rrweb-cssom": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", - "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", + "node_modules/rehype-expressive-code": { + "version": "0.40.2", + "resolved": "https://registry.npmjs.org/rehype-expressive-code/-/rehype-expressive-code-0.40.2.tgz", + "integrity": "sha512-+kn+AMGCrGzvtH8Q5lC6Y5lnmTV/r33fdmi5QU/IH1KPHKobKr5UnLwJuqHv5jBTSN/0v2wLDS7RTM73FVzqmQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "expressive-code": "^0.40.2" + } }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "node_modules/rehype-parse": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", + "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], "license": "MIT", "dependencies": { - "queue-microtask": "^1.2.2" + "@types/hast": "^3.0.0", + "hast-util-from-html": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/rxjs": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", - "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", - "license": "Apache-2.0", + "node_modules/rehype-raw": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", + "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", + "dev": true, + "license": "MIT", "dependencies": { - "tslib": "^2.1.0" + "@types/hast": "^3.0.0", + "hast-util-raw": "^9.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "node_modules/rehype-stringify": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", + "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" + "@types/hast": "^3.0.0", + "hast-util-to-html": "^9.0.0", + "unified": "^11.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/safe-wipe": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/safe-wipe/-/safe-wipe-0.2.5.tgz", - "integrity": "sha512-MwTNf4YrRqCHsB5jUzOVdXoRbW4jkhgTvhlyfiaxox8EP7cOCiD4ydMOQCxDPR9KpvwdBSM2dQHScV1m85k8wQ==", + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", "dev": true, - "license": "Unlicense", - "dependencies": { - "extend": "^3.0.2", - "q": "1.*", - "rimraf": "2.*" + "license": "MIT", + "engines": { + "node": ">= 0.10" } }, - "node_modules/safe-wipe/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/remark-gfm": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/safe-wipe/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" }, - "engines": { - "node": "*" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/safe-wipe/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/remark-smartypants": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-3.0.2.tgz", + "integrity": "sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "retext": "^9.0.0", + "retext-smartypants": "^6.0.0", + "unified": "^11.0.4", + "unist-util-visit": "^5.0.0" }, "engines": { - "node": "*" + "node": ">=16.0.0" } }, - "node_modules/safe-wipe/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "glob": "^7.1.3" + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" }, - "bin": { - "rimraf": "bin.js" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" - }, - "node_modules/sass": { - "version": "1.97.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.97.1.tgz", - "integrity": "sha512-uf6HoO8fy6ClsrShvMgaKUn14f2EHQLQRtpsZZLeU/Mv0Q1K5P0+x2uvH6Cub39TVVbWNSrraUhDAoFph6vh0A==", + "node_modules/remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", "dev": true, "license": "MIT", "dependencies": { - "chokidar": "^4.0.0", - "immutable": "^5.0.2", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" }, "engines": { - "node": ">=14.0.0" - }, - "optionalDependencies": { - "@parcel/watcher": "^2.4.1" + "node": ">=0.10.0" } }, - "node_modules/sass-convert": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/sass-convert/-/sass-convert-0.5.2.tgz", - "integrity": "sha512-eV9wXZg7MrHmnKLD6WojC/WX7lhLm+PSSLrOukzRIECa04fGbkmFDO9Ot9/82KjzSe+VEClYe9WDKzCuBz30Dg==", + "node_modules/remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha512-wigO8/O08XHb8YPzpDDT+QmRANfW6vLqxfaXm1YXhnFf3AkSLyjfG3GEFg4McZkmgL7KvCj5u2KczkvSP6NfHA==", "dev": true, - "license": "Unlicense", + "license": "MIT", "dependencies": { - "concat-stream": "^1.4.7", - "dargs": "^4.0.0", - "ends-with": "^0.2.0", - "es6-denodeify": "^0.1.0", - "es6-promise": "^3.0.2", - "memoize-decorator": "^1.0.2", - "object-assign": "^3.0.0", - "semver": "^5.0.1", - "semver-regex": "^1.0.0", - "through2": "^2.0.0", - "which": "^1.0.5" + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" }, "engines": { - "node": ">=0.10.0", - "npm": ">=2.1.0" + "node": ">= 0.10" } }, - "node_modules/sass-convert/node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true, + "license": "ISC" + }, + "node_modules/replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", "dev": true, - "engines": [ - "node >= 0.8" - ], "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "engines": { + "node": ">= 0.10" } }, - "node_modules/sass-convert/node_modules/object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha512-jHP15vXVGeVh1HuaA2wY6lxk+whK/x4KBG88VXeRma7CCun7iGD5qPc4eYykQ9sdQvg8jkwFKsSxHln2ybW3xQ==", + "node_modules/replace-homedir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-2.0.0.tgz", + "integrity": "sha512-bgEuQQ/BHW0XkkJtawzrfzHFSN70f/3cNOiHa2QsYxqrjaC30X1k74FJ6xswVBP0sr0SpGIdVFuPwfrYziVeyw==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 10.13.0" } }, - "node_modules/sass-convert/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/sass-convert/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true, "license": "MIT" }, - "node_modules/sass-convert/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", "dev": true, - "license": "ISC", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, "bin": { - "semver": "bin/semver" + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/sass-convert/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", "dev": true, "license": "MIT", "dependencies": { - "safe-buffer": "~5.1.0" + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/sass-convert/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" + "license": "MIT", + "engines": { + "node": ">=4" } }, - "node_modules/sass-embedded": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.97.2.tgz", - "integrity": "sha512-lKJcskySwAtJ4QRirKrikrWMFa2niAuaGenY2ElHjd55IwHUiur5IdKu6R1hEmGYMs4Qm+6rlRW0RvuAkmcryg==", + "node_modules/resolve-options": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-2.0.0.tgz", + "integrity": "sha512-/FopbmmFOQCfsCx77BRFdKOniglTiHumLgwvd6IDPihy1GKkadZbgQJBcTb2lMzSR1pndzd96b1nZrreZ7+9/A==", "dev": true, "license": "MIT", "dependencies": { - "@bufbuild/protobuf": "^2.5.0", - "buffer-builder": "^0.2.0", - "colorjs.io": "^0.5.0", - "immutable": "^5.0.2", - "rxjs": "^7.4.0", - "supports-color": "^8.1.1", - "sync-child-process": "^1.0.2", - "varint": "^6.0.0" - }, - "bin": { - "sass": "dist/bin/sass.js" + "value-or-function": "^4.0.0" }, "engines": { - "node": ">=16.0.0" - }, - "optionalDependencies": { - "sass-embedded-all-unknown": "1.97.2", - "sass-embedded-android-arm": "1.97.2", - "sass-embedded-android-arm64": "1.97.2", - "sass-embedded-android-riscv64": "1.97.2", - "sass-embedded-android-x64": "1.97.2", - "sass-embedded-darwin-arm64": "1.97.2", - "sass-embedded-darwin-x64": "1.97.2", - "sass-embedded-linux-arm": "1.97.2", - "sass-embedded-linux-arm64": "1.97.2", - "sass-embedded-linux-musl-arm": "1.97.2", - "sass-embedded-linux-musl-arm64": "1.97.2", - "sass-embedded-linux-musl-riscv64": "1.97.2", - "sass-embedded-linux-musl-x64": "1.97.2", - "sass-embedded-linux-riscv64": "1.97.2", - "sass-embedded-linux-x64": "1.97.2", - "sass-embedded-unknown-all": "1.97.2", - "sass-embedded-win32-arm64": "1.97.2", - "sass-embedded-win32-x64": "1.97.2" + "node": ">= 10.13.0" } }, - "node_modules/sass-embedded-all-unknown": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass-embedded-all-unknown/-/sass-embedded-all-unknown-1.97.2.tgz", - "integrity": "sha512-Fj75+vOIDv1T/dGDwEpQ5hgjXxa2SmMeShPa8yrh2sUz1U44bbmY4YSWPCdg8wb7LnwiY21B2KRFM+HF42yO4g==", - "cpu": [ - "!arm", - "!arm64", - "!riscv64", - "!x64" - ], + "node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "sass": "1.97.2" + "lowercase-keys": "^1.0.0" } }, - "node_modules/sass-embedded-all-unknown/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "readdirp": "^4.0.1" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": ">= 14.16.0" + "node": ">=18" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/sass-embedded-all-unknown/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "node_modules/retext": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz", + "integrity": "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==", "dev": true, "license": "MIT", - "optional": true, - "engines": { - "node": ">= 14.18.0" + "dependencies": { + "@types/nlcst": "^2.0.0", + "retext-latin": "^4.0.0", + "retext-stringify": "^4.0.0", + "unified": "^11.0.0" }, "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/sass-embedded-all-unknown/node_modules/sass": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.97.2.tgz", - "integrity": "sha512-y5LWb0IlbO4e97Zr7c3mlpabcbBtS+ieiZ9iwDooShpFKWXf62zz5pEPdwrLYm+Bxn1fnbwFGzHuCLSA9tBmrw==", + "node_modules/retext-latin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-4.0.0.tgz", + "integrity": "sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "chokidar": "^4.0.0", - "immutable": "^5.0.2", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=14.0.0" + "@types/nlcst": "^2.0.0", + "parse-latin": "^7.0.0", + "unified": "^11.0.0" }, - "optionalDependencies": { - "@parcel/watcher": "^2.4.1" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/sass-embedded-android-arm": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.97.2.tgz", - "integrity": "sha512-BPT9m19ttY0QVHYYXRa6bmqmS3Fa2EHByNUEtSVcbm5PkIk1ntmYkG9fn5SJpIMbNmFDGwHx+pfcZMmkldhnRg==", - "cpu": [ - "arm" - ], + "node_modules/retext-smartypants": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.2.0.tgz", + "integrity": "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=14.0.0" + "dependencies": { + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/sass-embedded-android-arm64": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.97.2.tgz", - "integrity": "sha512-pF6I+R5uThrscd3lo9B3DyNTPyGFsopycdx0tDAESN6s+dBbiRgNgE4Zlpv50GsLocj/lDLCZaabeTpL3ubhYA==", - "cpu": [ - "arm64" - ], + "node_modules/retext-stringify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-4.0.0.tgz", + "integrity": "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=14.0.0" + "dependencies": { + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/sass-embedded-android-riscv64": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.97.2.tgz", - "integrity": "sha512-fprI8ZTJdz+STgARhg8zReI2QhhGIT9G8nS7H21kc3IkqPRzhfaemSxEtCqZyvDbXPcgYiDLV7AGIReHCuATog==", - "cpu": [ - "riscv64" - ], + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=14.0.0" + "node": ">= 4" } }, - "node_modules/sass-embedded-android-x64": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.97.2.tgz", - "integrity": "sha512-RswwSjURZxupsukEmNt2t6RGvuvIw3IAD5sDq1Pc65JFvWFY3eHqCmH0lG0oXqMg6KJcF0eOxHOp2RfmIm2+4w==", - "cpu": [ - "x64" - ], + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=14.0.0" + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "node_modules/sass-embedded-darwin-arm64": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.97.2.tgz", - "integrity": "sha512-xcsZNnU1XZh21RE/71OOwNqPVcGBU0qT9A4k4QirdA34+ts9cDIaR6W6lgHOBR/Bnnu6w6hXJR4Xth7oFrefPA==", - "cpu": [ - "arm64" - ], + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=14.0.0" - } + "license": "MIT" }, - "node_modules/sass-embedded-darwin-x64": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.97.2.tgz", - "integrity": "sha512-T/9DTMpychm6+H4slHCAsYJRJ6eM+9H9idKlBPliPrP4T8JdC2Cs+ZOsYqrObj6eOtAD0fGf+KgyNhnW3xVafA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", + "node_modules/rgbcolor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", + "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", + "license": "MIT OR SEE LICENSE IN FEEL-FREE.md", "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": ">=14.0.0" + "node": ">= 0.8.15" } }, - "node_modules/sass-embedded-linux-arm": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.97.2.tgz", - "integrity": "sha512-yDRe1yifGHl6kibkDlRIJ2ZzAU03KJ1AIvsAh4dsIDgK5jx83bxZLV1ZDUv7a8KK/iV/80LZnxnu/92zp99cXQ==", - "cpu": [ - "arm" - ], + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/sass-embedded-linux-arm64": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.97.2.tgz", - "integrity": "sha512-Wh+nQaFer9tyE5xBPv5murSUZE/+kIcg8MyL5uqww6be9Iq+UmZpcJM7LUk+q8klQ9LfTmoDSNFA74uBqxD6IA==", - "cpu": [ - "arm64" - ], + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/sass-embedded-linux-musl-arm": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.97.2.tgz", - "integrity": "sha512-GIO6xfAtahJAWItvsXZ3MD1HM6s8cKtV1/HL088aUpKJaw/2XjTCveiOO2AdgMpLNztmq9DZ1lx5X5JjqhS45g==", - "cpu": [ - "arm" - ], + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, "engines": { - "node": ">=14.0.0" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/sass-embedded-linux-musl-arm64": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.97.2.tgz", - "integrity": "sha512-NfUqZSjHwnHvpSa7nyNxbWfL5obDjNBqhHUYmqbHUcmqBpFfHIQsUPgXME9DKn1yBlBc3mWnzMxRoucdYTzd2Q==", - "cpu": [ - "arm64" - ], + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=14.0.0" + "node": "*" } }, - "node_modules/sass-embedded-linux-musl-riscv64": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.97.2.tgz", - "integrity": "sha512-qtM4dJ5gLfvyTZ3QencfNbsTEShIWImSEpkThz+Y2nsCMbcMP7/jYOA03UWgPfEOKSehQQ7EIau7ncbFNoDNPQ==", - "cpu": [ - "riscv64" - ], + "node_modules/rolldown": { + "version": "1.0.0-beta.47", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-beta.47.tgz", + "integrity": "sha512-Mid74GckX1OeFAOYz9KuXeWYhq3xkXbMziYIC+ULVdUzPTG9y70OBSBQDQn9hQP8u/AfhuYw1R0BSg15nBI4Dg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@oxc-project/types": "=0.96.0", + "@rolldown/pluginutils": "1.0.0-beta.47" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, "engines": { - "node": ">=14.0.0" + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.0-beta.47", + "@rolldown/binding-darwin-arm64": "1.0.0-beta.47", + "@rolldown/binding-darwin-x64": "1.0.0-beta.47", + "@rolldown/binding-freebsd-x64": "1.0.0-beta.47", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.47", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.47", + "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.47", + "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.47", + "@rolldown/binding-linux-x64-musl": "1.0.0-beta.47", + "@rolldown/binding-openharmony-arm64": "1.0.0-beta.47", + "@rolldown/binding-wasm32-wasi": "1.0.0-beta.47", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.47", + "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.47", + "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.47" } }, - "node_modules/sass-embedded-linux-musl-x64": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.97.2.tgz", - "integrity": "sha512-ZAxYOdmexcnxGnzdsDjYmNe3jGj+XW3/pF/n7e7r8y+5c6D2CQRrCUdapLgaqPt1edOPQIlQEZF8q5j6ng21yw==", - "cpu": [ - "x64" - ], + "node_modules/rollup": { + "version": "4.55.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz", + "integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.55.1", + "@rollup/rollup-android-arm64": "4.55.1", + "@rollup/rollup-darwin-arm64": "4.55.1", + "@rollup/rollup-darwin-x64": "4.55.1", + "@rollup/rollup-freebsd-arm64": "4.55.1", + "@rollup/rollup-freebsd-x64": "4.55.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", + "@rollup/rollup-linux-arm-musleabihf": "4.55.1", + "@rollup/rollup-linux-arm64-gnu": "4.55.1", + "@rollup/rollup-linux-arm64-musl": "4.55.1", + "@rollup/rollup-linux-loong64-gnu": "4.55.1", + "@rollup/rollup-linux-loong64-musl": "4.55.1", + "@rollup/rollup-linux-ppc64-gnu": "4.55.1", + "@rollup/rollup-linux-ppc64-musl": "4.55.1", + "@rollup/rollup-linux-riscv64-gnu": "4.55.1", + "@rollup/rollup-linux-riscv64-musl": "4.55.1", + "@rollup/rollup-linux-s390x-gnu": "4.55.1", + "@rollup/rollup-linux-x64-gnu": "4.55.1", + "@rollup/rollup-linux-x64-musl": "4.55.1", + "@rollup/rollup-openbsd-x64": "4.55.1", + "@rollup/rollup-openharmony-arm64": "4.55.1", + "@rollup/rollup-win32-arm64-msvc": "4.55.1", + "@rollup/rollup-win32-ia32-msvc": "4.55.1", + "@rollup/rollup-win32-x64-gnu": "4.55.1", + "@rollup/rollup-win32-x64-msvc": "4.55.1", + "fsevents": "~2.3.2" } }, - "node_modules/sass-embedded-linux-riscv64": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.97.2.tgz", - "integrity": "sha512-reVwa9ZFEAOChXpDyNB3nNHHyAkPMD+FTctQKECqKiVJnIzv2EaFF6/t0wzyvPgBKeatA8jszAIeOkkOzbYVkQ==", - "cpu": [ - "riscv64" - ], + "node_modules/rollup-plugin-dts": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-dts/-/rollup-plugin-dts-6.3.0.tgz", + "integrity": "sha512-d0UrqxYd8KyZ6i3M2Nx7WOMy708qsV/7fTHMHxCMCBOAe3V/U7OMPu5GkX8hC+cmkHhzGnfeYongl1IgiooddA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "LGPL-3.0-only", + "dependencies": { + "magic-string": "^0.30.21" + }, "engines": { - "node": ">=14.0.0" + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/Swatinem" + }, + "optionalDependencies": { + "@babel/code-frame": "^7.27.1" + }, + "peerDependencies": { + "rollup": "^3.29.4 || ^4", + "typescript": "^4.5 || ^5.0" } }, - "node_modules/sass-embedded-linux-x64": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.97.2.tgz", - "integrity": "sha512-bvAdZQsX3jDBv6m4emaU2OMTpN0KndzTAMgJZZrKUgiC0qxBmBqbJG06Oj/lOCoXGCxAvUOheVYpezRTF+Feog==", - "cpu": [ - "x64" - ], + "node_modules/rollup-plugin-dts/node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.0.0" + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/sass-embedded-unknown-all": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass-embedded-unknown-all/-/sass-embedded-unknown-all-1.97.2.tgz", - "integrity": "sha512-86tcYwohjPgSZtgeU9K4LikrKBJNf8ZW/vfsFbdzsRlvc73IykiqanufwQi5qIul0YHuu9lZtDWyWxM2dH/Rsg==", - "dev": true, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", "license": "MIT", - "optional": true, - "os": [ - "!android", - "!darwin", - "!linux", - "!win32" + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/rrweb-cssom": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", + "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } ], + "license": "MIT", "dependencies": { - "sass": "1.97.2" + "queue-microtask": "^1.2.2" } }, - "node_modules/sass-embedded-unknown-all/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "node_modules/rxjs": { + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-wipe": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/safe-wipe/-/safe-wipe-0.2.5.tgz", + "integrity": "sha512-MwTNf4YrRqCHsB5jUzOVdXoRbW4jkhgTvhlyfiaxox8EP7cOCiD4ydMOQCxDPR9KpvwdBSM2dQHScV1m85k8wQ==", + "dev": true, + "license": "Unlicense", + "dependencies": { + "extend": "^3.0.2", + "q": "1.*", + "rimraf": "2.*" + } + }, + "node_modules/safe-wipe/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "readdirp": "^4.0.1" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/safe-wipe/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">= 14.16.0" + "node": "*" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/sass-embedded-unknown-all/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "node_modules/safe-wipe/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", - "optional": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">= 14.18.0" + "node": "*" + } + }, + "node_modules/safe-wipe/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" + "bin": { + "rimraf": "bin.js" } }, - "node_modules/sass-embedded-unknown-all/node_modules/sass": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.97.2.tgz", - "integrity": "sha512-y5LWb0IlbO4e97Zr7c3mlpabcbBtS+ieiZ9iwDooShpFKWXf62zz5pEPdwrLYm+Bxn1fnbwFGzHuCLSA9tBmrw==", + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/sass": { + "version": "1.93.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.93.2.tgz", + "integrity": "sha512-t+YPtOQHpGW1QWsh1CHQ5cPIr9lbbGZLZnbihP/D/qZj/yuV68m8qarcV17nvkOX81BCrvzAlq2klCQFZghyTg==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", @@ -21988,793 +20863,846 @@ "@parcel/watcher": "^2.4.1" } }, - "node_modules/sass-embedded-win32-arm64": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.97.2.tgz", - "integrity": "sha512-Cv28q8qNjAjZfqfzTrQvKf4JjsZ6EOQ5FxyHUQQeNzm73R86nd/8ozDa1Vmn79Hq0kwM15OCM9epanDuTG1ksA==", - "cpu": [ - "arm64" - ], + "node_modules/sass-convert": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/sass-convert/-/sass-convert-0.5.2.tgz", + "integrity": "sha512-eV9wXZg7MrHmnKLD6WojC/WX7lhLm+PSSLrOukzRIECa04fGbkmFDO9Ot9/82KjzSe+VEClYe9WDKzCuBz30Dg==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "license": "Unlicense", + "dependencies": { + "concat-stream": "^1.4.7", + "dargs": "^4.0.0", + "ends-with": "^0.2.0", + "es6-denodeify": "^0.1.0", + "es6-promise": "^3.0.2", + "memoize-decorator": "^1.0.2", + "object-assign": "^3.0.0", + "semver": "^5.0.1", + "semver-regex": "^1.0.0", + "through2": "^2.0.0", + "which": "^1.0.5" + }, "engines": { - "node": ">=14.0.0" + "node": ">=0.10.0", + "npm": ">=2.1.0" } }, - "node_modules/sass-embedded-win32-x64": { - "version": "1.97.2", - "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.97.2.tgz", - "integrity": "sha512-DVxLxkeDCGIYeyHLAvWW3yy9sy5Ruk5p472QWiyfyyG1G1ASAR8fgfIY5pT0vE6Rv+VAKVLwF3WTspUYu7S1/Q==", - "cpu": [ - "x64" - ], + "node_modules/sass-convert/node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" + "engines": [ + "node >= 0.8" ], - "engines": { - "node": ">=14.0.0" + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, - "node_modules/sass-embedded/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/sass-convert/node_modules/object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha512-jHP15vXVGeVh1HuaA2wY6lxk+whK/x4KBG88VXeRma7CCun7iGD5qPc4eYykQ9sdQvg8jkwFKsSxHln2ybW3xQ==", "dev": true, "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/sass-true": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/sass-true/-/sass-true-8.1.0.tgz", - "integrity": "sha512-LUiNRslsNreGk8Oe85ZvMmV0mlIh3LFP2KTDMZsSHz5DxPElCy7wI9ocJzf8IpIf7Q5ZO0w+hDBF1nbdUcmZHA==", + "node_modules/sass-convert/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "@adobe/css-tools": "^4.4.0", - "jest-diff": "^29.7.0", - "lodash": "^4.17.21" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "sass": ">=1.45.0", - "sass-embedded": ">=1.45.0" - }, - "peerDependenciesMeta": { - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - } + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/sass/node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "node_modules/sass-convert/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } + "license": "MIT" }, - "node_modules/sass/node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "node_modules/sass-convert/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" + "license": "ISC", + "bin": { + "semver": "bin/semver" } }, - "node_modules/sassdoc": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/sassdoc/-/sassdoc-2.7.4.tgz", - "integrity": "sha512-/HEjX9pMILkePyC4ZKGhkLqZHJZpsTxFwQIQNsLhV4XHiPKoWHrSmam1pMntM79tcdtBII3JX7ShfyZjHnrkyw==", + "node_modules/sass-convert/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.2.1", - "babel-runtime": "^6.26.0", - "chalk": "^2.4.2", - "concat-stream": "^2.0.0", - "docopt": "^0.6.1", - "glob": "^7.1.6", - "glob2base": "0.0.12", - "js-yaml": "^3.14.0", - "lodash.difference": "^4.5.0", - "lodash.uniq": "^4.5.0", - "minimatch": "^3.0.4", - "mkdirp": "^1.0.4", - "multipipe": "1.0.2", - "rimraf": "^3.0.2", - "safe-wipe": "0.2.5", - "sass-convert": "^0.5.0", - "sassdoc-theme-default": "^2.8.3", - "scss-comment-parser": "^0.8.4", - "strip-indent": "^3.0.0", - "through2": "1.1.1", - "update-notifier": "^4.1.0", - "vinyl-fs": "^3.0.3", - "vinyl-source-stream": "1.1.2", - "vinyl-string": "^1.0.2" - }, - "bin": { - "sassdoc": "bin/sassdoc" + "safe-buffer": "~5.1.0" } }, - "node_modules/sassdoc-extras": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/sassdoc-extras/-/sassdoc-extras-2.5.1.tgz", - "integrity": "sha512-/+ilEnk1H1hG9nympL1GIFWhAczzoclyDzgzfphIg46nsT/dWJuzWYHyzIpduc/nTVwKeQfmTz0ZVvy12QMkrQ==", + "node_modules/sass-convert/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "marked": "^0.6.2" + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" } }, - "node_modules/sassdoc-extras/node_modules/marked": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.6.3.tgz", - "integrity": "sha512-Fqa7eq+UaxfMriqzYLayfqAE40WN03jf+zHjT18/uXNuzjq3TY0XTbrAoPeqSJrAmPz11VuUA+kBPYOhHt9oOQ==", + "node_modules/sass-embedded": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.97.2.tgz", + "integrity": "sha512-lKJcskySwAtJ4QRirKrikrWMFa2niAuaGenY2ElHjd55IwHUiur5IdKu6R1hEmGYMs4Qm+6rlRW0RvuAkmcryg==", "dev": true, "license": "MIT", + "dependencies": { + "@bufbuild/protobuf": "^2.5.0", + "buffer-builder": "^0.2.0", + "colorjs.io": "^0.5.0", + "immutable": "^5.0.2", + "rxjs": "^7.4.0", + "supports-color": "^8.1.1", + "sync-child-process": "^1.0.2", + "varint": "^6.0.0" + }, "bin": { - "marked": "bin/marked" + "sass": "dist/bin/sass.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=16.0.0" + }, + "optionalDependencies": { + "sass-embedded-all-unknown": "1.97.2", + "sass-embedded-android-arm": "1.97.2", + "sass-embedded-android-arm64": "1.97.2", + "sass-embedded-android-riscv64": "1.97.2", + "sass-embedded-android-x64": "1.97.2", + "sass-embedded-darwin-arm64": "1.97.2", + "sass-embedded-darwin-x64": "1.97.2", + "sass-embedded-linux-arm": "1.97.2", + "sass-embedded-linux-arm64": "1.97.2", + "sass-embedded-linux-musl-arm": "1.97.2", + "sass-embedded-linux-musl-arm64": "1.97.2", + "sass-embedded-linux-musl-riscv64": "1.97.2", + "sass-embedded-linux-musl-x64": "1.97.2", + "sass-embedded-linux-riscv64": "1.97.2", + "sass-embedded-linux-x64": "1.97.2", + "sass-embedded-unknown-all": "1.97.2", + "sass-embedded-win32-arm64": "1.97.2", + "sass-embedded-win32-x64": "1.97.2" } }, - "node_modules/sassdoc-plugin-localization": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sassdoc-plugin-localization/-/sassdoc-plugin-localization-2.0.0.tgz", - "integrity": "sha512-jC/Mi8jYaux1SIt+eH9gj1g4UgzfBxm00oHxfqOXQSGrSEGkM+YfPe8iOcZzflEiXRPgR6ckLoHCdSM1YkSGTg==", + "node_modules/sass-embedded-all-unknown": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass-embedded-all-unknown/-/sass-embedded-all-unknown-1.97.2.tgz", + "integrity": "sha512-Fj75+vOIDv1T/dGDwEpQ5hgjXxa2SmMeShPa8yrh2sUz1U44bbmY4YSWPCdg8wb7LnwiY21B2KRFM+HF42yO4g==", + "cpu": [ + "!arm", + "!arm64", + "!riscv64", + "!x64" + ], "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "fs-extra": "^7.0.1" + "sass": "1.97.2" } }, - "node_modules/sassdoc-plugin-localization/node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "node_modules/sass-embedded-all-unknown/node_modules/sass": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.97.2.tgz", + "integrity": "sha512-y5LWb0IlbO4e97Zr7c3mlpabcbBtS+ieiZ9iwDooShpFKWXf62zz5pEPdwrLYm+Bxn1fnbwFGzHuCLSA9tBmrw==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" } }, - "node_modules/sassdoc-plugin-localization/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "node_modules/sass-embedded-android-arm": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.97.2.tgz", + "integrity": "sha512-BPT9m19ttY0QVHYYXRa6bmqmS3Fa2EHByNUEtSVcbm5PkIk1ntmYkG9fn5SJpIMbNmFDGwHx+pfcZMmkldhnRg==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" } }, - "node_modules/sassdoc-plugin-localization/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "node_modules/sass-embedded-android-arm64": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.97.2.tgz", + "integrity": "sha512-pF6I+R5uThrscd3lo9B3DyNTPyGFsopycdx0tDAESN6s+dBbiRgNgE4Zlpv50GsLocj/lDLCZaabeTpL3ubhYA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">= 4.0.0" + "node": ">=14.0.0" } }, - "node_modules/sassdoc-theme-default": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/sassdoc-theme-default/-/sassdoc-theme-default-2.8.6.tgz", - "integrity": "sha512-s12y6pThpPDm33UScHfnfa/RBs9+gkCxl/YNWDTyLl3a6IxzusEdut1uwv4fpmpaOsTpcjGxZw839Moi4d/3Eg==", + "node_modules/sass-embedded-android-riscv64": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.97.2.tgz", + "integrity": "sha512-fprI8ZTJdz+STgARhg8zReI2QhhGIT9G8nS7H21kc3IkqPRzhfaemSxEtCqZyvDbXPcgYiDLV7AGIReHCuATog==", + "cpu": [ + "riscv64" + ], "dev": true, "license": "MIT", - "dependencies": { - "babel-runtime": "^6.22.0", - "chroma-js": "^1.2.2", - "es6-denodeify": "^0.1.0", - "es6-promise": "^4.2.6", - "extend": "^3.0.2", - "fs-extra": "^2.0.0", - "html-minifier": "^3.5.21", - "nunjucks": "^3.1.7", - "sassdoc-extras": "^2.5.0" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=14.0.0" } }, - "node_modules/sassdoc-theme-default/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, + "node_modules/sass-embedded-android-x64": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.97.2.tgz", + "integrity": "sha512-RswwSjURZxupsukEmNt2t6RGvuvIw3IAD5sDq1Pc65JFvWFY3eHqCmH0lG0oXqMg6KJcF0eOxHOp2RfmIm2+4w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "node": ">=14.0.0" } }, - "node_modules/sassdoc-theme-default/node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "node_modules/sass-embedded-darwin-arm64": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.97.2.tgz", + "integrity": "sha512-xcsZNnU1XZh21RE/71OOwNqPVcGBU0qT9A4k4QirdA34+ts9cDIaR6W6lgHOBR/Bnnu6w6hXJR4Xth7oFrefPA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 6" + "node": ">=14.0.0" } }, - "node_modules/sassdoc-theme-default/node_modules/es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", - "dev": true, - "license": "MIT" - }, - "node_modules/sassdoc-theme-default/node_modules/fs-extra": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz", - "integrity": "sha512-9ztMtDZtSKC78V8mev+k31qaTabbmuH5jatdvPBMikrFHvw5BqlYnQIn/WGK3WHeRooSTkRvLa2IPlaHjPq5Sg==", + "node_modules/sass-embedded-darwin-x64": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.97.2.tgz", + "integrity": "sha512-T/9DTMpychm6+H4slHCAsYJRJ6eM+9H9idKlBPliPrP4T8JdC2Cs+ZOsYqrObj6eOtAD0fGf+KgyNhnW3xVafA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0" - } - }, - "node_modules/sassdoc-theme-default/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 6" + "node": ">=14.0.0" } }, - "node_modules/sassdoc-theme-default/node_modules/jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", + "node_modules/sass-embedded-linux-arm": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.97.2.tgz", + "integrity": "sha512-yDRe1yifGHl6kibkDlRIJ2ZzAU03KJ1AIvsAh4dsIDgK5jx83bxZLV1ZDUv7a8KK/iV/80LZnxnu/92zp99cXQ==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" } }, - "node_modules/sassdoc-theme-default/node_modules/nunjucks": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", - "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", + "node_modules/sass-embedded-linux-arm64": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.97.2.tgz", + "integrity": "sha512-Wh+nQaFer9tyE5xBPv5murSUZE/+kIcg8MyL5uqww6be9Iq+UmZpcJM7LUk+q8klQ9LfTmoDSNFA74uBqxD6IA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "a-sync-waterfall": "^1.0.0", - "asap": "^2.0.3", - "commander": "^5.1.0" - }, - "bin": { - "nunjucks-precompile": "bin/precompile" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 6.9.0" - }, - "peerDependencies": { - "chokidar": "^3.3.0" - }, - "peerDependenciesMeta": { - "chokidar": { - "optional": true - } + "node": ">=14.0.0" } }, - "node_modules/sassdoc-theme-default/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "extraneous": true, + "node_modules/sass-embedded-linux-musl-arm": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.97.2.tgz", + "integrity": "sha512-GIO6xfAtahJAWItvsXZ3MD1HM6s8cKtV1/HL088aUpKJaw/2XjTCveiOO2AdgMpLNztmq9DZ1lx5X5JjqhS45g==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">=14.0.0" } }, - "node_modules/sassdoc-theme-default/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "extraneous": true, + "node_modules/sass-embedded-linux-musl-arm64": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.97.2.tgz", + "integrity": "sha512-NfUqZSjHwnHvpSa7nyNxbWfL5obDjNBqhHUYmqbHUcmqBpFfHIQsUPgXME9DKn1yBlBc3mWnzMxRoucdYTzd2Q==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8.10.0" + "node": ">=14.0.0" } }, - "node_modules/sassdoc/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/sass-embedded-linux-musl-riscv64": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.97.2.tgz", + "integrity": "sha512-qtM4dJ5gLfvyTZ3QencfNbsTEShIWImSEpkThz+Y2nsCMbcMP7/jYOA03UWgPfEOKSehQQ7EIau7ncbFNoDNPQ==", + "cpu": [ + "riscv64" + ], "dev": true, "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" } }, - "node_modules/sassdoc/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/sass-embedded-linux-musl-x64": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.97.2.tgz", + "integrity": "sha512-ZAxYOdmexcnxGnzdsDjYmNe3jGj+XW3/pF/n7e7r8y+5c6D2CQRrCUdapLgaqPt1edOPQIlQEZF8q5j6ng21yw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.0.0" } }, - "node_modules/sassdoc/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/sass-embedded-linux-riscv64": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.97.2.tgz", + "integrity": "sha512-reVwa9ZFEAOChXpDyNB3nNHHyAkPMD+FTctQKECqKiVJnIzv2EaFF6/t0wzyvPgBKeatA8jszAIeOkkOzbYVkQ==", + "cpu": [ + "riscv64" + ], "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=4" + "node": ">=14.0.0" } }, - "node_modules/sassdoc/node_modules/chalk/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/sass-embedded-linux-x64": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.97.2.tgz", + "integrity": "sha512-bvAdZQsX3jDBv6m4emaU2OMTpN0KndzTAMgJZZrKUgiC0qxBmBqbJG06Oj/lOCoXGCxAvUOheVYpezRTF+Feog==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=4" + "node": ">=14.0.0" } }, - "node_modules/sassdoc/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/sass-embedded-unknown-all": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass-embedded-unknown-all/-/sass-embedded-unknown-all-1.97.2.tgz", + "integrity": "sha512-86tcYwohjPgSZtgeU9K4LikrKBJNf8ZW/vfsFbdzsRlvc73IykiqanufwQi5qIul0YHuu9lZtDWyWxM2dH/Rsg==", "dev": true, "license": "MIT", + "optional": true, + "os": [ + "!android", + "!darwin", + "!linux", + "!win32" + ], "dependencies": { - "color-name": "1.1.3" + "sass": "1.97.2" } }, - "node_modules/sassdoc/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "node_modules/sass-embedded-unknown-all/node_modules/sass": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.97.2.tgz", + "integrity": "sha512-y5LWb0IlbO4e97Zr7c3mlpabcbBtS+ieiZ9iwDooShpFKWXf62zz5pEPdwrLYm+Bxn1fnbwFGzHuCLSA9tBmrw==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "dependencies": { + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } }, - "node_modules/sassdoc/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/sass-embedded-win32-arm64": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.97.2.tgz", + "integrity": "sha512-Cv28q8qNjAjZfqfzTrQvKf4JjsZ6EOQ5FxyHUQQeNzm73R86nd/8ozDa1Vmn79Hq0kwM15OCM9epanDuTG1ksA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=0.8.0" + "node": ">=14.0.0" } }, - "node_modules/sassdoc/node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/sass-embedded-win32-x64": { + "version": "1.97.2", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.97.2.tgz", + "integrity": "sha512-DVxLxkeDCGIYeyHLAvWW3yy9sy5Ruk5p472QWiyfyyG1G1ASAR8fgfIY5pT0vE6Rv+VAKVLwF3WTspUYu7S1/Q==", + "cpu": [ + "x64" + ], "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=4" + "node": ">=14.0.0" } }, - "node_modules/sassdoc/node_modules/fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", + "node_modules/sass-embedded/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", "dependencies": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/sassdoc/node_modules/fs-mkdirp-stream/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/sassdoc/node_modules/fs-mkdirp-stream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/sass-true": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/sass-true/-/sass-true-8.1.0.tgz", + "integrity": "sha512-LUiNRslsNreGk8Oe85ZvMmV0mlIh3LFP2KTDMZsSHz5DxPElCy7wI9ocJzf8IpIf7Q5ZO0w+hDBF1nbdUcmZHA==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "@adobe/css-tools": "^4.4.0", + "jest-diff": "^29.7.0", + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "sass": ">=1.45.0", + "sass-embedded": ">=1.45.0" + }, + "peerDependenciesMeta": { + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + } } }, - "node_modules/sassdoc/node_modules/fs-mkdirp-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/sassdoc": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/sassdoc/-/sassdoc-2.7.4.tgz", + "integrity": "sha512-/HEjX9pMILkePyC4ZKGhkLqZHJZpsTxFwQIQNsLhV4XHiPKoWHrSmam1pMntM79tcdtBII3JX7ShfyZjHnrkyw==", "dev": true, "license": "MIT", "dependencies": { - "safe-buffer": "~5.1.0" + "ansi-styles": "^4.2.1", + "babel-runtime": "^6.26.0", + "chalk": "^2.4.2", + "concat-stream": "^2.0.0", + "docopt": "^0.6.1", + "glob": "^7.1.6", + "glob2base": "0.0.12", + "js-yaml": "^3.14.0", + "lodash.difference": "^4.5.0", + "lodash.uniq": "^4.5.0", + "minimatch": "^3.0.4", + "mkdirp": "^1.0.4", + "multipipe": "1.0.2", + "rimraf": "^3.0.2", + "safe-wipe": "0.2.5", + "sass-convert": "^0.5.0", + "sassdoc-theme-default": "^2.8.3", + "scss-comment-parser": "^0.8.4", + "strip-indent": "^3.0.0", + "through2": "1.1.1", + "update-notifier": "^4.1.0", + "vinyl-fs": "^3.0.3", + "vinyl-source-stream": "1.1.2", + "vinyl-string": "^1.0.2" + }, + "bin": { + "sassdoc": "bin/sassdoc" } }, - "node_modules/sassdoc/node_modules/fs-mkdirp-stream/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "node_modules/sassdoc-extras": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/sassdoc-extras/-/sassdoc-extras-2.5.1.tgz", + "integrity": "sha512-/+ilEnk1H1hG9nympL1GIFWhAczzoclyDzgzfphIg46nsT/dWJuzWYHyzIpduc/nTVwKeQfmTz0ZVvy12QMkrQ==", "dev": true, "license": "MIT", "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "marked": "^0.6.2" } }, - "node_modules/sassdoc/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/sassdoc-extras/node_modules/marked": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.6.3.tgz", + "integrity": "sha512-Fqa7eq+UaxfMriqzYLayfqAE40WN03jf+zHjT18/uXNuzjq3TY0XTbrAoPeqSJrAmPz11VuUA+kBPYOhHt9oOQ==", "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "license": "MIT", + "bin": { + "marked": "bin/marked" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=0.10.0" } }, - "node_modules/sassdoc/node_modules/glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "node_modules/sassdoc-plugin-localization": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sassdoc-plugin-localization/-/sassdoc-plugin-localization-2.0.0.tgz", + "integrity": "sha512-jC/Mi8jYaux1SIt+eH9gj1g4UgzfBxm00oHxfqOXQSGrSEGkM+YfPe8iOcZzflEiXRPgR6ckLoHCdSM1YkSGTg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" + "fs-extra": "^7.0.1" } }, - "node_modules/sassdoc/node_modules/glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", + "node_modules/sassdoc-plugin-localization/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, "license": "MIT", "dependencies": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, "engines": { - "node": ">= 0.10" + "node": ">=6 <7 || >=8" } }, - "node_modules/sassdoc/node_modules/glob-stream/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/sassdoc/node_modules/glob-stream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/sassdoc-plugin-localization/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/sassdoc/node_modules/glob-stream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/sassdoc-plugin-localization/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" + "engines": { + "node": ">= 4.0.0" } }, - "node_modules/sassdoc/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/sassdoc-theme-default": { + "version": "2.8.6", + "resolved": "https://registry.npmjs.org/sassdoc-theme-default/-/sassdoc-theme-default-2.8.6.tgz", + "integrity": "sha512-s12y6pThpPDm33UScHfnfa/RBs9+gkCxl/YNWDTyLl3a6IxzusEdut1uwv4fpmpaOsTpcjGxZw839Moi4d/3Eg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=4" + "dependencies": { + "babel-runtime": "^6.22.0", + "chroma-js": "^1.2.2", + "es6-denodeify": "^0.1.0", + "es6-promise": "^4.2.6", + "extend": "^3.0.2", + "fs-extra": "^2.0.0", + "html-minifier": "^3.5.21", + "nunjucks": "^3.1.7", + "sassdoc-extras": "^2.5.0" } }, - "node_modules/sassdoc/node_modules/is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "node_modules/sassdoc-theme-default/node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", "dev": true, "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/sassdoc/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "node_modules/sassdoc-theme-default/node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", "dev": true, "license": "MIT" }, - "node_modules/sassdoc/node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "node_modules/sassdoc-theme-default/node_modules/fs-extra": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz", + "integrity": "sha512-9ztMtDZtSKC78V8mev+k31qaTabbmuH5jatdvPBMikrFHvw5BqlYnQIn/WGK3WHeRooSTkRvLa2IPlaHjPq5Sg==", "dev": true, "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0" } }, - "node_modules/sassdoc/node_modules/lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", + "node_modules/sassdoc-theme-default/node_modules/jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", "dev": true, "license": "MIT", - "dependencies": { - "flush-write-stream": "^1.0.2" - }, - "engines": { - "node": ">= 0.10" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/sassdoc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/sassdoc-theme-default/node_modules/nunjucks": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", + "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", "dev": true, - "license": "ISC", + "license": "BSD-2-Clause", "dependencies": { - "brace-expansion": "^1.1.7" + "a-sync-waterfall": "^1.0.0", + "asap": "^2.0.3", + "commander": "^5.1.0" }, - "engines": { - "node": "*" - } - }, - "node_modules/sassdoc/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "license": "MIT", "bin": { - "mkdirp": "bin/cmd.js" + "nunjucks-precompile": "bin/precompile" }, "engines": { - "node": ">=10" + "node": ">= 6.9.0" + }, + "peerDependencies": { + "chokidar": "^3.3.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } } }, - "node_modules/sassdoc/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "node_modules/sassdoc/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "license": "MIT", "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" + "sprintf-js": "~1.0.2" } }, - "node_modules/sassdoc/node_modules/now-and-later": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", - "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "node_modules/sassdoc/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { - "once": "^1.3.2" - }, - "engines": { - "node": ">= 0.10" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/sassdoc/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "node_modules/sassdoc/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "license": "MIT", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/sassdoc/node_modules/resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==", + "node_modules/sassdoc/node_modules/chalk/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "license": "MIT", "dependencies": { - "value-or-function": "^3.0.0" + "color-convert": "^1.9.0" }, "engines": { - "node": ">= 0.10" + "node": ">=4" } }, - "node_modules/sassdoc/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "node_modules/sassdoc/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } }, - "node_modules/sassdoc/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "node_modules/sassdoc/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true, "license": "MIT" }, - "node_modules/sassdoc/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/sassdoc/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, "engines": { - "node": ">=4" + "node": ">=0.8.0" } }, - "node_modules/sassdoc/node_modules/through2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-1.1.1.tgz", - "integrity": "sha512-zEbpaeSMHxczpTzO1KkMHjBC1enTA68ojeaZGG4toqdASpb9t4xUZaYFBq2/9OHo5nTGFVSYd4c910OR+6wxbQ==", + "node_modules/sassdoc/node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": ">=1.1.13-1 <1.2.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" } }, - "node_modules/sassdoc/node_modules/to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==", + "node_modules/sassdoc/node_modules/fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", "dev": true, "license": "MIT", "dependencies": { + "graceful-fs": "^4.1.11", "through2": "^2.0.3" }, "engines": { "node": ">= 0.10" } }, - "node_modules/sassdoc/node_modules/to-through/node_modules/isarray": { + "node_modules/sassdoc/node_modules/fs-mkdirp-stream/node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, "license": "MIT" }, - "node_modules/sassdoc/node_modules/to-through/node_modules/readable-stream": { + "node_modules/sassdoc/node_modules/fs-mkdirp-stream/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", @@ -22790,7 +21718,7 @@ "util-deprecate": "~1.0.1" } }, - "node_modules/sassdoc/node_modules/to-through/node_modules/string_decoder": { + "node_modules/sassdoc/node_modules/fs-mkdirp-stream/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", @@ -22800,7 +21728,7 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/sassdoc/node_modules/to-through/node_modules/through2": { + "node_modules/sassdoc/node_modules/fs-mkdirp-stream/node_modules/through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", @@ -22811,53 +21739,69 @@ "xtend": "~4.0.1" } }, - "node_modules/sassdoc/node_modules/value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==", + "node_modules/sassdoc/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, "engines": { - "node": ">= 0.10" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/sassdoc/node_modules/vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "node_modules/sassdoc/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/sassdoc/node_modules/glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", "dev": true, "license": "MIT", "dependencies": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" }, "engines": { "node": ">= 0.10" } }, - "node_modules/sassdoc/node_modules/vinyl-fs/node_modules/isarray": { + "node_modules/sassdoc/node_modules/glob-stream/node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, "license": "MIT" }, - "node_modules/sassdoc/node_modules/vinyl-fs/node_modules/readable-stream": { + "node_modules/sassdoc/node_modules/glob-stream/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", @@ -22873,7 +21817,7 @@ "util-deprecate": "~1.0.1" } }, - "node_modules/sassdoc/node_modules/vinyl-fs/node_modules/string_decoder": { + "node_modules/sassdoc/node_modules/glob-stream/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", @@ -22883,3451 +21827,4067 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/sassdoc/node_modules/vinyl-fs/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "node_modules/sassdoc/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, "license": "MIT", - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "engines": { + "node": ">=4" } }, - "node_modules/sassdoc/node_modules/vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==", + "node_modules/sassdoc/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", "dev": true, "license": "MIT", "dependencies": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" + "is-extglob": "^2.1.0" }, "engines": { - "node": ">= 0.10" + "node": ">=0.10.0" } }, - "node_modules/sax": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz", - "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", + "node_modules/sassdoc/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=11.0.0" - } + "license": "MIT" }, - "node_modules/saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "node_modules/sassdoc/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "xmlchars": "^2.2.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" }, - "engines": { - "node": ">=v12.22.7" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/scss-comment-parser": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/scss-comment-parser/-/scss-comment-parser-0.8.4.tgz", - "integrity": "sha512-ERw4BODvM22n8Ke8hJxuH3fKXLm0Q4chfUNHwDSOAExCths2ZXq8PT32vms4R9Om6dffRSXzzGZS1p38UU4EAg==", + "node_modules/sassdoc/node_modules/lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", "dev": true, "license": "MIT", "dependencies": { - "cdocparser": "^0.13.0" + "flush-write-stream": "^1.0.2" + }, + "engines": { + "node": ">= 0.10" } }, - "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "node_modules/sassdoc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=10" + "node": "*" } }, - "node_modules/semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "node_modules/sassdoc/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "license": "MIT", - "dependencies": { - "semver": "^6.3.0" + "bin": { + "mkdirp": "bin/cmd.js" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/semver-diff/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/sassdoc/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/semver-greatest-satisfied-range": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-2.0.0.tgz", - "integrity": "sha512-lH3f6kMbwyANB7HuOWRMlLCa2itaCrZJ+SAqqkSZrZKO/cAsk2EOyaKHUtNkVLFyFW9pct22SFesFp3Z7zpA0g==", + "node_modules/sassdoc/node_modules/now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", "dev": true, "license": "MIT", "dependencies": { - "sver": "^1.8.3" + "once": "^1.3.2" }, "engines": { - "node": ">= 10.13.0" + "node": ">= 0.10" } }, - "node_modules/semver-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz", - "integrity": "sha512-1vZcoRC+LPtHFkLUPyrabsATDSHerxW+hJBN8h04HZOZBuewbXaNROtUVdEPrTdZsWNq6sfsXDhd48GB2xTG4g==", + "node_modules/sassdoc/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } }, - "node_modules/send": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", - "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "node_modules/sassdoc/node_modules/resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==", + "dev": true, "license": "MIT", "dependencies": { - "debug": "^4.4.3", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.1", - "mime-types": "^3.0.2", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.2" + "value-or-function": "^3.0.0" }, "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "node": ">= 0.10" } }, - "node_modules/serve-static": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", - "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", - "license": "MIT", - "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } + "node_modules/sassdoc/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" }, - "node_modules/set-cookie-parser": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", - "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "node_modules/sassdoc/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", "dev": true, "license": "MIT" }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "node_modules/sassdoc/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "license": "MIT", "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" + "has-flag": "^3.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=4" } }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "node_modules/sharp": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", - "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "node_modules/sassdoc/node_modules/through2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-1.1.1.tgz", + "integrity": "sha512-zEbpaeSMHxczpTzO1KkMHjBC1enTA68ojeaZGG4toqdASpb9t4xUZaYFBq2/9OHo5nTGFVSYd4c910OR+6wxbQ==", "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", - "optional": true, + "license": "MIT", "dependencies": { - "@img/colour": "^1.0.0", - "detect-libc": "^2.1.2", - "semver": "^7.7.3" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.5", - "@img/sharp-darwin-x64": "0.34.5", - "@img/sharp-libvips-darwin-arm64": "1.2.4", - "@img/sharp-libvips-darwin-x64": "1.2.4", - "@img/sharp-libvips-linux-arm": "1.2.4", - "@img/sharp-libvips-linux-arm64": "1.2.4", - "@img/sharp-libvips-linux-ppc64": "1.2.4", - "@img/sharp-libvips-linux-riscv64": "1.2.4", - "@img/sharp-libvips-linux-s390x": "1.2.4", - "@img/sharp-libvips-linux-x64": "1.2.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", - "@img/sharp-libvips-linuxmusl-x64": "1.2.4", - "@img/sharp-linux-arm": "0.34.5", - "@img/sharp-linux-arm64": "0.34.5", - "@img/sharp-linux-ppc64": "0.34.5", - "@img/sharp-linux-riscv64": "0.34.5", - "@img/sharp-linux-s390x": "0.34.5", - "@img/sharp-linux-x64": "0.34.5", - "@img/sharp-linuxmusl-arm64": "0.34.5", - "@img/sharp-linuxmusl-x64": "0.34.5", - "@img/sharp-wasm32": "0.34.5", - "@img/sharp-win32-arm64": "0.34.5", - "@img/sharp-win32-ia32": "0.34.5", - "@img/sharp-win32-x64": "0.34.5" + "readable-stream": ">=1.1.13-1 <1.2.0-0", + "xtend": ">=4.0.0 <4.1.0-0" } }, - "node_modules/shebang-command": { + "node_modules/sassdoc/node_modules/to-through": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==", "dev": true, "license": "MIT", "dependencies": { - "shebang-regex": "^3.0.0" + "through2": "^2.0.3" }, "engines": { - "node": ">=8" + "node": ">= 0.10" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/sassdoc/node_modules/to-through/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/shiki": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.21.0.tgz", - "integrity": "sha512-N65B/3bqL/TI2crrXr+4UivctrAGEjmsib5rPMMPpFp1xAx/w03v8WZ9RDDFYteXoEgY7qZ4HGgl5KBIu1153w==", + "node_modules/sassdoc/node_modules/to-through/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, "license": "MIT", "dependencies": { - "@shikijs/core": "3.21.0", - "@shikijs/engine-javascript": "3.21.0", - "@shikijs/engine-oniguruma": "3.21.0", - "@shikijs/langs": "3.21.0", - "@shikijs/themes": "3.21.0", - "@shikijs/types": "3.21.0", - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "node_modules/sassdoc/node_modules/to-through/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "safe-buffer": "~5.1.0" } }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "node_modules/sassdoc/node_modules/to-through/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" } }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "node_modules/sassdoc/node_modules/value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==", + "dev": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.10" } }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "node_modules/sassdoc/node_modules/vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.10" } }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "node_modules/sassdoc/node_modules/vinyl-fs/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/sigstore": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-4.1.0.tgz", - "integrity": "sha512-/fUgUhYghuLzVT/gaJoeVehLCgZiUxPCPMcyVNY0lIf/cTCz58K/WTI7PefDarXxp9nUKpEwg1yyz3eSBMTtgA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^4.0.0", - "@sigstore/core": "^3.1.0", - "@sigstore/protobuf-specs": "^0.5.0", - "@sigstore/sign": "^4.1.0", - "@sigstore/tuf": "^4.0.1", - "@sigstore/verify": "^3.1.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" - } + "license": "MIT" }, - "node_modules/sirv": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", - "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", + "node_modules/sassdoc/node_modules/vinyl-fs/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "license": "MIT", "dependencies": { - "@polka/url": "^1.0.0-next.24", - "mrmime": "^2.0.0", - "totalist": "^3.0.0" - }, - "engines": { - "node": ">=18" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true, - "license": "MIT" - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/sassdoc/node_modules/vinyl-fs/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "safe-buffer": "~5.1.0" } }, - "node_modules/slice-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", - "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "node_modules/sassdoc/node_modules/vinyl-fs/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" } }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "node_modules/sassdoc/node_modules/vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "license": "MIT", "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" + "node": ">= 0.10" } }, - "node_modules/smol-toml": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.0.tgz", - "integrity": "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==", + "node_modules/sax": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz", + "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", "dev": true, - "license": "BSD-3-Clause", + "license": "BlueOak-1.0.0", "engines": { - "node": ">= 18" - }, - "funding": { - "url": "https://github.com/sponsors/cyyynthia" + "node": ">=11.0.0" } }, - "node_modules/socket.io": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.3.tgz", - "integrity": "sha512-2Dd78bqzzjE6KPkD5fHZmDAKRNe3J15q+YHDrIsy9WEkqttc7GY+kT9OBLSMaPbQaEd0x1BjcmtMtXkfpc+T5A==", + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "cors": "~2.8.5", - "debug": "~4.4.1", - "engine.io": "~6.6.0", - "socket.io-adapter": "~2.5.2", - "socket.io-parser": "~4.2.4" + "xmlchars": "^2.2.0" }, "engines": { - "node": ">=10.2.0" + "node": ">=v12.22.7" } }, - "node_modules/socket.io-adapter": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.6.tgz", - "integrity": "sha512-DkkO/dz7MGln0dHn5bmN3pPy+JmywNICWrJqVWiVOyvXjWQFIv9c2h24JrQLLFJ2aQVQf/Cvl1vblnd4r2apLQ==", + "node_modules/scss-comment-parser": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/scss-comment-parser/-/scss-comment-parser-0.8.4.tgz", + "integrity": "sha512-ERw4BODvM22n8Ke8hJxuH3fKXLm0Q4chfUNHwDSOAExCths2ZXq8PT32vms4R9Om6dffRSXzzGZS1p38UU4EAg==", "dev": true, "license": "MIT", "dependencies": { - "debug": "~4.4.1", - "ws": "~8.18.3" - } - }, - "node_modules/socket.io-adapter/node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "cdocparser": "^0.13.0" } }, - "node_modules/socket.io-parser": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.5.tgz", - "integrity": "sha512-bPMmpy/5WWKHea5Y/jYAP6k74A+hvmRCQaJuJB6I/ML5JZq/KfNieUVo/3Mh7SAqn7TyFdIo6wqYHInG1MU1bQ==", + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "dev": true, - "license": "MIT", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.4.1" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=10.0.0" + "node": ">=10" } }, - "node_modules/socket.io/node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "node_modules/semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", "dev": true, "license": "MIT", "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "semver": "^6.3.0" }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/socket.io/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "node_modules/semver-diff/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/socket.io/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/semver-greatest-satisfied-range": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-2.0.0.tgz", + "integrity": "sha512-lH3f6kMbwyANB7HuOWRMlLCa2itaCrZJ+SAqqkSZrZKO/cAsk2EOyaKHUtNkVLFyFW9pct22SFesFp3Z7zpA0g==", "dev": true, "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "sver": "^1.8.3" }, "engines": { - "node": ">= 0.6" + "node": ">= 10.13.0" } }, - "node_modules/socket.io/node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "node_modules/semver-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz", + "integrity": "sha512-1vZcoRC+LPtHFkLUPyrabsATDSHerxW+hJBN8h04HZOZBuewbXaNROtUVdEPrTdZsWNq6sfsXDhd48GB2xTG4g==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/socks": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", - "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", - "dev": true, + "node_modules/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", "license": "MIT", "dependencies": { - "ip-address": "^10.0.1", - "smart-buffer": "^4.2.0" + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" }, "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/socks-proxy-agent": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", - "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", - "dev": true, + "node_modules/serve-static": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", "license": "MIT", "dependencies": { - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "socks": "^2.8.3" + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" }, "engines": { - "node": ">= 14" + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, - "node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 12" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "license": "MIT", "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", "dev": true, - "license": "BSD-3-Clause", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "license": "MIT", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" } }, - "node_modules/sparkles": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-2.1.0.tgz", - "integrity": "sha512-r7iW1bDw8R/cFifrD3JnQJX0K1jqT0kprL48BiBpLZLJPmAm34zsVBsK5lc7HirZYZqMW65dOXZgbAGt/I6frg==", + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, "engines": { - "node": ">= 10.13.0" + "node": ">=8" } }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true, - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, + "node_modules/shiki": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.21.0.tgz", + "integrity": "sha512-N65B/3bqL/TI2crrXr+4UivctrAGEjmsib5rPMMPpFp1xAx/w03v8WZ9RDDFYteXoEgY7qZ4HGgl5KBIu1153w==", "license": "MIT", "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "@shikijs/core": "3.21.0", + "@shikijs/engine-javascript": "3.21.0", + "@shikijs/engine-oniguruma": "3.21.0", + "@shikijs/langs": "3.21.0", + "@shikijs/themes": "3.21.0", + "@shikijs/types": "3.21.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" } }, - "node_modules/spdx-license-ids": { - "version": "3.0.22", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", - "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/ssri": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-13.0.0.tgz", - "integrity": "sha512-yizwGBpbCn4YomB2lzhZqrHLJoqFGXihNbib3ozhqF/cIp5ue+xSmOQrjNasEE62hFxsCcg/V/z23t4n8jMEng==", - "dev": true, - "license": "ISC", + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", "dependencies": { - "minipass": "^7.0.3" + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" }, "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/stackblur-canvas": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz", - "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==", + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "license": "MIT", - "optional": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, "engines": { - "node": ">=0.1.14" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/stdin-discarder": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", - "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", - "dev": true, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, "engines": { - "node": ">=18" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/stream-composer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-composer/-/stream-composer-1.0.2.tgz", - "integrity": "sha512-bnBselmwfX5K10AH6L4c8+S5lgZMWI7ZYrz2rvYjCPB2DIMC4Ig8OpxGpNJSxRZ58oti7y1IcNvjBAz9vW5m4w==", + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true, - "license": "MIT", - "dependencies": { - "streamx": "^2.13.2" - } + "license": "ISC" }, - "node_modules/stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sigstore": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-4.1.0.tgz", + "integrity": "sha512-/fUgUhYghuLzVT/gaJoeVehLCgZiUxPCPMcyVNY0lIf/cTCz58K/WTI7PefDarXxp9nUKpEwg1yyz3eSBMTtgA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@sigstore/bundle": "^4.0.0", + "@sigstore/core": "^3.1.0", + "@sigstore/protobuf-specs": "^0.5.0", + "@sigstore/sign": "^4.1.0", + "@sigstore/tuf": "^4.0.1", + "@sigstore/verify": "^3.1.0" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/sirv": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", + "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "dev": true, "license": "MIT" }, - "node_modules/stream-shift": { + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/smol-toml": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.0.tgz", + "integrity": "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, + "node_modules/socks": { + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ip-address": "^10.0.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/source-map": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 12" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/sparkles": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-2.1.0.tgz", + "integrity": "sha512-r7iW1bDw8R/cFifrD3JnQJX0K1jqT0kprL48BiBpLZLJPmAm34zsVBsK5lc7HirZYZqMW65dOXZgbAGt/I6frg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.22", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", + "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/sprintf-js": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", - "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/ssri": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz", + "integrity": "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/stackblur-canvas": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz", + "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.14" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, + "license": "MIT" + }, + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stream-composer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-composer/-/stream-composer-1.0.2.tgz", + "integrity": "sha512-bnBselmwfX5K10AH6L4c8+S5lgZMWI7ZYrz2rvYjCPB2DIMC4Ig8OpxGpNJSxRZ58oti7y1IcNvjBAz9vW5m4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "streamx": "^2.13.2" + } + }, + "node_modules/stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "dev": true, + "license": "MIT" + }, + "node_modules/stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/streamx": { + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", + "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stylelint": { + "version": "16.26.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.26.1.tgz", + "integrity": "sha512-v20V59/crfc8sVTAtge0mdafI3AdnzQ2KsWe6v523L4OA1bJO02S7MO2oyXDCS6iWb9ckIPnqAFVItqSBQr7jw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + }, + { + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-syntax-patches-for-csstree": "^1.0.19", + "@csstools/css-tokenizer": "^3.0.4", + "@csstools/media-query-list-parser": "^4.0.3", + "@csstools/selector-specificity": "^5.0.0", + "@dual-bundle/import-meta-resolve": "^4.2.1", + "balanced-match": "^2.0.0", + "colord": "^2.9.3", + "cosmiconfig": "^9.0.0", + "css-functions-list": "^3.2.3", + "css-tree": "^3.1.0", + "debug": "^4.4.3", + "fast-glob": "^3.3.3", + "fastest-levenshtein": "^1.0.16", + "file-entry-cache": "^11.1.1", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.3.1", + "ignore": "^7.0.5", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.37.0", + "mathml-tag-names": "^2.1.3", + "meow": "^13.2.0", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.5.6", + "postcss-resolve-nested-selector": "^0.1.6", + "postcss-safe-parser": "^7.0.1", + "postcss-selector-parser": "^7.1.0", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "string-width": "^4.2.3", + "supports-hyperlinks": "^3.2.0", + "svg-tags": "^1.0.0", + "table": "^6.9.0", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "stylelint": "bin/stylelint.mjs" + }, + "engines": { + "node": ">=18.12.0" + } + }, + "node_modules/stylelint-config-recommended": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz", + "integrity": "sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + }, + { + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], + "license": "MIT", + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "stylelint": "^16.1.0" + } + }, + "node_modules/stylelint-config-recommended-scss": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-14.1.0.tgz", + "integrity": "sha512-bhaMhh1u5dQqSsf6ri2GVWWQW5iUjBYgcHkh7SgDDn92ijoItC/cfO/W+fpXshgTQWhwFkP1rVcewcv4jaftRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-scss": "^4.0.9", + "stylelint-config-recommended": "^14.0.1", + "stylelint-scss": "^6.4.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "postcss": "^8.3.3", + "stylelint": "^16.6.1" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + } + } + }, + "node_modules/stylelint-config-standard": { + "version": "36.0.1", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-36.0.1.tgz", + "integrity": "sha512-8aX8mTzJ6cuO8mmD5yon61CWuIM4UD8Q5aBcWKGSf6kg+EC3uhB+iOywpTK4ca6ZL7B49en8yanOFtUW0qNzyw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + }, + { + "type": "github", + "url": "https://github.com/sponsors/stylelint" + } + ], + "license": "MIT", + "dependencies": { + "stylelint-config-recommended": "^14.0.1" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "stylelint": "^16.1.0" + } + }, + "node_modules/stylelint-config-standard-scss": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard-scss/-/stylelint-config-standard-scss-13.1.0.tgz", + "integrity": "sha512-Eo5w7/XvwGHWkeGLtdm2FZLOMYoZl1omP2/jgFCXyl2x5yNz7/8vv4Tj6slHvMSSUNTaGoam/GAZ0ZhukvalfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "stylelint-config-recommended-scss": "^14.0.0", + "stylelint-config-standard": "^36.0.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "postcss": "^8.3.3", + "stylelint": "^16.3.1" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + } + } + }, + "node_modules/stylelint-prettier": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/stylelint-prettier/-/stylelint-prettier-5.0.3.tgz", + "integrity": "sha512-B6V0oa35ekRrKZlf+6+jA+i50C4GXJ7X1PPmoCqSUoXN6BrNF6NhqqhanvkLjqw2qgvrS0wjdpeC+Tn06KN3jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "prettier": ">=3.0.0", + "stylelint": ">=16.0.0" + } + }, + "node_modules/stylelint-scss": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.14.0.tgz", + "integrity": "sha512-ZKmHMZolxeuYsnB+PCYrTpFce0/QWX9i9gh0hPXzp73WjuIMqUpzdQaBCrKoLWh6XtCFSaNDErkMPqdjy1/8aA==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-tree": "^3.0.1", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.37.0", + "mdn-data": "^2.25.0", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.6", + "postcss-selector-parser": "^7.1.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": ">=18.12.0" + }, + "peerDependencies": { + "stylelint": "^16.8.2" + } + }, + "node_modules/stylelint-scss/node_modules/mdn-data": { + "version": "2.26.0", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.26.0.tgz", + "integrity": "sha512-ZqI0qjKWHMPcGUfLmlr80NPNVHIOjPMHtIOe1qXYFGS0YBZ1YKAzo9yk8W+gGrLCN0Xdv/RKxqdIsqPakEfmow==", "dev": true, - "license": "MIT" + "license": "CC0-1.0" }, - "node_modules/streamroller": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", - "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", + "node_modules/stylelint-scss/node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "dev": true, "license": "MIT", "dependencies": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "fs-extra": "^8.1.0" + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" }, "engines": { - "node": ">=8.0" + "node": ">=4" } }, - "node_modules/streamroller/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "node_modules/stylelint/node_modules/@csstools/selector-specificity": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", + "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", "engines": { - "node": ">=6 <7 || >=8" + "node": ">=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^7.0.0" } }, - "node_modules/streamroller/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "node_modules/stylelint/node_modules/balanced-match": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", "dev": true, - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } + "license": "MIT" }, - "node_modules/streamroller/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "node_modules/stylelint/node_modules/file-entry-cache": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.1.tgz", + "integrity": "sha512-TPVFSDE7q91Dlk1xpFLvFllf8r0HyOMOlnWy7Z2HBku5H3KhIeOGInexrIeg2D64DosVB/JXkrrk6N/7Wriq4A==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 4.0.0" + "dependencies": { + "flat-cache": "^6.1.19" } }, - "node_modules/streamx": { - "version": "2.23.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", - "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", + "node_modules/stylelint/node_modules/flat-cache": { + "version": "6.1.19", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.19.tgz", + "integrity": "sha512-l/K33newPTZMTGAnnzaiqSl6NnH7Namh8jBNjrgjprWxGmZUuxx/sJNIRaijOh3n7q7ESbhNZC+pvVZMFdeU4A==", "dev": true, "license": "MIT", "dependencies": { - "events-universal": "^1.0.0", - "fast-fifo": "^1.3.2", - "text-decoder": "^1.1.0" + "cacheable": "^2.2.0", + "flatted": "^3.3.3", + "hookified": "^1.13.0" } }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "node_modules/stylelint/node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", "dev": true, "license": "MIT", "dependencies": { - "safe-buffer": "~5.2.0" + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/stylelint/node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" }, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/stylelint/node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/string-width-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/stylelint/node_modules/globby/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 4" } }, - "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/stylelint/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" + }, + "node_modules/stylelint/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/stylelint/node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/stylelint/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/string-width/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/stylelint/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" } }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/stringify-entities": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", - "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "node_modules/supports-hyperlinks": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", + "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", + "dev": true, "license": "MIT", "dependencies": { - "character-entities-html4": "^2.0.0", - "character-entities-legacy": "^3.0.0" + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" } }, - "node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sver": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/sver/-/sver-1.8.4.tgz", + "integrity": "sha512-71o1zfzyawLfIWBOmw8brleKyvnbn73oVHNCsu51uPMz/HWiKkkXsI31JjHW5zqXEqnPYkIiHd8ZmL7FCimLEA==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "semver": "^6.3.0" + } + }, + "node_modules/sver/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/svg-pathdata": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", + "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12.0.0" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, + "node_modules/svgo": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.0.tgz", + "integrity": "sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "commander": "^11.1.0", + "css-select": "^5.1.0", + "css-tree": "^3.0.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.1.1", + "sax": "^1.4.1" + }, + "bin": { + "svgo": "bin/svgo.js" }, "engines": { - "node": ">=8" + "node": ">=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" } }, - "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/svgo/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=16" } }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "node_modules/svgo/node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "min-indent": "^1.0.0" + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/svgo/node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "engines": { - "node": ">=8" + "node": ">= 6" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/stylelint": { - "version": "16.26.1", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.26.1.tgz", - "integrity": "sha512-v20V59/crfc8sVTAtge0mdafI3AdnzQ2KsWe6v523L4OA1bJO02S7MO2oyXDCS6iWb9ckIPnqAFVItqSBQr7jw==", + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/stylelint" - }, - { - "type": "github", - "url": "https://github.com/sponsors/stylelint" - } - ], - "license": "MIT", - "dependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-syntax-patches-for-csstree": "^1.0.19", - "@csstools/css-tokenizer": "^3.0.4", - "@csstools/media-query-list-parser": "^4.0.3", - "@csstools/selector-specificity": "^5.0.0", - "@dual-bundle/import-meta-resolve": "^4.2.1", - "balanced-match": "^2.0.0", - "colord": "^2.9.3", - "cosmiconfig": "^9.0.0", - "css-functions-list": "^3.2.3", - "css-tree": "^3.1.0", - "debug": "^4.4.3", - "fast-glob": "^3.3.3", - "fastest-levenshtein": "^1.0.16", - "file-entry-cache": "^11.1.1", - "global-modules": "^2.0.0", - "globby": "^11.1.0", - "globjoin": "^0.1.4", - "html-tags": "^3.3.1", - "ignore": "^7.0.5", - "imurmurhash": "^0.1.4", - "is-plain-object": "^5.0.0", - "known-css-properties": "^0.37.0", - "mathml-tag-names": "^2.1.3", - "meow": "^13.2.0", - "micromatch": "^4.0.8", - "normalize-path": "^3.0.0", - "picocolors": "^1.1.1", - "postcss": "^8.5.6", - "postcss-resolve-nested-selector": "^0.1.6", - "postcss-safe-parser": "^7.0.1", - "postcss-selector-parser": "^7.1.0", - "postcss-value-parser": "^4.2.0", - "resolve-from": "^5.0.0", - "string-width": "^4.2.3", - "supports-hyperlinks": "^3.2.0", - "svg-tags": "^1.0.0", - "table": "^6.9.0", - "write-file-atomic": "^5.0.1" - }, - "bin": { - "stylelint": "bin/stylelint.mjs" - }, - "engines": { - "node": ">=18.12.0" - } + "license": "MIT" }, - "node_modules/stylelint-config-recommended": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz", - "integrity": "sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg==", + "node_modules/sync-child-process": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/sync-child-process/-/sync-child-process-1.0.2.tgz", + "integrity": "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/stylelint" - }, - { - "type": "github", - "url": "https://github.com/sponsors/stylelint" - } - ], "license": "MIT", - "engines": { - "node": ">=18.12.0" + "dependencies": { + "sync-message-port": "^1.0.0" }, - "peerDependencies": { - "stylelint": "^16.1.0" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/stylelint-config-recommended-scss": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended-scss/-/stylelint-config-recommended-scss-14.1.0.tgz", - "integrity": "sha512-bhaMhh1u5dQqSsf6ri2GVWWQW5iUjBYgcHkh7SgDDn92ijoItC/cfO/W+fpXshgTQWhwFkP1rVcewcv4jaftRg==", + "node_modules/sync-message-port": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sync-message-port/-/sync-message-port-1.1.3.tgz", + "integrity": "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==", "dev": true, "license": "MIT", - "dependencies": { - "postcss-scss": "^4.0.9", - "stylelint-config-recommended": "^14.0.1", - "stylelint-scss": "^6.4.0" - }, "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "postcss": "^8.3.3", - "stylelint": "^16.6.1" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - } + "node": ">=16.0.0" } }, - "node_modules/stylelint-config-standard": { - "version": "36.0.1", - "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-36.0.1.tgz", - "integrity": "sha512-8aX8mTzJ6cuO8mmD5yon61CWuIM4UD8Q5aBcWKGSf6kg+EC3uhB+iOywpTK4ca6ZL7B49en8yanOFtUW0qNzyw==", + "node_modules/table": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/stylelint" - }, - { - "type": "github", - "url": "https://github.com/sponsors/stylelint" - } - ], - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "stylelint-config-recommended": "^14.0.1" + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "stylelint": "^16.1.0" + "node": ">=10.0.0" } }, - "node_modules/stylelint-config-standard-scss": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/stylelint-config-standard-scss/-/stylelint-config-standard-scss-13.1.0.tgz", - "integrity": "sha512-Eo5w7/XvwGHWkeGLtdm2FZLOMYoZl1omP2/jgFCXyl2x5yNz7/8vv4Tj6slHvMSSUNTaGoam/GAZ0ZhukvalfA==", + "node_modules/table/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", - "dependencies": { - "stylelint-config-recommended-scss": "^14.0.0", - "stylelint-config-standard": "^36.0.0" - }, "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "postcss": "^8.3.3", - "stylelint": "^16.3.1" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - } + "node": ">=8" } }, - "node_modules/stylelint-prettier": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/stylelint-prettier/-/stylelint-prettier-5.0.3.tgz", - "integrity": "sha512-B6V0oa35ekRrKZlf+6+jA+i50C4GXJ7X1PPmoCqSUoXN6BrNF6NhqqhanvkLjqw2qgvrS0wjdpeC+Tn06KN3jw==", + "node_modules/table/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, - "license": "MIT", - "dependencies": { - "prettier-linter-helpers": "^1.0.0" - }, + "license": "MIT", "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "prettier": ">=3.0.0", - "stylelint": ">=16.0.0" + "node": ">=8" } }, - "node_modules/stylelint-scss": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/stylelint-scss/-/stylelint-scss-6.14.0.tgz", - "integrity": "sha512-ZKmHMZolxeuYsnB+PCYrTpFce0/QWX9i9gh0hPXzp73WjuIMqUpzdQaBCrKoLWh6XtCFSaNDErkMPqdjy1/8aA==", + "node_modules/table/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, "license": "MIT", "dependencies": { - "css-tree": "^3.0.1", - "is-plain-object": "^5.0.0", - "known-css-properties": "^0.37.0", - "mdn-data": "^2.25.0", - "postcss-media-query-parser": "^0.2.3", - "postcss-resolve-nested-selector": "^0.1.6", - "postcss-selector-parser": "^7.1.1", - "postcss-value-parser": "^4.2.0" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, "engines": { - "node": ">=18.12.0" + "node": ">=10" }, - "peerDependencies": { - "stylelint": "^16.8.2" + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/stylelint-scss/node_modules/mdn-data": { - "version": "2.26.0", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.26.0.tgz", - "integrity": "sha512-ZqI0qjKWHMPcGUfLmlr80NPNVHIOjPMHtIOe1qXYFGS0YBZ1YKAzo9yk8W+gGrLCN0Xdv/RKxqdIsqPakEfmow==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/stylelint-scss/node_modules/postcss-selector-parser": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", - "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "node_modules/table/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/stylelint/node_modules/@csstools/selector-specificity": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-5.0.0.tgz", - "integrity": "sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==", + "node_modules/tar": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.2.tgz", + "integrity": "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, "engines": { "node": ">=18" - }, - "peerDependencies": { - "postcss-selector-parser": "^7.0.0" } }, - "node_modules/stylelint/node_modules/balanced-match": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", - "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", - "dev": true, - "license": "MIT" - }, - "node_modules/stylelint/node_modules/file-entry-cache": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.2.tgz", - "integrity": "sha512-N2WFfK12gmrK1c1GXOqiAJ1tc5YE+R53zvQ+t5P8S5XhnmKYVB5eZEiLNZKDSmoG8wqqbF9EXYBBW/nef19log==", + "node_modules/tar-fs": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz", + "integrity": "sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^6.1.20" + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^4.0.1", + "bare-path": "^3.0.0" } }, - "node_modules/stylelint/node_modules/flat-cache": { - "version": "6.1.20", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.20.tgz", - "integrity": "sha512-AhHYqwvN62NVLp4lObVXGVluiABTHapoB57EyegZVmazN+hhGhLTn3uZbOofoTw4DSDvVCadzzyChXhOAvy8uQ==", + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", "dev": true, "license": "MIT", "dependencies": { - "cacheable": "^2.3.2", - "flatted": "^3.3.3", - "hookified": "^1.15.0" + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" } }, - "node_modules/stylelint/node_modules/global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", "dev": true, - "license": "MIT", - "dependencies": { - "global-prefix": "^3.0.0" - }, + "license": "BlueOak-1.0.0", "engines": { - "node": ">=6" + "node": ">=18" } }, - "node_modules/stylelint/node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "node_modules/teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", "dev": true, "license": "MIT", "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "engines": { - "node": ">=6" + "streamx": "^2.12.5" } }, - "node_modules/stylelint/node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/term-size": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", + "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", "dev": true, "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/stylelint/node_modules/globby/node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "node_modules/text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" } }, - "node_modules/stylelint/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, - "license": "ISC" - }, - "node_modules/stylelint/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", "license": "MIT", - "engines": { - "node": ">=0.10.0" + "optional": true, + "dependencies": { + "utrie": "^1.0.2" } }, - "node_modules/stylelint/node_modules/postcss-selector-parser": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", - "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "license": "MIT", "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" } }, - "node_modules/stylelint/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/stylelint/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "license": "ISC", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" + "through2": "~2.0.0", + "xtend": "~4.0.0" } }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/supports-hyperlinks": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", - "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", + "node_modules/through2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/through2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=14.18" - }, - "funding": { - "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" + "safe-buffer": "~5.1.0" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "node_modules/time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha512-gLCeArryy2yNTRzTGKbZbloctj64jkZ57hj5zdraXue6aFgd6PmvVtEyiUU+hvU0v7q08oVv8r8ev0tRo6bvgw==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/sver": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/sver/-/sver-1.8.4.tgz", - "integrity": "sha512-71o1zfzyawLfIWBOmw8brleKyvnbn73oVHNCsu51uPMz/HWiKkkXsI31JjHW5zqXEqnPYkIiHd8ZmL7FCimLEA==", + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", "dev": true, - "license": "MIT", - "optionalDependencies": { - "semver": "^6.3.0" - } + "license": "MIT" }, - "node_modules/sver/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", "dev": true, - "license": "ISC", - "optional": true, - "bin": { - "semver": "bin/semver.js" - } + "license": "MIT" }, - "node_modules/svg-pathdata": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", - "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", + "node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "dev": true, "license": "MIT", - "optional": true, "engines": { - "node": ">=12.0.0" + "node": ">=18" } }, - "node_modules/svg-tags": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", - "dev": true - }, - "node_modules/svgo": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.0.tgz", - "integrity": "sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==", + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, "license": "MIT", "dependencies": { - "commander": "^11.1.0", - "css-select": "^5.1.0", - "css-tree": "^3.0.1", - "css-what": "^6.1.0", - "csso": "^5.0.5", - "picocolors": "^1.1.1", - "sax": "^1.4.1" - }, - "bin": { - "svgo": "bin/svgo.js" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { - "node": ">=16" + "node": ">=12.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/svgo" + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/svgo/node_modules/commander": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "node_modules/tinyrainbow": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", + "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", "dev": true, "license": "MIT", "engines": { - "node": ">=16" + "node": ">=14.0.0" } }, - "node_modules/svgo/node_modules/css-select": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", - "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "node_modules/tldts": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", + "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/svgo/node_modules/css-what": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", - "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">= 6" + "tldts-core": "^6.1.86" }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "bin": { + "tldts": "bin/cli.js" } }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "node_modules/tldts-core": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", + "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", "dev": true, "license": "MIT" }, - "node_modules/sync-child-process": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/sync-child-process/-/sync-child-process-1.0.2.tgz", - "integrity": "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==", + "node_modules/to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha512-rtwLUQEwT8ZeKQbyFJyomBRYXyE16U5VKuy0ftxLMK/PZb2fkOsg5r9kHdauuVDbsNdIBoC/HCthpidamQFXYA==", "dev": true, "license": "MIT", "dependencies": { - "sync-message-port": "^1.0.0" + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=0.10.0" } }, - "node_modules/sync-message-port": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sync-message-port/-/sync-message-port-1.1.3.tgz", - "integrity": "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==", + "node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", "dev": true, "license": "MIT", "engines": { - "node": ">=16.0.0" + "node": ">=6" } }, - "node_modules/table": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", - "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" + "is-number": "^7.0.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=8.0" } }, - "node_modules/table/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/to-through": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-3.0.0.tgz", + "integrity": "sha512-y8MN937s/HVhEoBU1SxfHC+wxCHkV1a9gW8eAdTadYh/bGyesZIVcbjI+mSpFbSVwQici/XjBjuUyri1dnXwBw==", "dev": true, "license": "MIT", + "dependencies": { + "streamx": "^2.12.5" + }, "engines": { - "node": ">=8" + "node": ">=10.13.0" } }, - "node_modules/table/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.6" } }, - "node_modules/table/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", "dev": true, "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "node": ">=6" } }, - "node_modules/table/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/tough-cookie/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, "engines": { - "node": ">=8" + "node": ">= 4.0.0" } }, - "node_modules/tar": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.6.tgz", - "integrity": "sha512-xqUeu2JAIJpXyvskvU3uvQW8PAmHrtXp2KDuMJwQqW8Sqq0CaZBAQ+dKS3RBXVhU4wC5NjAdKrmh84241gO9cA==", + "node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.1.0", - "yallist": "^5.0.0" + "punycode": "^2.3.1" }, "engines": { "node": ">=18" } }, - "node_modules/tar-fs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.1.tgz", - "integrity": "sha512-LZA0oaPOc2fVo82Txf3gw+AkEd38szODlptMYejQUhndHMLQ9M059uXR+AfS7DNo0NpINvSqDsvyaCrBVkptWg==", + "node_modules/tr46/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", - "dependencies": { - "pump": "^3.0.0", - "tar-stream": "^3.1.5" - }, - "optionalDependencies": { - "bare-fs": "^4.0.1", - "bare-path": "^3.0.0" + "engines": { + "node": ">=6" } }, - "node_modules/tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "dev": true, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", "license": "MIT", - "dependencies": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/teex": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", - "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", "dev": true, "license": "MIT", - "dependencies": { - "streamx": "^2.12.5" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/term-size": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", - "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", + "node_modules/ts-api-utils": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=18.12" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "typescript": ">=4.8.4" } }, - "node_modules/text-decoder": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", - "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "b4a": "^1.6.4" - } - }, - "node_modules/text-segmentation": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", - "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", "license": "MIT", - "optional": true, "dependencies": { - "utrie": "^1.0.2" + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } } }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" } }, - "node_modules/through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "node_modules/tsconfck": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.6.tgz", + "integrity": "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==", "dev": true, "license": "MIT", - "dependencies": { - "through2": "~2.0.0", - "xtend": "~4.0.0" + "bin": { + "tsconfck": "bin/tsconfck.js" + }, + "engines": { + "node": "^18 || >=20" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/through2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tuf-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-4.1.0.tgz", + "integrity": "sha512-50QV99kCKH5P/Vs4E2Gzp7BopNV+KzTXqWeaxrfu5IQJBOULRsTIS9seSsOVT8ZnGXzCyx55nYWAi4qJzpZKEQ==", "dev": true, "license": "MIT", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "@tufjs/models": "4.1.0", + "debug": "^4.4.3", + "make-fetch-happen": "^15.0.1" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/through2/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/through2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", "dependencies": { - "safe-buffer": "~5.1.0" + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha512-gLCeArryy2yNTRzTGKbZbloctj64jkZ57hj5zdraXue6aFgd6PmvVtEyiUU+hvU0v7q08oVv8r8ev0tRo6bvgw==", + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/tiny-inflate": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", - "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", + "node_modules/typed-query-selector": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz", + "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==", + "dev": true, + "license": "MIT" + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", "dev": true, "license": "MIT" }, - "node_modules/tinyexec": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", - "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "dev": true, "license": "MIT", - "engines": { - "node": ">=18" + "dependencies": { + "is-typedarray": "^1.0.0" } }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "node_modules/typedoc": { + "version": "0.28.16", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.16.tgz", + "integrity": "sha512-x4xW77QC3i5DUFMBp0qjukOTnr/sSg+oEs86nB3LjDslvAmwe/PUGDWbe3GrIqt59oTqoXK5GRK9tAa0sYMiog==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "@gerrit0/mini-shiki": "^3.17.0", + "lunr": "^2.3.9", + "markdown-it": "^14.1.0", + "minimatch": "^9.0.5", + "yaml": "^2.8.1" + }, + "bin": { + "typedoc": "bin/typedoc" }, "engines": { - "node": ">=12.0.0" + "node": ">= 18", + "pnpm": ">= 10" }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" + "peerDependencies": { + "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x" } }, - "node_modules/tldts": { - "version": "6.1.86", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", - "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", + "node_modules/typedoc-plugin-localization": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/typedoc-plugin-localization/-/typedoc-plugin-localization-3.1.0.tgz", + "integrity": "sha512-IiLBuWzMnn+IzIF8LpqSuKDEi6HLQ/D+Rd62ZnZwO4bVpKnKBZLhiaQuJPWmLoWxSVL/K2RhEY3Sz/UT2RVmHA==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.86" - }, + "fs-extra": "^11.2.0" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", "bin": { - "tldts": "bin/cli.js" + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" } }, - "node_modules/tldts-core": { - "version": "6.1.86", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", - "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", "dev": true, "license": "MIT" }, - "node_modules/tmp": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", - "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "node_modules/ufo": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.2.tgz", + "integrity": "sha512-heMioaxBcG9+Znsda5Q8sQbWnLJSl98AFDXTO80wELWEzX3hordXsTdxrIfMQoO9IY1MEnoGoPjpoKpMj+Yx0Q==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.14" - } + "license": "MIT" }, - "node_modules/to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha512-rtwLUQEwT8ZeKQbyFJyomBRYXyE16U5VKuy0ftxLMK/PZb2fkOsg5r9kHdauuVDbsNdIBoC/HCthpidamQFXYA==", + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "dev": true, - "license": "MIT", - "dependencies": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" + "license": "BSD-2-Clause", + "bin": { + "uglifyjs": "bin/uglifyjs" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.8.0" } }, - "node_modules/to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "node_modules/ultrahtml": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.6.0.tgz", + "integrity": "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==", + "dev": true, + "license": "MIT" + }, + "node_modules/unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/uncrypto": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", + "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/undertaker": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-2.0.0.tgz", + "integrity": "sha512-tO/bf30wBbTsJ7go80j0RzA2rcwX6o7XPBpeFcb+jzoeb4pfMM2zUeSDIkY1AWqeZabWxaQZ/h8N9t35QKDLPQ==", "dev": true, "license": "MIT", "dependencies": { - "is-number": "^7.0.0" + "bach": "^2.0.1", + "fast-levenshtein": "^3.0.0", + "last-run": "^2.0.0", + "undertaker-registry": "^2.0.0" }, "engines": { - "node": ">=8.0" + "node": ">=10.13.0" } }, - "node_modules/to-through": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-3.0.0.tgz", - "integrity": "sha512-y8MN937s/HVhEoBU1SxfHC+wxCHkV1a9gW8eAdTadYh/bGyesZIVcbjI+mSpFbSVwQici/XjBjuUyri1dnXwBw==", + "node_modules/undertaker-registry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-2.0.0.tgz", + "integrity": "sha512-+hhVICbnp+rlzZMgxXenpvTxpuvA67Bfgtt+O9WOE5jo7w/dyiF1VmoZVIHvP2EkUjsyKyTwYKlLhA+j47m1Ew==", "dev": true, "license": "MIT", - "dependencies": { - "streamx": "^2.12.5" - }, "engines": { - "node": ">=10.13.0" + "node": ">= 10.13.0" } }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "node_modules/undertaker/node_modules/fast-levenshtein": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-3.0.0.tgz", + "integrity": "sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=0.6" + "dependencies": { + "fastest-levenshtein": "^1.0.7" } }, - "node_modules/totalist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "node_modules/undici": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.16.0.tgz", + "integrity": "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=20.18.1" } }, - "node_modules/tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT" + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "dev": true, + "license": "MIT", "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" }, - "engines": { - "node": ">=6" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/tough-cookie/node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "node_modules/unifont": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.7.1.tgz", + "integrity": "sha512-0lg9M1cMYvXof8//wZBq6EDEfbwv4++t7+dYpXeS2ypaLuZJmUFYEwTm412/1ED/Wfo/wyzSu6kNZEr9hgRNfg==", "dev": true, "license": "MIT", + "dependencies": { + "css-tree": "^3.1.0", + "ofetch": "^1.5.1", + "ohash": "^2.0.11" + } + }, + "node_modules/unique-filename": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-5.0.0.tgz", + "integrity": "sha512-2RaJTAvAb4owyjllTfXzFClJ7WsGxlykkPvCr9pA//LD9goVq+m4PPAeBgNodGZ7nSrntT/auWpJ6Y5IFXcfjg==", + "dev": true, + "license": "ISC", + "dependencies": { + "unique-slug": "^6.0.0" + }, "engines": { - "node": ">=6" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/tough-cookie/node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "node_modules/unique-slug": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-6.0.0.tgz", + "integrity": "sha512-4Lup7Ezn8W3d52/xBhZBVdx323ckxa7DEvd9kPQHppTkLoJXw6ltrBCyj5pnrxj0qKDxYMJ56CoxNuFCscdTiw==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + }, "engines": { - "node": ">= 4.0.0" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/tr46": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", - "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "node_modules/unique-stream": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.4.0.tgz", + "integrity": "sha512-V6QarSfeSgDipGA9EZdoIzu03ZDlOFkk+FbEP5cwgrZXN3iIkYR91IjU2EnM6rB835kGQsqHX8qncObTXV+6KA==", "dev": true, "license": "MIT", "dependencies": { - "punycode": "^2.3.1" - }, - "engines": { - "node": ">=18" + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "3.0.0" } }, - "node_modules/tr46/node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", "dev": true, "license": "MIT", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/trim-lines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", - "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "node_modules/unist-util-find-after": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "dev": true, "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/trough": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", - "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", - "dev": true, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/ts-api-utils": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", - "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", + "node_modules/unist-util-modify-children": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-4.0.0.tgz", + "integrity": "sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=18.12" + "dependencies": { + "@types/unist": "^3.0.0", + "array-iterate": "^2.0.0" }, - "peerDependencies": { - "typescript": ">=4.8.4" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", "license": "MIT", "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" + "@types/unist": "^3.0.0" }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/ts-node/node_modules/diff": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", - "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/tsconfck": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.6.tgz", - "integrity": "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==", + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", "dev": true, "license": "MIT", - "bin": { - "tsconfck": "bin/tsconfck.js" - }, - "engines": { - "node": "^18 || >=20" - }, - "peerDependencies": { - "typescript": "^5.0.0" + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/tuf-js": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-4.1.0.tgz", - "integrity": "sha512-50QV99kCKH5P/Vs4E2Gzp7BopNV+KzTXqWeaxrfu5IQJBOULRsTIS9seSsOVT8ZnGXzCyx55nYWAi4qJzpZKEQ==", - "dev": true, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "license": "MIT", "dependencies": { - "@tufjs/models": "4.1.0", - "debug": "^4.4.3", - "make-fetch-happen": "^15.0.1" + "@types/unist": "^3.0.0" }, - "engines": { - "node": "^20.17.0 || >=22.9.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" }, - "engines": { - "node": ">= 0.8.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "node_modules/unist-util-visit-children": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-3.0.0.tgz", + "integrity": "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==", "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", "license": "MIT", "dependencies": { - "content-type": "^1.0.5", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" }, - "engines": { - "node": ">= 0.6" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/typed-query-selector": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz", - "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==", - "dev": true, - "license": "MIT" - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", - "dependencies": { - "is-typedarray": "^1.0.0" + "engines": { + "node": ">= 10.0.0" } }, - "node_modules/typedoc": { - "version": "0.28.16", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.16.tgz", - "integrity": "sha512-x4xW77QC3i5DUFMBp0qjukOTnr/sSg+oEs86nB3LjDslvAmwe/PUGDWbe3GrIqt59oTqoXK5GRK9tAa0sYMiog==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@gerrit0/mini-shiki": "^3.17.0", - "lunr": "^2.3.9", - "markdown-it": "^14.1.0", - "minimatch": "^9.0.5", - "yaml": "^2.8.1" - }, - "bin": { - "typedoc": "bin/typedoc" - }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { - "node": ">= 18", - "pnpm": ">= 10" - }, - "peerDependencies": { - "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x" + "node": ">= 0.8" } }, - "node_modules/typedoc-plugin-localization": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/typedoc-plugin-localization/-/typedoc-plugin-localization-3.1.0.tgz", - "integrity": "sha512-IiLBuWzMnn+IzIF8LpqSuKDEi6HLQ/D+Rd62ZnZwO4bVpKnKBZLhiaQuJPWmLoWxSVL/K2RhEY3Sz/UT2RVmHA==", + "node_modules/unstorage": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.3.tgz", + "integrity": "sha512-i+JYyy0DoKmQ3FximTHbGadmIYb8JEpq7lxUjnjeB702bCPum0vzo6oy5Mfu0lpqISw7hCyMW2yj4nWC8bqJ3Q==", "dev": true, "license": "MIT", "dependencies": { - "fs-extra": "^11.2.0" + "anymatch": "^3.1.3", + "chokidar": "^4.0.3", + "destr": "^2.0.5", + "h3": "^1.15.4", + "lru-cache": "^10.4.3", + "node-fetch-native": "^1.6.7", + "ofetch": "^1.5.1", + "ufo": "^1.6.1" + }, + "peerDependencies": { + "@azure/app-configuration": "^1.8.0", + "@azure/cosmos": "^4.2.0", + "@azure/data-tables": "^13.3.0", + "@azure/identity": "^4.6.0", + "@azure/keyvault-secrets": "^4.9.0", + "@azure/storage-blob": "^12.26.0", + "@capacitor/preferences": "^6.0.3 || ^7.0.0", + "@deno/kv": ">=0.9.0", + "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", + "@planetscale/database": "^1.19.0", + "@upstash/redis": "^1.34.3", + "@vercel/blob": ">=0.27.1", + "@vercel/functions": "^2.2.12 || ^3.0.0", + "@vercel/kv": "^1.0.1", + "aws4fetch": "^1.0.20", + "db0": ">=0.2.1", + "idb-keyval": "^6.2.1", + "ioredis": "^5.4.2", + "uploadthing": "^7.4.4" + }, + "peerDependenciesMeta": { + "@azure/app-configuration": { + "optional": true + }, + "@azure/cosmos": { + "optional": true + }, + "@azure/data-tables": { + "optional": true + }, + "@azure/identity": { + "optional": true + }, + "@azure/keyvault-secrets": { + "optional": true + }, + "@azure/storage-blob": { + "optional": true + }, + "@capacitor/preferences": { + "optional": true + }, + "@deno/kv": { + "optional": true + }, + "@netlify/blobs": { + "optional": true + }, + "@planetscale/database": { + "optional": true + }, + "@upstash/redis": { + "optional": true + }, + "@vercel/blob": { + "optional": true + }, + "@vercel/functions": { + "optional": true + }, + "@vercel/kv": { + "optional": true + }, + "aws4fetch": { + "optional": true + }, + "db0": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "uploadthing": { + "optional": true + } } }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "node_modules/unstorage/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } + "license": "ISC" }, - "node_modules/ua-parser-js": { - "version": "0.7.41", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.41.tgz", - "integrity": "sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg==", + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" + "url": "https://opencollective.com/browserslist" }, { - "type": "paypal", - "url": "https://paypal.me/faisalman" + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" }, { "type": "github", - "url": "https://github.com/sponsors/faisalman" + "url": "https://github.com/sponsors/ai" } ], "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, "bin": { - "ua-parser-js": "script/cli.js" + "update-browserslist-db": "cli.js" }, - "engines": { - "node": "*" + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "node_modules/uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "dev": true, - "license": "MIT" - }, - "node_modules/ufo": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", - "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/uglify-js": { - "version": "3.19.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", - "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "node_modules/update-notifier": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", + "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==", "dev": true, "license": "BSD-2-Clause", - "bin": { - "uglifyjs": "bin/uglifyjs" + "dependencies": { + "boxen": "^4.2.0", + "chalk": "^3.0.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.3.1", + "is-npm": "^4.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.0.0", + "pupa": "^2.0.1", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" }, "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/ultrahtml": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.6.0.tgz", - "integrity": "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==", - "dev": true, - "license": "MIT" - }, - "node_modules/unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" } }, - "node_modules/uncrypto": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", - "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/undertaker": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-2.0.0.tgz", - "integrity": "sha512-tO/bf30wBbTsJ7go80j0RzA2rcwX6o7XPBpeFcb+jzoeb4pfMM2zUeSDIkY1AWqeZabWxaQZ/h8N9t35QKDLPQ==", + "node_modules/update-notifier/node_modules/boxen": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", + "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", "dev": true, "license": "MIT", "dependencies": { - "bach": "^2.0.1", - "fast-levenshtein": "^3.0.0", - "last-run": "^2.0.0", - "undertaker-registry": "^2.0.0" + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^3.0.0", + "cli-boxes": "^2.2.0", + "string-width": "^4.1.0", + "term-size": "^2.1.0", + "type-fest": "^0.8.1", + "widest-line": "^3.1.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/undertaker-registry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-2.0.0.tgz", - "integrity": "sha512-+hhVICbnp+rlzZMgxXenpvTxpuvA67Bfgtt+O9WOE5jo7w/dyiF1VmoZVIHvP2EkUjsyKyTwYKlLhA+j47m1Ew==", + "node_modules/update-notifier/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, "license": "MIT", "engines": { - "node": ">= 10.13.0" + "node": ">=6" } }, - "node_modules/undertaker/node_modules/fast-levenshtein": { + "node_modules/update-notifier/node_modules/chalk": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-3.0.0.tgz", - "integrity": "sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ==", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "license": "MIT", "dependencies": { - "fastest-levenshtein": "^1.0.7" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/undici": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.18.0.tgz", - "integrity": "sha512-CfPufgPFHCYu0W4h1NiKW9+tNJ39o3kWm7Cm29ET1enSJx+AERfz7A2wAr26aY0SZbYzZlTBQtcHy15o60VZfQ==", + "node_modules/update-notifier/node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", "dev": true, "license": "MIT", "engines": { - "node": ">=20.18.1" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "node_modules/update-notifier/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, - "license": "MIT" + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } }, - "node_modules/unified": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", - "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "node_modules/update-notifier/node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0", - "bail": "^2.0.0", - "devlop": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^6.0.0" + "string-width": "^4.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">=8" } }, - "node_modules/unifont": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.7.3.tgz", - "integrity": "sha512-b0GtQzKCyuSHGsfj5vyN8st7muZ6VCI4XD4vFlr7Uy1rlWVYxC3npnfk8MyreHxJYrz1ooLDqDzFe9XqQTlAhA==", + "node_modules/upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==", "dev": true, - "license": "MIT", - "dependencies": { - "css-tree": "^3.1.0", - "ofetch": "^1.5.1", - "ohash": "^2.0.11" - } + "license": "MIT" }, - "node_modules/unique-filename": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-5.0.0.tgz", - "integrity": "sha512-2RaJTAvAb4owyjllTfXzFClJ7WsGxlykkPvCr9pA//LD9goVq+m4PPAeBgNodGZ7nSrntT/auWpJ6Y5IFXcfjg==", + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "license": "ISC", + "license": "BSD-2-Clause", "dependencies": { - "unique-slug": "^6.0.0" - }, - "engines": { - "node": "^20.17.0 || >=22.9.0" + "punycode": "^2.1.0" } }, - "node_modules/unique-slug": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-6.0.0.tgz", - "integrity": "sha512-4Lup7Ezn8W3d52/xBhZBVdx323ckxa7DEvd9kPQHppTkLoJXw6ltrBCyj5pnrxj0qKDxYMJ56CoxNuFCscdTiw==", + "node_modules/uri-js/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, + "license": "MIT", "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=6" } }, - "node_modules/unique-stream": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.4.0.tgz", - "integrity": "sha512-V6QarSfeSgDipGA9EZdoIzu03ZDlOFkk+FbEP5cwgrZXN3iIkYR91IjU2EnM6rB835kGQsqHX8qncObTXV+6KA==", + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "dev": true, "license": "MIT", "dependencies": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "3.0.0" + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" } }, - "node_modules/unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", "dev": true, "license": "MIT", "dependencies": { - "crypto-random-string": "^2.0.0" + "prepend-http": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/unist-util-find-after": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", - "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true, + "license": "MIT" + }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", "license": "MIT", + "optional": true, "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "base64-arraybuffer": "^1.0.2" } }, - "node_modules/unist-util-is": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", - "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/v8flags": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-4.0.1.tgz", + "integrity": "sha512-fcRLaS4H/hrZk9hYwbdRM35D0U8IYMfEClhXxCivOojl+yTRAZH3Zy2sSy6qVCiGbV9YAtPssP6jaChqC9vPCg==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">= 10.13.0" } }, - "node_modules/unist-util-modify-children": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-4.0.0.tgz", - "integrity": "sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==", + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "@types/unist": "^3.0.0", - "array-iterate": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, - "node_modules/unist-util-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", - "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node_modules/validate-npm-package-name": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-6.0.2.tgz", + "integrity": "sha512-IUoow1YUtvoBBC06dXs8bR8B9vuA3aJfmQNKMoaPG/OFsPmoQvw8xh+6Ye25Gx9DQhoEom3Pcu9MKHerm/NpUQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/unist-util-remove-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", - "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "node_modules/value-or-function": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-4.0.0.tgz", + "integrity": "sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg==", "dev": true, "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-visit": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">= 10.13.0" } }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "node_modules/varint": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", + "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", + "dev": true, + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">= 0.8" } }, - "node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" + "vfile-message": "^4.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-visit-children": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-3.0.0.tgz", - "integrity": "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==", + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^3.0.0" + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", - "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" + "unist-util-stringify-position": "^4.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "node_modules/vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", "dev": true, "license": "MIT", + "dependencies": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + }, "engines": { - "node": ">= 10.0.0" + "node": ">= 0.10" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "node_modules/vinyl-contents": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-contents/-/vinyl-contents-2.0.0.tgz", + "integrity": "sha512-cHq6NnGyi2pZ7xwdHSW1v4Jfnho4TEGtxZHw01cmnc8+i7jgR6bRnED/LbrKan/Q7CvVLbnvA5OepnhbpjBZ5Q==", + "dev": true, "license": "MIT", + "dependencies": { + "bl": "^5.0.0", + "vinyl": "^3.0.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=10.13.0" } }, - "node_modules/unstorage": { - "version": "1.17.4", - "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.4.tgz", - "integrity": "sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw==", + "node_modules/vinyl-contents/node_modules/replace-ext": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", + "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/vinyl-contents/node_modules/vinyl": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.1.tgz", + "integrity": "sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==", "dev": true, "license": "MIT", "dependencies": { - "anymatch": "^3.1.3", - "chokidar": "^5.0.0", - "destr": "^2.0.5", - "h3": "^1.15.5", - "lru-cache": "^11.2.0", - "node-fetch-native": "^1.6.7", - "ofetch": "^1.5.1", - "ufo": "^1.6.3" - }, - "peerDependencies": { - "@azure/app-configuration": "^1.8.0", - "@azure/cosmos": "^4.2.0", - "@azure/data-tables": "^13.3.0", - "@azure/identity": "^4.6.0", - "@azure/keyvault-secrets": "^4.9.0", - "@azure/storage-blob": "^12.26.0", - "@capacitor/preferences": "^6 || ^7 || ^8", - "@deno/kv": ">=0.9.0", - "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", - "@planetscale/database": "^1.19.0", - "@upstash/redis": "^1.34.3", - "@vercel/blob": ">=0.27.1", - "@vercel/functions": "^2.2.12 || ^3.0.0", - "@vercel/kv": "^1 || ^2 || ^3", - "aws4fetch": "^1.0.20", - "db0": ">=0.2.1", - "idb-keyval": "^6.2.1", - "ioredis": "^5.4.2", - "uploadthing": "^7.4.4" + "clone": "^2.1.2", + "remove-trailing-separator": "^1.1.0", + "replace-ext": "^2.0.0", + "teex": "^1.0.1" }, - "peerDependenciesMeta": { - "@azure/app-configuration": { - "optional": true - }, - "@azure/cosmos": { - "optional": true - }, - "@azure/data-tables": { - "optional": true - }, - "@azure/identity": { - "optional": true - }, - "@azure/keyvault-secrets": { - "optional": true - }, - "@azure/storage-blob": { - "optional": true - }, - "@capacitor/preferences": { - "optional": true - }, - "@deno/kv": { - "optional": true - }, - "@netlify/blobs": { - "optional": true - }, - "@planetscale/database": { - "optional": true - }, - "@upstash/redis": { - "optional": true - }, - "@vercel/blob": { - "optional": true - }, - "@vercel/functions": { - "optional": true - }, - "@vercel/kv": { - "optional": true - }, - "aws4fetch": { - "optional": true - }, - "db0": { - "optional": true - }, - "idb-keyval": { - "optional": true - }, - "ioredis": { - "optional": true - }, - "uploadthing": { - "optional": true - } + "engines": { + "node": ">=10.13.0" } }, - "node_modules/unstorage/node_modules/lru-cache": { - "version": "11.2.4", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz", - "integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==", + "node_modules/vinyl-fs": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-4.0.2.tgz", + "integrity": "sha512-XRFwBLLTl8lRAOYiBqxY279wY46tVxLaRhSwo3GzKEuLz1giffsOquWWboD/haGf5lx+JyTigCFfe7DWHoARIA==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", + "dependencies": { + "fs-mkdirp-stream": "^2.0.1", + "glob-stream": "^8.0.3", + "graceful-fs": "^4.2.11", + "iconv-lite": "^0.6.3", + "is-valid-glob": "^1.0.0", + "lead": "^4.0.0", + "normalize-path": "3.0.0", + "resolve-options": "^2.0.0", + "stream-composer": "^1.0.2", + "streamx": "^2.14.0", + "to-through": "^3.0.0", + "value-or-function": "^4.0.0", + "vinyl": "^3.0.1", + "vinyl-sourcemap": "^2.0.0" + }, "engines": { - "node": "20 || >=22" + "node": ">=10.13.0" } }, - "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "node_modules/vinyl-fs/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/update-notifier": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", - "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==", + "node_modules/vinyl-fs/node_modules/replace-ext": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", + "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/vinyl-fs/node_modules/vinyl": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.1.tgz", + "integrity": "sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==", + "dev": true, + "license": "MIT", "dependencies": { - "boxen": "^4.2.0", - "chalk": "^3.0.0", - "configstore": "^5.0.1", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.3.1", - "is-npm": "^4.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.0.0", - "pupa": "^2.0.1", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" + "clone": "^2.1.2", + "remove-trailing-separator": "^1.1.0", + "replace-ext": "^2.0.0", + "teex": "^1.0.1" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/yeoman/update-notifier?sponsor=1" + "node": ">=10.13.0" } }, - "node_modules/update-notifier/node_modules/boxen": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", - "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", + "node_modules/vinyl-source-stream": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz", + "integrity": "sha512-X+1Jq+M6ufv/ky480hndPBsNb0ieqTQkvpakxMTxb7oUlyuNaJKL2HddYUrbTec0Lb0J53JlDiCetcgJ3b3Wmg==", "dev": true, "license": "MIT", "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^5.3.1", - "chalk": "^3.0.0", - "cli-boxes": "^2.2.0", - "string-width": "^4.1.0", - "term-size": "^2.1.0", - "type-fest": "^0.8.1", - "widest-line": "^3.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "through2": "^2.0.3", + "vinyl": "^0.4.3" } }, - "node_modules/update-notifier/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/vinyl-source-stream/node_modules/clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha512-g62n3Kb9cszeZvmvBUqP/dsEJD/+80pDA8u8KqHnAPrVnQ2Je9rVV6opxkhuWCd1kCn2gOibzDKxCtBvD3q5kA==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": "*" } }, - "node_modules/update-notifier/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "node_modules/vinyl-source-stream/node_modules/clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha512-dhUqc57gSMCo6TX85FLfe51eC/s+Im2MLkAgJwfaRRexR2tA4dd3eLEW4L6efzHc2iNorrRRXITifnDLlRrhaA==", + "dev": true, + "license": "MIT" + }, + "node_modules/vinyl-source-stream/node_modules/vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha512-pmza4M5VA15HOImIQYWhoXGlGNafCm0QK5BpBUXkzzEwrRxKqBsbAhTfkT2zMcJhUX1G1Gkid0xaV8WjOl7DsA==", "dev": true, - "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "clone": "^0.2.0", + "clone-stats": "^0.0.1" }, "engines": { - "node": ">=8" + "node": ">= 0.9" } }, - "node_modules/update-notifier/node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "node_modules/vinyl-sourcemap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-2.0.0.tgz", + "integrity": "sha512-BAEvWxbBUXvlNoFQVFVHpybBbjW1r03WhohJzJDSfgrrK5xVYIDTan6xN14DlyImShgDRv2gl9qhM6irVMsV0Q==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "convert-source-map": "^2.0.0", + "graceful-fs": "^4.2.10", + "now-and-later": "^3.0.0", + "streamx": "^2.12.5", + "vinyl": "^3.0.0", + "vinyl-contents": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=10.13.0" } }, - "node_modules/update-notifier/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "node_modules/vinyl-sourcemap/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "MIT" + }, + "node_modules/vinyl-sourcemap/node_modules/replace-ext": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", + "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 10" } }, - "node_modules/update-notifier/node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "node_modules/vinyl-sourcemap/node_modules/vinyl": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.1.tgz", + "integrity": "sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==", "dev": true, "license": "MIT", "dependencies": { - "string-width": "^4.0.0" + "clone": "^2.1.2", + "remove-trailing-separator": "^1.1.0", + "replace-ext": "^2.0.0", + "teex": "^1.0.1" }, "engines": { - "node": ">=8" + "node": ">=10.13.0" } }, - "node_modules/upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==", - "dev": true, - "license": "MIT" - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "node_modules/vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha512-+oDh3KYZBoZC8hfocrbrxbLUeaYtQK7J5WU5Br9VqWqmCll3tFJqKp97GC9GmMsVIL0qnx2DgEDVxdo5EZ5sSw==", "dev": true, - "license": "BSD-2-Clause", + "license": "ISC", "dependencies": { - "punycode": "^2.1.0" + "source-map": "^0.5.1" } }, - "node_modules/uri-js/node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "node_modules/vinyl-sourcemaps-apply/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "node_modules/vinyl-string": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/vinyl-string/-/vinyl-string-1.0.2.tgz", + "integrity": "sha512-mDkPUvCM7K9r0WYZKIWc/dfPH8wkJBbe/3wZUU9EJyw3g6VSACg6FLlcZ/QbP1lTSdtBsVjQoYG1a9K0cfoKeQ==", "dev": true, "license": "MIT", "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" + "vinyl": "^1.1.1" } }, - "node_modules/url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", + "node_modules/vinyl-string/node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "dev": true, "license": "MIT", - "dependencies": { - "prepend-http": "^2.0.0" - }, "engines": { - "node": ">=4" + "node": ">=0.8" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "node_modules/vinyl-string/node_modules/clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha512-dhUqc57gSMCo6TX85FLfe51eC/s+Im2MLkAgJwfaRRexR2tA4dd3eLEW4L6efzHc2iNorrRRXITifnDLlRrhaA==", "dev": true, "license": "MIT" }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "node_modules/vinyl-string/node_modules/replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha512-AFBWBy9EVRTa/LhEcG8QDP3FvpwZqmvN2QFDuJswFeaVhWnZMp8q3E6Zd90SR04PlIwfGdyVjNyLPyen/ek5CQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/vinyl-string/node_modules/vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha512-Ci3wnR2uuSAWFMSglZuB8Z2apBdtOyz8CV7dC6/U1XbltXBC+IuutUkXQISz01P+US2ouBuesSbV6zILZ6BuzQ==", "dev": true, "license": "MIT", + "dependencies": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + }, "engines": { - "node": ">= 0.4.0" + "node": ">= 0.9" } }, - "node_modules/utrie": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", - "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "node_modules/vite": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.2.tgz", + "integrity": "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "base64-arraybuffer": "^1.0.2" + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, - "license": "MIT" - }, - "node_modules/v8flags": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-4.0.1.tgz", - "integrity": "sha512-fcRLaS4H/hrZk9hYwbdRM35D0U8IYMfEClhXxCivOojl+yTRAZH3Zy2sSy6qVCiGbV9YAtPssP6jaChqC9vPCg==", + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "node": ">=18" } }, - "node_modules/validate-npm-package-name": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-7.0.2.tgz", - "integrity": "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A==", + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], "dev": true, - "license": "ISC", + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^20.17.0 || >=22.9.0" + "node": ">=18" } }, - "node_modules/value-or-function": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-4.0.0.tgz", - "integrity": "sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg==", + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">= 10.13.0" + "node": ">=18" } }, - "node_modules/varint": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", - "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT" - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">= 0.8" - } - }, - "node_modules/vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "node": ">=18" } }, - "node_modules/vfile-location": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", - "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-message": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", - "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" } }, - "node_modules/vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 0.10" + "node": ">=18" } }, - "node_modules/vinyl-contents": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/vinyl-contents/-/vinyl-contents-2.0.0.tgz", - "integrity": "sha512-cHq6NnGyi2pZ7xwdHSW1v4Jfnho4TEGtxZHw01cmnc8+i7jgR6bRnED/LbrKan/Q7CvVLbnvA5OepnhbpjBZ5Q==", + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "bl": "^5.0.0", - "vinyl": "^3.0.0" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=10.13.0" + "node": ">=18" } }, - "node_modules/vinyl-contents/node_modules/replace-ext": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", - "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">= 10" + "node": ">=18" } }, - "node_modules/vinyl-contents/node_modules/vinyl": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.1.tgz", - "integrity": "sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==", + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "clone": "^2.1.2", - "remove-trailing-separator": "^1.1.0", - "replace-ext": "^2.0.0", - "teex": "^1.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10.13.0" + "node": ">=18" } }, - "node_modules/vinyl-fs": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-4.0.2.tgz", - "integrity": "sha512-XRFwBLLTl8lRAOYiBqxY279wY46tVxLaRhSwo3GzKEuLz1giffsOquWWboD/haGf5lx+JyTigCFfe7DWHoARIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fs-mkdirp-stream": "^2.0.1", - "glob-stream": "^8.0.3", - "graceful-fs": "^4.2.11", - "iconv-lite": "^0.6.3", - "is-valid-glob": "^1.0.0", - "lead": "^4.0.0", - "normalize-path": "3.0.0", - "resolve-options": "^2.0.0", - "stream-composer": "^1.0.2", - "streamx": "^2.14.0", - "to-through": "^3.0.0", - "value-or-function": "^4.0.0", - "vinyl": "^3.0.1", - "vinyl-sourcemap": "^2.0.0" - }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10.13.0" + "node": ">=18" } }, - "node_modules/vinyl-fs/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/vinyl-fs/node_modules/replace-ext": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", - "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 10" + "node": ">=18" } }, - "node_modules/vinyl-fs/node_modules/vinyl": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.1.tgz", - "integrity": "sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==", + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], "dev": true, "license": "MIT", - "dependencies": { - "clone": "^2.1.2", - "remove-trailing-separator": "^1.1.0", - "replace-ext": "^2.0.0", - "teex": "^1.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=10.13.0" + "node": ">=18" } }, - "node_modules/vinyl-source-stream": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz", - "integrity": "sha512-X+1Jq+M6ufv/ky480hndPBsNb0ieqTQkvpakxMTxb7oUlyuNaJKL2HddYUrbTec0Lb0J53JlDiCetcgJ3b3Wmg==", + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", - "dependencies": { - "through2": "^2.0.3", - "vinyl": "^0.4.3" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/vinyl-source-stream/node_modules/clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha512-g62n3Kb9cszeZvmvBUqP/dsEJD/+80pDA8u8KqHnAPrVnQ2Je9rVV6opxkhuWCd1kCn2gOibzDKxCtBvD3q5kA==", + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "*" + "node": ">=18" } }, - "node_modules/vinyl-source-stream/node_modules/clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha512-dhUqc57gSMCo6TX85FLfe51eC/s+Im2MLkAgJwfaRRexR2tA4dd3eLEW4L6efzHc2iNorrRRXITifnDLlRrhaA==", + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/vinyl-source-stream/node_modules/vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha512-pmza4M5VA15HOImIQYWhoXGlGNafCm0QK5BpBUXkzzEwrRxKqBsbAhTfkT2zMcJhUX1G1Gkid0xaV8WjOl7DsA==", + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.9" + "node": ">=18" } }, - "node_modules/vinyl-sourcemap": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-2.0.0.tgz", - "integrity": "sha512-BAEvWxbBUXvlNoFQVFVHpybBbjW1r03WhohJzJDSfgrrK5xVYIDTan6xN14DlyImShgDRv2gl9qhM6irVMsV0Q==", + "node_modules/vite/node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "convert-source-map": "^2.0.0", - "graceful-fs": "^4.2.10", - "now-and-later": "^3.0.0", - "streamx": "^2.12.5", - "vinyl": "^3.0.0", - "vinyl-contents": "^2.0.0" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=10.13.0" + "node": ">=18" } }, - "node_modules/vinyl-sourcemap/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/vinyl-sourcemap/node_modules/replace-ext": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", - "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", + "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">= 10" + "node": ">=18" } }, - "node_modules/vinyl-sourcemap/node_modules/vinyl": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.1.tgz", - "integrity": "sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==", + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "clone": "^2.1.2", - "remove-trailing-separator": "^1.1.0", - "replace-ext": "^2.0.0", - "teex": "^1.0.1" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=10.13.0" + "node": ">=18" } }, - "node_modules/vinyl-sourcemaps-apply": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", - "integrity": "sha512-+oDh3KYZBoZC8hfocrbrxbLUeaYtQK7J5WU5Br9VqWqmCll3tFJqKp97GC9GmMsVIL0qnx2DgEDVxdo5EZ5sSw==", + "node_modules/vite/node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "source-map": "^0.5.1" + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" } }, - "node_modules/vinyl-sourcemaps-apply/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/vinyl-string": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/vinyl-string/-/vinyl-string-1.0.2.tgz", - "integrity": "sha512-mDkPUvCM7K9r0WYZKIWc/dfPH8wkJBbe/3wZUU9EJyw3g6VSACg6FLlcZ/QbP1lTSdtBsVjQoYG1a9K0cfoKeQ==", + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "vinyl": "^1.1.1" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "node_modules/vinyl-string/node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=0.8" + "node": ">=18" } }, - "node_modules/vinyl-string/node_modules/clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha512-dhUqc57gSMCo6TX85FLfe51eC/s+Im2MLkAgJwfaRRexR2tA4dd3eLEW4L6efzHc2iNorrRRXITifnDLlRrhaA==", + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/vinyl-string/node_modules/replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha512-AFBWBy9EVRTa/LhEcG8QDP3FvpwZqmvN2QFDuJswFeaVhWnZMp8q3E6Zd90SR04PlIwfGdyVjNyLPyen/ek5CQ==", + "node_modules/vite/node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, "engines": { - "node": ">= 0.4" + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" } }, - "node_modules/vinyl-string/node_modules/vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha512-Ci3wnR2uuSAWFMSglZuB8Z2apBdtOyz8CV7dC6/U1XbltXBC+IuutUkXQISz01P+US2ouBuesSbV6zILZ6BuzQ==", + "node_modules/vitefu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.1.tgz", + "integrity": "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==", "dev": true, "license": "MIT", - "dependencies": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" + "workspaces": [ + "tests/deps/*", + "tests/projects/*", + "tests/projects/workspace/packages/*" + ], + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, - "engines": { - "node": ">= 0.9" + "peerDependenciesMeta": { + "vite": { + "optional": true + } } }, - "node_modules/vite": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.0.tgz", - "integrity": "sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==", + "node_modules/vitest": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.17.tgz", + "integrity": "sha512-FQMeF0DJdWY0iOnbv466n/0BudNdKj1l5jYgl5JVTwjSsZSlqyXFt/9+1sEyhR6CLowbZpV7O1sCHrzBhucKKg==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.27.0", - "fdir": "^6.5.0", + "@vitest/expect": "4.0.17", + "@vitest/mocker": "4.0.17", + "@vitest/pretty-format": "4.0.17", + "@vitest/runner": "4.0.17", + "@vitest/snapshot": "4.0.17", + "@vitest/spy": "4.0.17", + "@vitest/utils": "4.0.17", + "es-module-lexer": "^1.7.0", + "expect-type": "^1.2.2", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" + "std-env": "^3.10.0", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.0.3", + "vite": "^6.0.0 || ^7.0.0", + "why-is-node-running": "^2.3.0" }, "bin": { - "vite": "bin/vite.js" + "vitest": "vitest.mjs" }, "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" }, "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" + "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "lightningcss": "^1.21.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.0.17", + "@vitest/browser-preview": "4.0.17", + "@vitest/browser-webdriverio": "4.0.17", + "@vitest/ui": "4.0.17", + "happy-dom": "*", + "jsdom": "*" }, "peerDependenciesMeta": { - "@types/node": { + "@edge-runtime/vm": { "optional": true }, - "jiti": { - "optional": true - }, - "less": { + "@opentelemetry/api": { "optional": true }, - "lightningcss": { - "optional": true - }, - "sass": { + "@types/node": { "optional": true }, - "sass-embedded": { + "@vitest/browser-playwright": { "optional": true }, - "stylus": { + "@vitest/browser-preview": { "optional": true }, - "sugarss": { + "@vitest/browser-webdriverio": { "optional": true }, - "terser": { + "@vitest/ui": { "optional": true }, - "tsx": { + "happy-dom": { "optional": true }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vitefu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.1.tgz", - "integrity": "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==", - "dev": true, - "license": "MIT", - "workspaces": [ - "tests/deps/*", - "tests/projects/*", - "tests/projects/workspace/packages/*" - ], - "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" - }, - "peerDependenciesMeta": { - "vite": { + "jsdom": { "optional": true } } }, - "node_modules/void-elements": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", - "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==", + "node_modules/vitest/node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/w3c-xmlserializer": { @@ -26344,9 +25904,9 @@ } }, "node_modules/watchpack": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.0.tgz", - "integrity": "sha512-e6vZvY6xboSwLz2GD36c16+O/2Z6fKvIf4pOXptw2rY9MVwE/TXc6RGqxD3I3x0a28lwBY7DE+76uTPSsBrrCA==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", + "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", "dev": true, "license": "MIT", "dependencies": { @@ -26470,6 +26030,23 @@ "node": ">=4" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/widest-line": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", @@ -26521,13 +26098,6 @@ "node": ">=0.10.0" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true, - "license": "MIT" - }, "node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -26543,48 +26113,6 @@ "node": ">=8" } }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/wrap-ansi/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -26679,16 +26207,6 @@ "node": ">=18" } }, - "node_modules/xmlbuilder": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-12.0.0.tgz", - "integrity": "sha512-lMo8DJ8u6JRWp0/Y4XLa/atVDr75H9litKlb2E5j3V3MesoL50EBgZDWoLT3F/LztVnG67GjPXLZpqcky/UMnQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0" - } - }, "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", diff --git a/package.json b/package.json index 71e3b8e52e4..da287923830 100644 --- a/package.json +++ b/package.json @@ -8,9 +8,10 @@ "start:performance": "ng serve --project igniteui-angular-performance", "build": "npm run build:lib && npm run build:elements && npm run build:schematics && npm run build:migrations && npm run build:i18n", "test": "ng test igniteui-angular", + "test:coverage": "ng test igniteui-angular --watch=false --no-progress", "lint": "ng lint", "e2e": "ng e2e", - "test:lib": "ng test igniteui-angular --watch=false --no-progress --code-coverage", + "test:lib": "ng test igniteui-angular --watch=false --no-progress", "test:lib:perf": "ng test igniteui-angular --watch=false --no-progress --karma-config=./projects/igniteui-angular/karma.test-perf.conf.js", "test:lib:grid": "ng test igniteui-angular --watch=false --no-progress --code-coverage --karma-config=./projects/igniteui-angular/karma.grid.conf.js", "test:lib:tgrid": "ng test igniteui-angular --watch=false --no-progress --code-coverage --karma-config=./projects/igniteui-angular/karma.tree-grid.conf.js", @@ -104,13 +105,13 @@ "@types/estree": "^1.0.0", "@types/express": "^5.0.0", "@types/hammerjs": "^2.0.46", - "@types/jasmine": "^5.1.7", - "@types/jasminewd2": "^2.0.10", "@types/node": "^20.17.6", "@types/sass-true": "^6.0.2", "@types/webpack-env": "^1.18.3", "@typescript-eslint/eslint-plugin": "^8.33.1", "@typescript-eslint/parser": "^8.33.1", + "@vitest/browser-playwright": "^4.0.17", + "@vitest/coverage-v8": "^4.0.17", "autoprefixer": "^10.4.16", "del": "^6.0.0", "eslint": "^9.28.0", @@ -129,15 +130,6 @@ "igniteui-i18n-resources": "^1.0.2", "igniteui-sassdoc-theme": "^2.1.0", "igniteui-webcomponents": "^6.5.0", - "jasmine": "^5.6.0", - "jasmine-core": "^5.6.0", - "karma": "^6.4.4", - "karma-chrome-launcher": "~3.2.0", - "karma-coverage": "^2.0.3", - "karma-jasmine": "~5.1.0", - "karma-junit-reporter": "^2.0.1", - "karma-parallel": "^0.3.1", - "karma-spec-reporter": "^0.0.36", "lit-html": "^3.2.1", "ng-packagr": "^21.0.0", "postcss": "^8.5.1", @@ -155,7 +147,8 @@ "ts-node": "^10.8.1", "typedoc": "^0.28.14", "typedoc-plugin-localization": "^3.1.0", - "typescript": "5.9.3" + "typescript": "5.9.3", + "vitest": "^4.0.17" }, "overrides": { "igniteui-sassdoc-theme": { diff --git a/projects/bundle-test/src/app/app.component.spec.ts b/projects/bundle-test/src/app/app.component.spec.ts index b460dd6df88..386516dd133 100644 --- a/projects/bundle-test/src/app/app.component.spec.ts +++ b/projects/bundle-test/src/app/app.component.spec.ts @@ -2,13 +2,13 @@ import { TestBed } from '@angular/core/testing'; import { AppComponent } from './app.component'; describe('AppComponent', () => { - beforeEach(() => TestBed.configureTestingModule({ - imports: [AppComponent] - })); + beforeEach(() => TestBed.configureTestingModule({ + imports: [AppComponent] + })); - it('should create the app', () => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.componentInstance; - expect(app).toBeTruthy(); - }); + it('should create the app', () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.componentInstance; + expect(app).toBeTruthy(); + }); }); diff --git a/projects/bundle-test/tsconfig.spec.json b/projects/bundle-test/tsconfig.spec.json index a9c0752ffe5..740196825da 100644 --- a/projects/bundle-test/tsconfig.spec.json +++ b/projects/bundle-test/tsconfig.spec.json @@ -4,7 +4,7 @@ "compilerOptions": { "outDir": "../../out-tsc/spec", "types": [ - "jasmine" + "vitest/globals" ] }, "include": [ diff --git a/projects/igniteui-angular-elements/jasmine.json b/projects/igniteui-angular-elements/jasmine.json deleted file mode 100644 index 3ea315cc591..00000000000 --- a/projects/igniteui-angular-elements/jasmine.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "spec_dir": "projects/igniteui-angular-elements/tests", - "spec_files": [ - "**/*.test.ts" - ], - "env": { - "random": false - } -} diff --git a/projects/igniteui-angular-elements/karma.conf.js b/projects/igniteui-angular-elements/karma.conf.js deleted file mode 100644 index 4220b46770d..00000000000 --- a/projects/igniteui-angular-elements/karma.conf.js +++ /dev/null @@ -1,43 +0,0 @@ -// Karma configuration file, see link for more information -// https://karma-runner.github.io/1.0/config/configuration-file.html - -module.exports = function (config) { - config.set({ - basePath: '', - frameworks: ['jasmine', '@angular-devkit/build-angular'], - plugins: [ - require('karma-jasmine'), - require('karma-chrome-launcher'), - require('karma-spec-reporter'), - require('karma-coverage') - ], - client: { - jasmine: { - // you can add configuration options for Jasmine here - // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html - // for example, you can disable the random execution with `random: false` - // or set a specific seed with `seed: 4321` - }, - clearContext: false // leave Jasmine Spec Runner output visible in browser - }, - jasmineHtmlReporter: { - suppressAll: true // removes the duplicated traces - }, - coverageReporter: { - dir: require('path').join(__dirname, '../../coverage/igniteui-angular-elements'), - subdir: '.', - reporters: [ - { type: 'html' }, - { type: 'text-summary' } - ] - }, - reporters: ['spec'], - port: 9876, - colors: true, - logLevel: config.LOG_INFO, - autoWatch: true, - browsers: ['ChromeHeadless'], - singleRun: false, - restartOnFileChange: true - }); -}; diff --git a/projects/igniteui-angular-elements/src/app/custom-strategy.spec.ts b/projects/igniteui-angular-elements/src/app/custom-strategy.spec.ts index 3521e662dab..21e9c40e670 100644 --- a/projects/igniteui-angular-elements/src/app/custom-strategy.spec.ts +++ b/projects/igniteui-angular-elements/src/app/custom-strategy.spec.ts @@ -4,34 +4,15 @@ import { firstValueFrom, fromEvent, skip, timer } from 'rxjs'; import { ComponentRefKey, IgcNgElement } from './custom-strategy'; import hgridData from '../assets/data/projects-hgrid.js'; import { SampleTestData } from 'igniteui-angular/test-utils/sample-test-data.spec'; -import { - IgcGridComponent, - IgcHierarchicalGridComponent, - IgcPivotGridComponent, - IgcColumnComponent, - IgcPaginatorComponent, - IgcGridStateComponent, - IgcColumnLayoutComponent, - IgcActionStripComponent, - IgcGridEditingActionsComponent, -} from './components'; +import { IgcGridComponent, IgcHierarchicalGridComponent, IgcPivotGridComponent, IgcColumnComponent, IgcPaginatorComponent, IgcGridStateComponent, IgcColumnLayoutComponent, IgcActionStripComponent, IgcGridEditingActionsComponent, } from './components'; import { defineComponents } from '../utils/register'; +import { describe, beforeAll, beforeEach, afterEach, it, expect } from 'vitest'; describe('Elements: ', () => { let testContainer: HTMLDivElement; - beforeAll(async () =>{ - defineComponents( - IgcGridComponent, - IgcHierarchicalGridComponent, - IgcPivotGridComponent, - IgcColumnComponent, - IgcColumnLayoutComponent, - IgcPaginatorComponent, - IgcGridStateComponent, - IgcActionStripComponent, - IgcGridEditingActionsComponent - ); + beforeAll(async () => { + defineComponents(IgcGridComponent, IgcHierarchicalGridComponent, IgcPivotGridComponent, IgcColumnComponent, IgcColumnLayoutComponent, IgcPaginatorComponent, IgcGridStateComponent, IgcActionStripComponent, IgcGridEditingActionsComponent); }); beforeEach(async () => { @@ -72,10 +53,10 @@ describe('Elements: ', () => { gridEl.primaryKey = 'id'; gridEl.data = [{ id: '1' }]; (gridEl as any).detailTemplate = (ctx) => { - return html`
+ return html `
`; - } + }; // TODO: Better way to wait - potentially expose the queue or observable for update on the strategy await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 2)); @@ -98,7 +79,7 @@ describe('Elements: ', () => { detailGrid = document.querySelector('#child1'); expect(detailGrid).toBeDefined(); detailGridComponent = (await detailGrid?.ngElementStrategy[ComponentRefKey])?.instance as IgxGridComponent; - expect(detailGridComponent).toBeDefined("Detail child grid was destroyed on re-expand"); + expect(detailGridComponent, "Detail child grid was destroyed on re-expand").toBeDefined(); }); }); @@ -163,7 +144,7 @@ describe('Elements: ', () => { gridEl.data = SampleTestData.foodProductData(); gridEl.addEventListener("columnInit", (args: CustomEvent) => { - args.detail.headerTemplate = (ctx) => html`Templated ${args.detail.field}`; + args.detail.headerTemplate = (ctx) => html `Templated ${args.detail.field}`; }); testContainer.appendChild(gridEl); @@ -235,7 +216,7 @@ describe('Elements: ', () => { expect(grid.getColumnByVisibleIndex(1).field).toEqual('ProductName'); }); - it('should not destroy action strip when row it is shown in is destroyed or cached.', async() => { + it('should not destroy action strip when row it is shown in is destroyed or cached.', async () => { const innerHtml = ` @@ -258,16 +239,16 @@ describe('Elements: ', () => { actionStrip.show(row); await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 3)); - expect(actionStrip.hidden).toBeFalse(); + expect(actionStrip.hidden).toBe(false); grid.data = []; await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 3)); - // row destroyed - expect((row.cdr as any).destroyed).toBeTrue(); + // row destroyed + expect((row.cdr as any).destroyed).toBe(true); // action strip still in DOM, only hidden. - expect(actionStrip.hidden).toBeTrue(); - expect(actionStrip.isConnected).toBeTrue(); + expect(actionStrip.hidden).toBe(true); + expect(actionStrip.isConnected).toBe(true); grid.data = SampleTestData.foodProductData(); grid.groupBy({ fieldName: 'InStock', dir: 1, ignoreCase: false }); @@ -279,7 +260,7 @@ describe('Elements: ', () => { actionStrip.show(row); await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 3)); - expect(actionStrip.hidden).toBeFalse(); + expect(actionStrip.hidden).toBe(false); // collapse all data rows, leave only groups grid.toggleAllGroupRows(); @@ -288,12 +269,12 @@ describe('Elements: ', () => { await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 3)); // row not destroyed, but also not in dom anymore - expect((row.cdr as any).destroyed).toBeFalse(); + expect((row.cdr as any).destroyed).toBe(false); expect(row.element.nativeElement.isConnected).toBe(false); - // action strip still in DOM, only hidden. - expect(actionStrip.hidden).toBeTrue(); - expect(actionStrip.isConnected).toBeTrue(); + // action strip still in DOM, only hidden. + expect(actionStrip.hidden).toBe(true); + expect(actionStrip.isConnected).toBe(true); }); }); }); diff --git a/projects/igniteui-angular-elements/tests/index.test.ts b/projects/igniteui-angular-elements/tests/index.test.ts deleted file mode 100644 index 9d0bef750fa..00000000000 --- a/projects/igniteui-angular-elements/tests/index.test.ts +++ /dev/null @@ -1,8 +0,0 @@ -import 'jasmine'; - -describe('It works', () => { - it('is correct', () => { - expect(1).toEqual(1); - }); - -}); diff --git a/projects/igniteui-angular-elements/tsconfig.spec.json b/projects/igniteui-angular-elements/tsconfig.spec.json index 70dea48b858..27377a9044c 100644 --- a/projects/igniteui-angular-elements/tsconfig.spec.json +++ b/projects/igniteui-angular-elements/tsconfig.spec.json @@ -5,7 +5,7 @@ "allowJs": true, "outDir": "../../out-tsc/spec", "types": [ - "jasmine" + "vitest/globals" ] }, "files": [ diff --git a/projects/igniteui-angular-performance/tsconfig.spec.json b/projects/igniteui-angular-performance/tsconfig.spec.json index 37243947a17..5190a974e37 100644 --- a/projects/igniteui-angular-performance/tsconfig.spec.json +++ b/projects/igniteui-angular-performance/tsconfig.spec.json @@ -5,7 +5,7 @@ "compilerOptions": { "outDir": "../../out-tsc/spec", "types": [ - "jasmine" + "vitest/globals", ], "composite": true }, diff --git a/projects/igniteui-angular/accordion/src/accordion/accordion.component.spec.ts b/projects/igniteui-angular/accordion/src/accordion/accordion.component.spec.ts index f75116923a9..ed1977b3e07 100644 --- a/projects/igniteui-angular/accordion/src/accordion/accordion.component.spec.ts +++ b/projects/igniteui-angular/accordion/src/accordion/accordion.component.spec.ts @@ -7,6 +7,7 @@ import { IgxExpansionPanelBodyComponent, IgxExpansionPanelComponent, IgxExpansio import { IAccordionCancelableEventArgs, IAccordionEventArgs, IgxAccordionComponent } from './accordion.component'; import { slideInLeft, slideOutRight } from 'igniteui-angular/animations'; import { UIInteractions } from 'igniteui-angular/test-utils/ui-interactions.spec'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const ACCORDION_CLASS = 'igx-accordion'; const PANEL_TAG = 'IGX-EXPANSION-PANEL'; @@ -15,16 +16,14 @@ const ACCORDION_TAG = 'IGX-ACCORDION'; describe('Rendering Tests', () => { let fix: ComponentFixture; let accordion: IgxAccordionComponent; - beforeEach( - waitForAsync(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule, - IgxAccordionSampleTestComponent - ] - }).compileComponents(); - }) - ); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [ + NoopAnimationsModule, + IgxAccordionSampleTestComponent + ] + }).compileComponents(); + })); beforeEach(() => { fix = TestBed.createComponent(IgxAccordionSampleTestComponent); fix.detectChanges(); @@ -69,8 +68,8 @@ describe('Rendering Tests', () => { it(`Should be able to expand only one panel when singleBranchExpanded is set to true and expandAll/collapseAll should not update the current expansion state `, fakeAsync(() => { - spyOn(accordion.panelExpanded, 'emit').and.callThrough(); - spyOn(accordion.panelCollapsed, 'emit').and.callThrough(); + vi.spyOn(accordion.panelExpanded, 'emit'); + vi.spyOn(accordion.panelCollapsed, 'emit'); accordion.singleBranchExpand = true; fix.detectChanges(); @@ -79,7 +78,7 @@ describe('Rendering Tests', () => { fix.detectChanges(); expect(accordion.panels.filter(panel => !panel.collapsed).length).toEqual(1); - expect(accordion.panels[3].collapsed).toBeFalse(); + expect(accordion.panels[3].collapsed).toBe(false); expect(accordion.panelExpanded.emit).toHaveBeenCalledTimes(0); accordion.panels[0].expand(); @@ -87,10 +86,10 @@ describe('Rendering Tests', () => { fix.detectChanges(); expect(accordion.panels.filter(panel => !panel.collapsed).length).toEqual(2); - expect(accordion.panels[0].collapsed).toBeFalse(); - expect(accordion.panels[1].collapsed).toBeTrue(); - expect(accordion.panels[2].collapsed).toBeTrue(); - expect(accordion.panels[3].collapsed).toBeFalse(); + expect(accordion.panels[0].collapsed).toBe(false); + expect(accordion.panels[1].collapsed).toBe(true); + expect(accordion.panels[2].collapsed).toBe(true); + expect(accordion.panels[3].collapsed).toBe(false); accordion.collapseAll(); tick(); @@ -104,10 +103,10 @@ describe('Rendering Tests', () => { fix.detectChanges(); expect(accordion.panels.filter(panel => !panel.collapsed).length).toEqual(1); - expect(accordion.panels[0].collapsed).toBeTrue(); - expect(accordion.panels[1].collapsed).toBeFalse(); - expect(accordion.panels[2].collapsed).toBeTrue(); - expect(accordion.panels[3].collapsed).toBeTrue(); + expect(accordion.panels[0].collapsed).toBe(true); + expect(accordion.panels[1].collapsed).toBe(false); + expect(accordion.panels[2].collapsed).toBe(true); + expect(accordion.panels[3].collapsed).toBe(true); })); @@ -120,26 +119,26 @@ describe('Rendering Tests', () => { fix.detectChanges(); expect(accordion.panels.filter(panel => !panel.collapsed).length).toEqual(3); - expect(accordion.panels[0].collapsed).toBeFalse(); - expect(accordion.panels[1].collapsed).toBeTrue(); - expect(accordion.panels[2].collapsed).toBeFalse(); - expect(accordion.panels[3].collapsed).toBeFalse(); + expect(accordion.panels[0].collapsed).toBe(false); + expect(accordion.panels[1].collapsed).toBe(true); + expect(accordion.panels[2].collapsed).toBe(false); + expect(accordion.panels[3].collapsed).toBe(false); accordion.panels[1].expand(); tick(); fix.detectChanges(); expect(accordion.panels.filter(panel => !panel.collapsed).length).toEqual(4); - expect(accordion.panels[0].collapsed).toBeFalse(); - expect(accordion.panels[1].collapsed).toBeFalse(); - expect(accordion.panels[2].collapsed).toBeFalse(); - expect(accordion.panels[3].collapsed).toBeFalse(); + expect(accordion.panels[0].collapsed).toBe(false); + expect(accordion.panels[1].collapsed).toBe(false); + expect(accordion.panels[2].collapsed).toBe(false); + expect(accordion.panels[3].collapsed).toBe(false); })); it(`Should update the current expansion state when expandAll/collapseAll is invoked and singleBranchExpaned is set to false`, fakeAsync(() => { - spyOn(accordion.panelExpanded, 'emit').and.callThrough(); - spyOn(accordion.panelCollapsed, 'emit').and.callThrough(); + vi.spyOn(accordion.panelExpanded, 'emit'); + vi.spyOn(accordion.panelCollapsed, 'emit'); accordion.singleBranchExpand = false; accordion.panels[3].collapse(); tick(); @@ -161,38 +160,38 @@ describe('Rendering Tests', () => { })); it(`Should collapse all expanded and not disabled panels except for the last one when setting singleBranchExpand to true`, () => { - expect(accordion.panels[0].collapsed).toBeTrue(); - expect(accordion.panels[1].collapsed).toBeTrue(); - expect(accordion.panels[2].collapsed).toBeFalse(); - expect(accordion.panels[3].collapsed).toBeFalse(); + expect(accordion.panels[0].collapsed).toBe(true); + expect(accordion.panels[1].collapsed).toBe(true); + expect(accordion.panels[2].collapsed).toBe(false); + expect(accordion.panels[3].collapsed).toBe(false); accordion.panels[1].collapsed = false; fix.detectChanges(); - expect(accordion.panels[0].collapsed).toBeTrue(); - expect(accordion.panels[1].collapsed).toBeFalse(); - expect(accordion.panels[2].collapsed).toBeFalse(); - expect(accordion.panels[3].collapsed).toBeFalse(); + expect(accordion.panels[0].collapsed).toBe(true); + expect(accordion.panels[1].collapsed).toBe(false); + expect(accordion.panels[2].collapsed).toBe(false); + expect(accordion.panels[3].collapsed).toBe(false); accordion.singleBranchExpand = true; fix.detectChanges(); - expect(accordion.panels[0].collapsed).toBeTrue(); - expect(accordion.panels[1].collapsed).toBeTrue(); - expect(accordion.panels[2].collapsed).toBeFalse(); - expect(accordion.panels[3].collapsed).toBeFalse(); + expect(accordion.panels[0].collapsed).toBe(true); + expect(accordion.panels[1].collapsed).toBe(true); + expect(accordion.panels[2].collapsed).toBe(false); + expect(accordion.panels[3].collapsed).toBe(false); }); it('Should emit ing and ed events when expand panel state is toggled', fakeAsync(() => { - spyOn(accordion.panelExpanded, 'emit').and.callThrough(); - spyOn(accordion.panelExpanding, 'emit').and.callThrough(); - spyOn(accordion.panelCollapsed, 'emit').and.callThrough(); - spyOn(accordion.panelCollapsing, 'emit').and.callThrough(); + vi.spyOn(accordion.panelExpanded, 'emit'); + vi.spyOn(accordion.panelExpanding, 'emit'); + vi.spyOn(accordion.panelCollapsed, 'emit'); + vi.spyOn(accordion.panelCollapsing, 'emit'); - spyOn(accordion.panels[0].contentCollapsing, 'emit').and.callThrough(); - spyOn(accordion.panels[0].contentCollapsed, 'emit').and.callThrough(); - spyOn(accordion.panels[0].contentExpanding, 'emit').and.callThrough(); - spyOn(accordion.panels[0].contentExpanded, 'emit').and.callThrough(); + vi.spyOn(accordion.panels[0].contentCollapsing, 'emit'); + vi.spyOn(accordion.panels[0].contentCollapsed, 'emit'); + vi.spyOn(accordion.panels[0].contentExpanding, 'emit'); + vi.spyOn(accordion.panels[0].contentExpanded, 'emit'); accordion.singleBranchExpand = false; fix.detectChanges(); @@ -286,8 +285,7 @@ describe('Rendering Tests', () => { fix.detectChanges(); // SHIFT + ALT + ArrowDown - UIInteractions.triggerKeyDownEvtUponElem('arrowdown', - accordion.panels[0].header.innerElement, true, true, true, false); + UIInteractions.triggerKeyDownEvtUponElem('arrowdown', accordion.panels[0].header.innerElement, true, true, true, false); tick(); fix.detectChanges(); @@ -295,8 +293,7 @@ describe('Rendering Tests', () => { expect(accordion.panels.filter(p => !p.collapsed).length).toEqual(3); // SHIFT + ALT + ArrowUp - UIInteractions.triggerKeyDownEvtUponElem('arrowup', - accordion.panels[0].header.innerElement, true, true, true, false); + UIInteractions.triggerKeyDownEvtUponElem('arrowup', accordion.panels[0].header.innerElement, true, true, true, false); tick(); fix.detectChanges(); @@ -313,16 +310,14 @@ describe('Rendering Tests', () => { fix.detectChanges(); // SHIFT + ALT + ArrowDown - UIInteractions.triggerKeyDownEvtUponElem('arrowdown', - accordion.panels[0].header.innerElement, true, true, true, false); + UIInteractions.triggerKeyDownEvtUponElem('arrowdown', accordion.panels[0].header.innerElement, true, true, true, false); tick(); fix.detectChanges(); expect(accordion.panels.filter(p => !p.collapsed).length).toEqual(2); // SHIFT + ALT + ArrowUp - UIInteractions.triggerKeyDownEvtUponElem('arrowup', - accordion.panels[0].header.innerElement, true, true, true, false); + UIInteractions.triggerKeyDownEvtUponElem('arrowup', accordion.panels[0].header.innerElement, true, true, true, false); tick(); fix.detectChanges(); @@ -406,6 +401,7 @@ describe('Rendering Tests', () => { imports: [IgxAccordionComponent, IgxExpansionPanelComponent, IgxExpansionPanelHeaderComponent, IgxExpansionPanelBodyComponent, IgxExpansionPanelTitleDirective] }) export class IgxAccordionSampleTestComponent { - @ViewChild(IgxAccordionComponent) public accordion: IgxAccordionComponent; + @ViewChild(IgxAccordionComponent) + public accordion: IgxAccordionComponent; public divChild = true; } diff --git a/projects/igniteui-angular/action-strip/src/action-strip/action-strip.component.spec.ts b/projects/igniteui-angular/action-strip/src/action-strip/action-strip.component.spec.ts index 5f17dcfc137..dd3d2036530 100644 --- a/projects/igniteui-angular/action-strip/src/action-strip/action-strip.component.spec.ts +++ b/projects/igniteui-angular/action-strip/src/action-strip/action-strip.component.spec.ts @@ -5,6 +5,7 @@ import { By } from '@angular/platform-browser'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxIconComponent } from 'igniteui-angular/icon'; import { wait } from '../../../test-utils/ui-interactions.spec'; +import { describe, it, test, expect, beforeEach, vi } from 'vitest'; const ACTION_STRIP_CONTAINER_CSS = 'igx-action-strip__actions'; const DROP_DOWN_LIST = 'igx-drop-down__list'; @@ -114,8 +115,10 @@ describe('igxActionStrip', () => { expect(dropDownItems.length).toBe(3); }); - it('should emit onMenuOpen/onMenuOpening when toggling the menu', () => { - pending('implementation'); + it.skip('should emit onMenuOpen/onMenuOpening when toggling the menu', () => { + // TODO: vitest-migration: The pending() function was converted to a skipped test (`it.skip`). See: https://vitest.dev/api/vi.html#it-skip + // pending('implementation'); + ; }); it('should allow combining content outside and inside the menu', () => { diff --git a/projects/igniteui-angular/avatar/src/avatar/avatar.component.spec.ts b/projects/igniteui-angular/avatar/src/avatar/avatar.component.spec.ts index 5f13ec83de7..8df720068ad 100644 --- a/projects/igniteui-angular/avatar/src/avatar/avatar.component.spec.ts +++ b/projects/igniteui-angular/avatar/src/avatar/avatar.component.spec.ts @@ -2,6 +2,7 @@ import { Component, ViewChild } from '@angular/core'; import { TestBed, waitForAsync } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { IgxAvatarComponent, IgxAvatarType, IgxAvatarSize } from './avatar.component'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Avatar', () => { const baseClass = 'igx-avatar'; @@ -196,7 +197,8 @@ describe('Avatar', () => { imports: [IgxAvatarComponent] }) class InitAvatarComponent { - @ViewChild(IgxAvatarComponent, { static: true }) public avatar: IgxAvatarComponent; + @ViewChild(IgxAvatarComponent, { static: true }) + public avatar: IgxAvatarComponent; } @Component({ @@ -205,7 +207,8 @@ class InitAvatarComponent { imports: [IgxAvatarComponent] }) class AvatarWithAttribsComponent { - @ViewChild(IgxAvatarComponent, { static: true }) public avatar: IgxAvatarComponent; + @ViewChild(IgxAvatarComponent, { static: true }) + public avatar: IgxAvatarComponent; public initials = 'ZK'; } @@ -215,7 +218,8 @@ class AvatarWithAttribsComponent { imports: [IgxAvatarComponent] }) class InitIconAvatarComponent { - @ViewChild(IgxAvatarComponent, { static: true }) public avatar: IgxAvatarComponent; + @ViewChild(IgxAvatarComponent, { static: true }) + public avatar: IgxAvatarComponent; } @Component({ @@ -223,7 +227,8 @@ class InitIconAvatarComponent { imports: [IgxAvatarComponent] }) class InitImageAvatarComponent { - @ViewChild(IgxAvatarComponent, { static: true }) public avatar: IgxAvatarComponent; + @ViewChild(IgxAvatarComponent, { static: true }) + public avatar: IgxAvatarComponent; public source = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxQTEhUUExQWFRUXFRcaFRgXFxcXFBcYFxQXFxcUFxcYHCggGBolHBQUITEhJSkrLi4uFx8zODMsNygtLiwBCgoKDg0OGhAQGi4kHyQsLCwsLCwsLSwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLP/AABEIAK4BIgMBIgACEQEDEQH/xAAbAAACAwEBAQAAAAAAAAAAAAACAwABBAcFBv/EADUQAAICAgADBQYFBAIDAAAAAAABAgMRIQQxQQYSUaPSE1NhcYHwM5GhseEWI8HxQ9EUInP/xAAaAQEBAQEBAQEAAAAAAAAAAAAAAQIDBAYF/8QAMBEBAAECAggEBgIDAAAAAAAAAAECEQNRBRITFCGhotEEFTFTFkGBsdLwQ2EGM1L/2gAMAwEAAhEDEQA/APp+Gj0Hxis8s66iKORppjyz9/UDNxkc70vvkLpo1k9HiK8pff2wa6l+XL4AL9k8LBdcceJqppx/I9UR/jIGateP/X+xtdOzXTw+dDLqsaQGZ0JFxoxyHxTfQdXHYGNQfUKNeDcoC5V8wAUC5LoFXF5I1sBeBiQfsw3EDJKP7GZ0tt6PSugDGIHnrhsfUaquhsjDJbrQGeFAFlKWcnoRgZ3Xlv5gZK68/IXZwia2up6NcNgSgB5tlWvzM74bK3k9WVWmLjD4AeNbw+G8pvwJGjevljw0ev7DYp1Yf3sDPVRjf7cgb6875ffM2NaWRUoged/42zNbQstPoz1FB5F8XVzesa+/2A8mzh8LWV/r9Aqac7+WH9P2NX34gVWY5Y+/tADPhVjo+XiJv4XC8Ovhs9GMtchPEy1j9gPn/Zvx/REPSwvH9ywHV5NtEdY3n6GfhYZfP/s9Hha88/ECpvGt/Uup/uPvgnjAuqADMJL7/wAmmpJ46/EXClfM1RSxhfwA+K8AnV4k4eIedgV7PHIBxNKexGMv6gCkSMeZojAjrASoBKGB0UCwEyQXdG91Bez0AnuC5o0SQkCokkhkYF93IEgtCc4GpYX0Ed3IF8yOAyDAcwF2CMDLoPmLekAFmurE2rwHTeQMcgFxgw3VlBx/wGloBDpaXiIugnp9eaPRxyEOHj/AHlXR1jHUVVwuNvS/we1GCzyFzq2B53VJL/AriasPL59Pv6np2VpI8/iIN/f6AeY/mQNw+C/NlgauHqWXs9GpIzx4br9/IfDQGxQLpq8eQNd6aNUGArGGMiNSRTq8AG1svu7LpRJgV7RoYq1zM0ZZl+xsrXQCgostoGpAW9gsPuk7rApLREF3cAyYFTkhGdhyr6klXyAvJbQUYlyjoBeNMGIcUVKIFd7oLUQ3F9CopgLsQiS6Gh/EUgFKoCcMI1uIiSyAiKZoS1skaw4VgBGJLIrpz6ju7sGaAVJCt9OnIbbB4yVBa8AF2VcjDxED1E29GTio4eFzYHkSofh+hRqnxiTenzIA1yyHE43X2243a9t193V6Bj7a8bj8br7ur0HLbQ4bxTlLsaNdS0cWh2y43X9/X/zq9Bu4bthxvvvLq9BNvSxPi6I+UuwRQ2uXQ5BZ2v433/l1egOntjxvvvLq9A29LO+4eU/v1dgSx9ALVrJymXbXjMNe28ur9P8A0F3dseNwsXeXV6Cbek37Dynl3db4avqaIy2cjr7Z8b3fxvLq9Av+s+Nx+N5dXoG3pTfsPKeXd2VMiici4ftlxuPxvLq9Af8AWHG++8ur0jeKU8ww8p5d3W69gTk84OVw7Y8Yv+by6vSBHtnxjk17b5f26vSN4pTzDDynl3dWjBsYoJHKF2x4z33l1+kj7Ycb77y6/SN4pPMcLKeXd1axCJo5c+2PG++8ur0iru2PG++6+7q9A3ilY0hh5Ty7utxKkjktfbHjffeXV6Rj7YcZ77y6vSN4pPMMPKeXd1PugSZy2XbDjcfjdPd1egzrtjxvvvLq9A3ikjx+HPynl3derRbjo5NDthxuPxvLq9AT7Y8b77y6vSN4pPMMPKeXd1GxAKODlj7Y8b77y6vSIn2z43P43l1egbeld+w8p5d3W0hLicsj2x43f97y6vQA+2HG5/G8ur0Db0rv2HlP79XW4QHYOP19suN995dXoHf1lxmPxvLq9I3ilN+w8p5d3UrGLjE5RZ2y43P43l1egz/1nxy53eXV6C7elqPGUZT+/V1+4VCRyeXbfjPfeXV6DMu2vGvld5dXoG3pWPF0ZT+/V2C2zWvv72Y7Jdfmcon2245f83l1egzS7Z8c+d3l1egbalqPE0ZS6o6WQ5M+2vG+/wDLq9BZdtC7xTlLwYpbHRWRTX7DaY7PM8MnezNVK/JY/MFfm+nzNVVWDLhVVwLnIingK5Y/wSineWRnhY+mDby/oNui9fMKnxYeMvZHKZ4resCHEcl0IodchImy6Fp/UuUvAXF5Wiu/sJYUZ7BfNBKG8jMIF12MOEzPKYyuQSY4DmhMx9ktGfG8ApMhDAdkNA1v7+Ac2En1JkxUYhTkApZDcQYglyA2iNMCTaBnDIMmUregWwormBNY2MhLmBYsBYKqY2MzOuY5V8gspL/Bhtls9P2ejLdDYhaZY2go1t8vqM9n8xsI65FbmpinWYz0LeqPPskjUOtDO5linL4ohp2s114+uTTFGRS2a6UZlyqaOFqfPqbq44BqgMZl5qpvJd3ND0taESSbQzK5ESWiqr4hN+ArhW09jJy8A5z6pnwFTmPr2JvWwR6i4Nc/vmBdF5G0RwiWAvxHQs6L4iKArnhh8U9Bn5s8UUrCq2NSDciTAfiPwLa2GYkuL+I+vlvmKhHfzH8kCpnsiJjHH5j7DOg3BtUs5CxkVBjYMJJEwJL8h9iwIk/9BqB1vmgbZaFwlhjpRC+kslcmmPVouUNjfZcslamw3Y8ASfUOcFgyS546ESIHFvI1S1kTkkp6wVbM/GWb0YO6bO7kX3OeSu1M2hk9n8CDnJeBDTpeWap4xo21Jv4GaETXRokpXL0qlpDqrDFGQ6u3xwZeWaU4iW8kjMXbLQFb+IatwbYPkPseGZqp5HLeEiOUxxF3y5S0XKvYqTwEgMbHyHN7E98tTTCzB8UFY8lVx0SL3gME2R+/v6F1sbZHIuCwGr8DW9ASlsFvoDNhIg+sOYuOQZ29AluIbAYxz9STJVPIa+SlH+A60DWv4GwjpgmSL5dBVstYKtt2JTyw6RCI0SsEOPMuMtYYWTKZbHuejFVIZHl9/mVJhdthl9rsOd2/oZpL9w3TSc55+hS3zLjHKJLGApdj54ESbwNkt/BguOStwyYZZGmWadB11/H9B1cPiJbHQkeOcSvN9vGh/BT60c6u7RFl6YuIRz2tebfkfgPb6qu60yRr8Acj0Jxq4+bUaC8BP8fVV3SttGim1pCE9h97BicfEzXyDR8+uH1Vd2n2vUCc8gRkU2Tb4ma/D2jvb6qvySEw4y+AokJDbYmafD+jvb6qvyaoXEV2HyEqReSbfEzX4e0b7XVV+TQ789BU5lJi5sRj4mf2X4d0bH8XVV+Se02X3xUBiLOPXmkf4/o72+qru0q3C5Coz5skmKkyRj4mf2Wf8e0bH8XVV+QpWgqxpARCuRrb15s/D+j7f6+qrudGeg5W/AVHkWuRnb4mf2a+HdHe11VfkR4/MpayFPxKfI1t6808g0f7fVV3DnwKUvELAt6Ltq80nQPgPb6qu461hhWPohff0DKehtcTNJ0Fo/2+qruTNbKrTI+ZcUdNrXmx5J4H2+dXcyM2DLZUi1Im1rzXyPwHt86u5Tj8QIa6jLEB3DUYtWbM6F8F7fOruTKD8f0KG5RDW1qZ8n8H/wAc6u5Q6Bm74yqZmqH6FNUXa0y3ICMi4o5Wei62aIMzjq3ozU1T6jbCi8gBIw6Qtg94JoXJiCR94iyVFh4CoEgMssimxYFjy9cyrJYRdKwsvmyf2t78FxgW2ScxcpdPEE8DO9kt8i+7oFkUEdMpvLI46KizTI3IYuQlstSJZbrbFOWAmxNkjUQxVJzYi2QXe8BbNRDNUrKSKGRax8SyzHFXdBehjA5iFkMpEyXMCxFhmVTYEpAymAzpEOVVQXMgpkOlnDWkOBsGJTGxLLNJ7ngOqWTOpDVM5zDvTVxOYUJaFNhpmJh1iTnIODM7mHCRiYbiri0d4TORIMqSJENTN4FCwZCwzA94urdnXs1xmW7DNB5LfgTVa1+Bzl3sDnYZ4vCBdhLXWKrGzmVB7FyKSLbgl+LXCZYiuQffMTDpEiyJTDUhedliGZkeSgO8WmWyXRgSDmxUmahmoUWFjItbCcxMJEhRGyrJld41Zm562gO8VGzWALrDMRxamqLXXkCbKjYD7Y3aXOaosXIXNjZS6iLpnWlwrmxbkQU7PiQ66rza6h9b0Z0x0BUUepr5FxnoGbEqzZmIu6TVaW+DLczJG3P5jFPRzml1jEua7Ao2GRyYUJbLNJGJxehGRUmKU+RcrGctV31uA++C5GedocJGtWzGvfgdCQcZ7yZe+/1GqZJpaprPlPIrvYAUy5sllmq5qsyFCZkUmWrOY1EjEbLJC3YIVhVmxFKziZNVdyF22b+ZmjJh9/KLqWlNpeLHxmTviURMmqa0nuzJWRLkU5l1TXaFIpyExb6lSmNU1zLXnDAQtTySTNavyY1r8TZT2KmLcyKeixTZia7md4WwJyKNxDE1JOYu2RU5AW9DcQ41VAILafiQ62efW/p//9k='; } diff --git a/projects/igniteui-angular/badge/src/badge/badge.component.spec.ts b/projects/igniteui-angular/badge/src/badge/badge.component.spec.ts index 6d398d5e871..f0daf27a01d 100644 --- a/projects/igniteui-angular/badge/src/badge/badge.component.spec.ts +++ b/projects/igniteui-angular/badge/src/badge/badge.component.spec.ts @@ -2,6 +2,7 @@ import { Component, ViewChild } from '@angular/core'; import { TestBed, waitForAsync } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { IgxBadgeComponent, IgxBadgeType } from './badge.component'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Badge', () => { beforeEach(waitForAsync(() => { @@ -115,7 +116,8 @@ describe('Badge', () => { imports: [IgxBadgeComponent] }) class InitBadgeComponent { - @ViewChild(IgxBadgeComponent, { static: true }) public badge: IgxBadgeComponent; + @ViewChild(IgxBadgeComponent, { static: true }) + public badge: IgxBadgeComponent; } @Component({ @@ -123,7 +125,8 @@ class InitBadgeComponent { imports: [IgxBadgeComponent] }) class InitBadgeWithDefaultsComponent { - @ViewChild(IgxBadgeComponent, { static: true }) public badge: IgxBadgeComponent; + @ViewChild(IgxBadgeComponent, { static: true }) + public badge: IgxBadgeComponent; } @Component({ @@ -131,7 +134,8 @@ class InitBadgeWithDefaultsComponent { imports: [IgxBadgeComponent] }) class InitBadgeWithIconComponent { - @ViewChild(IgxBadgeComponent, { static: true }) public badge: IgxBadgeComponent; + @ViewChild(IgxBadgeComponent, { static: true }) + public badge: IgxBadgeComponent; } @Component({ @@ -139,7 +143,8 @@ class InitBadgeWithIconComponent { imports: [IgxBadgeComponent] }) class InitBadgeWithIconARIAComponent { - @ViewChild(IgxBadgeComponent, { static: true }) public badge: IgxBadgeComponent; + @ViewChild(IgxBadgeComponent, { static: true }) + public badge: IgxBadgeComponent; } @Component({ @@ -147,5 +152,6 @@ class InitBadgeWithIconARIAComponent { imports: [IgxBadgeComponent] }) class InitBadgeWithDotComponent { - @ViewChild(IgxBadgeComponent, { static: true }) public badge: IgxBadgeComponent; + @ViewChild(IgxBadgeComponent, { static: true }) + public badge: IgxBadgeComponent; } diff --git a/projects/igniteui-angular/banner/src/banner/banner.component.spec.ts b/projects/igniteui-angular/banner/src/banner/banner.component.spec.ts index 0dad3dffeab..db02abbc088 100644 --- a/projects/igniteui-angular/banner/src/banner/banner.component.spec.ts +++ b/projects/igniteui-angular/banner/src/banner/banner.component.spec.ts @@ -7,6 +7,7 @@ import { IgxIconComponent } from 'igniteui-angular/icon'; import { IgxBannerActionsDirective } from './banner.directives'; import { IgxCardComponent, IgxCardContentDirective, IgxCardHeaderComponent } from 'igniteui-angular/card'; import { IgxAvatarComponent } from 'igniteui-angular/avatar'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const CSS_CLASS_EXPANSION_PANEL = 'igx-expansion-panel'; const CSS_CLASS_EXPANSION_PANEL_BODY = 'igx-expansion-panel__body'; @@ -231,12 +232,12 @@ describe('igxBanner', () => { const banner = fixture.componentInstance.banner; expect(banner.collapsed).toBeTruthy(); - spyOn(banner.opened, 'emit'); - spyOn(banner.closed, 'emit'); - spyOn(banner, 'onExpansionPanelClose').and.callThrough(); - spyOn(banner, 'onExpansionPanelOpen').and.callThrough(); - spyOn(banner, 'open').and.callThrough(); - spyOn(banner, 'close').and.callThrough(); + vi.spyOn(banner.opened, 'emit'); + vi.spyOn(banner.closed, 'emit'); + vi.spyOn(banner, 'onExpansionPanelClose'); + vi.spyOn(banner, 'onExpansionPanelOpen'); + vi.spyOn(banner, 'open'); + vi.spyOn(banner, 'close'); banner.open(); tick(); @@ -337,10 +338,10 @@ describe('igxBanner', () => { const fixture = TestBed.createComponent(IgxBannerSampleComponent); fixture.detectChanges(); const banner = fixture.componentInstance.banner; - spyOn(banner.closed, 'emit'); - spyOn(banner.closing, 'emit'); - spyOn(banner.opened, 'emit'); - spyOn(banner.opening, 'emit'); + vi.spyOn(banner.closed, 'emit'); + vi.spyOn(banner.closing, 'emit'); + vi.spyOn(banner.opened, 'emit'); + vi.spyOn(banner.opening, 'emit'); expect(banner.collapsed).toEqual(true); expect(banner.opening.emit).toHaveBeenCalledTimes(0); expect(banner.opened.emit).toHaveBeenCalledTimes(0); @@ -364,10 +365,10 @@ describe('igxBanner', () => { const fixture = TestBed.createComponent(SimpleBannerEventsComponent); fixture.detectChanges(); const banner = fixture.componentInstance.banner; - spyOn(banner.closing, 'emit').and.callThrough(); - spyOn(banner.opening, 'emit').and.callThrough(); - spyOn(banner.closed, 'emit').and.callThrough(); - spyOn(banner.opened, 'emit').and.callThrough(); + vi.spyOn(banner.closing, 'emit'); + vi.spyOn(banner.opening, 'emit'); + vi.spyOn(banner.closed, 'emit'); + vi.spyOn(banner.opened, 'emit'); expect(banner.collapsed).toEqual(true); fixture.componentInstance.cancelFlag = true; banner.toggle(); @@ -404,24 +405,24 @@ describe('igxBanner', () => { tick(); fixture.detectChanges(); - expect(banner.expanded).toBeFalse(); + expect(banner.expanded).toBe(false); banner.expanded = true; tick(); fixture.detectChanges(); - expect(banner.expanded).toBeTrue(); + expect(banner.expanded).toBe(true); expect(banner.elementRef.nativeElement.style.display).toEqual('block'); banner.expanded = false; tick(); fixture.detectChanges(); - expect(banner.expanded).toBeFalse(); + expect(banner.expanded).toBe(false); expect(banner.elementRef.nativeElement.style.display).toEqual(''); banner.expanded = true; tick(); fixture.detectChanges(); - expect(banner.expanded).toBeTrue(); + expect(banner.expanded).toBe(true); expect(banner.elementRef.nativeElement.style.display).toEqual('block'); })); }); @@ -519,7 +520,7 @@ describe('igxBanner', () => { fixture.detectChanges(); const banner = fixture.componentInstance.banner; - expect(banner.expanded).toBeTrue(); + expect(banner.expanded).toBe(true); expect(banner.elementRef.nativeElement.style.display).toEqual('block'); expect(banner.elementRef.nativeElement.querySelector('.' + CSS_CLASS_BANNER)).not.toBeNull(); })); @@ -543,7 +544,7 @@ describe('igxBanner', () => { imports: [IgxBannerComponent] }) export class IgxBannerEmptyComponent { - @ViewChild(IgxBannerComponent, { read: IgxBannerComponent, static: true }) + @ViewChild(IgxBannerComponent, { read: IgxBannerComponent, static: true }) public banner: IgxBannerComponent; } @@ -562,7 +563,7 @@ export class IgxBannerEmptyComponent { imports: [IgxBannerComponent, IgxBannerActionsDirective] }) export class IgxBannerOneButtonComponent { - @ViewChild(IgxBannerComponent, { read: IgxBannerComponent, static: true }) + @ViewChild(IgxBannerComponent, { read: IgxBannerComponent, static: true }) public banner: IgxBannerComponent; } @@ -583,7 +584,7 @@ export class IgxBannerOneButtonComponent { imports: [IgxBannerComponent, IgxBannerActionsDirective, IgxIconComponent] }) export class IgxBannerSampleComponent { - @ViewChild(IgxBannerComponent, { read: IgxBannerComponent, static: true }) + @ViewChild(IgxBannerComponent, { read: IgxBannerComponent, static: true }) public banner: IgxBannerComponent; } @@ -613,7 +614,7 @@ export class IgxBannerSampleComponent { imports: [IgxBannerComponent, IgxCardComponent, IgxCardHeaderComponent, IgxCardContentDirective, IgxBannerActionsDirective, IgxAvatarComponent] }) export class IgxBannerCustomTemplateComponent { - @ViewChild(IgxBannerComponent, { read: IgxBannerComponent, static: true }) + @ViewChild(IgxBannerComponent, { read: IgxBannerComponent, static: true }) public banner: IgxBannerComponent; } @@ -626,7 +627,7 @@ export class IgxBannerCustomTemplateComponent { imports: [IgxBannerComponent] }) export class SimpleBannerEventsComponent { - @ViewChild(IgxBannerComponent, { read: IgxBannerComponent, static: true }) + @ViewChild(IgxBannerComponent, { read: IgxBannerComponent, static: true }) public banner: IgxBannerComponent; public cancelFlag = false; diff --git a/projects/igniteui-angular/bottom-nav/src/bottom-nav/bottom-nav.component.spec.ts b/projects/igniteui-angular/bottom-nav/src/bottom-nav/bottom-nav.component.spec.ts index d60446d833b..d2d9e1a68f3 100644 --- a/projects/igniteui-angular/bottom-nav/src/bottom-nav/bottom-nav.component.spec.ts +++ b/projects/igniteui-angular/bottom-nav/src/bottom-nav/bottom-nav.component.spec.ts @@ -3,12 +3,7 @@ import { TestBed, fakeAsync, tick, waitForAsync } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { Router } from '@angular/router'; import { Location } from '@angular/common'; -import { BottomTabBarTestComponent, - TabBarRoutingTestComponent, - TabBarTabsOnlyModeTestComponent, - TabBarTestComponent, - BottomNavRoutingGuardTestComponent, - BottomNavTestHtmlAttributesComponent } from '../../../test-utils/bottom-nav-components.spec'; +import { BottomTabBarTestComponent, TabBarRoutingTestComponent, TabBarTabsOnlyModeTestComponent, TabBarTestComponent, BottomNavRoutingGuardTestComponent, BottomNavTestHtmlAttributesComponent } from '../../../test-utils/bottom-nav-components.spec'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxBottomNavContentComponent } from './bottom-nav-content.component'; import { UIInteractions } from '../../../test-utils/ui-interactions.spec'; @@ -16,6 +11,7 @@ import { RoutingTestGuard } from '../../../test-utils/routing-test-guard.spec'; import { RoutingView1Component, RoutingView2Component, RoutingView3Component, RoutingView4Component, RoutingView5Component } from '../../../test-utils/routing-view-components.spec'; import { IgxBottomNavItemComponent } from './bottom-nav-item.component'; import { IgxBottomNavComponent } from './bottom-nav.component'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxBottomNav', () => { @@ -324,9 +320,9 @@ describe('IgxBottomNav', () => { bottomNav = fixture.componentInstance.bottomNav; tabItems = bottomNav.items.toArray(); headers = tabItems.map(item => item.headerComponent.nativeElement); - itemChangeSpy = spyOn(bottomNav.selectedItemChange, 'emit').and.callThrough(); - indexChangeSpy = spyOn(bottomNav.selectedIndexChange, 'emit').and.callThrough(); - indexChangingSpy = spyOn(bottomNav.selectedIndexChanging, 'emit').and.callThrough(); + itemChangeSpy = vi.spyOn(bottomNav.selectedItemChange, 'emit'); + indexChangeSpy = vi.spyOn(bottomNav.selectedIndexChange, 'emit'); + indexChangingSpy = vi.spyOn(bottomNav.selectedIndexChanging, 'emit'); })); it('Validate the fired events on clicking tab headers.', fakeAsync(() => { @@ -384,9 +380,9 @@ describe('IgxBottomNav', () => { bottomNav = fixture.componentInstance.bottomNav; tabItems = bottomNav.items.toArray(); headers = tabItems.map(item => item.headerComponent.nativeElement); - itemChangeSpy = spyOn(bottomNav.selectedItemChange, 'emit'); - indexChangeSpy = spyOn(bottomNav.selectedIndexChange, 'emit'); - indexChangingSpy = spyOn(bottomNav.selectedIndexChanging, 'emit'); + itemChangeSpy = vi.spyOn(bottomNav.selectedItemChange, 'emit'); + indexChangeSpy = vi.spyOn(bottomNav.selectedIndexChange, 'emit'); + indexChangingSpy = vi.spyOn(bottomNav.selectedIndexChanging, 'emit'); })); it('Validate the events are not fired on clicking tab headers before pressing enter/space key.', fakeAsync(() => { diff --git a/projects/igniteui-angular/button-group/src/button-group/button-group.component.spec.ts b/projects/igniteui-angular/button-group/src/button-group/button-group.component.spec.ts index dd51eec749e..a351f23a581 100644 --- a/projects/igniteui-angular/button-group/src/button-group/button-group.component.spec.ts +++ b/projects/igniteui-angular/button-group/src/button-group/button-group.component.spec.ts @@ -6,6 +6,7 @@ import { IgxButtonDirective } from '../../../directives/src/directives/button/bu import { IgxRadioComponent } from '../../../radio/src/radio/radio.component'; import { UIInteractions, wait } from 'igniteui-angular/test-utils/ui-interactions.spec'; import { IgxRadioGroupDirective } from 'igniteui-angular/radio'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; interface IButton { type?: string; @@ -59,7 +60,7 @@ describe('IgxButtonGroup', () => { }).compileComponents(); })); - it('should initialize buttonGroup with default values', () => { + it('should initialize buttonGroup with default values', () => { const fixture = TestBed.createComponent(InitButtonGroupComponent); fixture.detectChanges(); @@ -77,7 +78,7 @@ describe('IgxButtonGroup', () => { expect(buttongroup.selectedButtons.length).toEqual(1); }); - it('should initialize buttonGroup with passed values', () => { + it('should initialize buttonGroup with passed values', () => { const fixture = TestBed.createComponent(InitButtonGroupWithValuesComponent); fixture.detectChanges(); @@ -99,7 +100,7 @@ describe('IgxButtonGroup', () => { fixture.detectChanges(); const btnGroupInstance = fixture.componentInstance.buttonGroup; - spyOn(btnGroupInstance.selected, 'emit'); + vi.spyOn(btnGroupInstance.selected, 'emit'); btnGroupInstance.ngAfterViewInit(); fixture.detectChanges(); @@ -128,7 +129,7 @@ describe('IgxButtonGroup', () => { const btnGroupInstance = fixture.componentInstance.buttonGroup; btnGroupInstance.buttons[0].select(); btnGroupInstance.buttons[1].select(); - spyOn(btnGroupInstance.deselected, 'emit'); + vi.spyOn(btnGroupInstance.deselected, 'emit'); btnGroupInstance.ngAfterViewInit(); fixture.detectChanges(); @@ -177,7 +178,7 @@ describe('IgxButtonGroup', () => { expect(buttonGroup.selectedButtons.length).toBe(0); }); - it('Button Group single selection', async () => { + it('Button Group single selection', async () => { const fixture = TestBed.createComponent(InitButtonGroupComponent); await wait(); @@ -204,7 +205,7 @@ describe('IgxButtonGroup', () => { const buttongroup = fixture.componentInstance.buttonGroup; buttongroup.selectionMode = 'singleRequired'; await wait(); - spyOn(buttongroup.deselected, 'emit'); + vi.spyOn(buttongroup.deselected, 'emit'); buttongroup.selectButton(0); await wait(); @@ -220,7 +221,7 @@ describe('IgxButtonGroup', () => { expect(buttongroup.deselected.emit).not.toHaveBeenCalled(); }); - it('Button Group multiple selection', async () => { + it('Button Group multiple selection', async () => { const fixture = TestBed.createComponent(InitButtonGroupWithValuesComponent); await wait(); fixture.detectChanges(); @@ -431,14 +432,14 @@ describe('IgxButtonGroup', () => { expect(buttonGroup.buttons[0].nativeElement.classList.contains('igx-button-group__item--selected')).toBe(false); }); - it('should emit selected event only once per selection', async() => { + it('should emit selected event only once per selection', async () => { const fixture = TestBed.createComponent(InitButtonGroupComponent); fixture.detectChanges(); await wait(); const buttonGroup = fixture.componentInstance.buttonGroup; - spyOn(buttonGroup.selected, 'emit').and.callThrough(); + vi.spyOn(buttonGroup.selected, 'emit'); buttonGroup.selectButton(0); await wait(); @@ -464,11 +465,12 @@ describe('IgxButtonGroup', () => { imports: [IgxButtonGroupComponent] }) class InitButtonGroupComponent implements OnInit { - @ViewChild(IgxButtonGroupComponent, { static: true }) public buttonGroup: IgxButtonGroupComponent; + @ViewChild(IgxButtonGroupComponent, { static: true }) + public buttonGroup: IgxButtonGroupComponent; public buttons: Button[]; - constructor() {} + constructor() { } public ngOnInit(): void { this.buttons = [ @@ -498,13 +500,14 @@ class InitButtonGroupComponent implements OnInit { imports: [IgxButtonGroupComponent] }) class InitButtonGroupWithValuesComponent implements OnInit { - @ViewChild(IgxButtonGroupComponent, { static: true }) public buttonGroup: IgxButtonGroupComponent; + @ViewChild(IgxButtonGroupComponent, { static: true }) + public buttonGroup: IgxButtonGroupComponent; public cities: Button[]; public alignment = ButtonGroupAlignment.vertical; - constructor() {} + constructor() { } public ngOnInit(): void { @@ -547,7 +550,8 @@ class InitButtonGroupWithValuesComponent implements OnInit { imports: [IgxButtonGroupComponent, IgxButtonDirective] }) class TemplatedButtonGroupComponent { - @ViewChild(IgxButtonGroupComponent, { static: true }) public buttonGroup: IgxButtonGroupComponent; + @ViewChild(IgxButtonGroupComponent, { static: true }) + public buttonGroup: IgxButtonGroupComponent; public alignment = ButtonGroupAlignment.vertical; } @@ -562,7 +566,8 @@ class TemplatedButtonGroupComponent { imports: [IgxButtonGroupComponent, IgxButtonDirective] }) class TemplatedButtonGroupDesplayDensityComponent { - @ViewChild(IgxButtonGroupComponent, { static: true }) public buttonGroup: IgxButtonGroupComponent; + @ViewChild(IgxButtonGroupComponent, { static: true }) + public buttonGroup: IgxButtonGroupComponent; } @Component({ @@ -576,7 +581,8 @@ class TemplatedButtonGroupDesplayDensityComponent { imports: [IgxButtonGroupComponent, IgxButtonDirective] }) class ButtonGroupWithSelectedButtonComponent { - @ViewChild(IgxButtonGroupComponent, { static: true }) public buttonGroup: IgxButtonGroupComponent; + @ViewChild(IgxButtonGroupComponent, { static: true }) + public buttonGroup: IgxButtonGroupComponent; } @Component({ @@ -590,7 +596,8 @@ class ButtonGroupWithSelectedButtonComponent { imports: [IgxButtonGroupComponent, IgxButtonDirective] }) class ButtonGroupButtonWithBoundSelectedOutputComponent { - @ViewChild(IgxButtonGroupComponent, { static: true }) public buttonGroup: IgxButtonGroupComponent; + @ViewChild(IgxButtonGroupComponent, { static: true }) + public buttonGroup: IgxButtonGroupComponent; public items = [ { key: 0, value: 'Button 1' }, @@ -627,12 +634,16 @@ class ButtonGroupButtonWithBoundSelectedOutputComponent { imports: [IgxButtonGroupComponent, IgxButtonDirective, IgxRadioGroupDirective, IgxRadioComponent] }) class ButtonGroupSelectionBoundToAnotherComponent { - @ViewChild('radioGroup', { read: IgxRadioGroupDirective, static: true }) public radioGroup: IgxRadioGroupDirective; - @ViewChild('buttonGroup', { static: true }) public buttonGroup: IgxButtonGroupComponent; + @ViewChild('radioGroup', { read: IgxRadioGroupDirective, static: true }) + public radioGroup: IgxRadioGroupDirective; + @ViewChild('buttonGroup', { static: true }) + public buttonGroup: IgxButtonGroupComponent; public selectedValue = 'Bar'; - public onRadioChange(event: { value: string; }) { + public onRadioChange(event: { + value: string; + }) { this.selectedValue = event.value; } diff --git a/projects/igniteui-angular/calendar/src/calendar/calendar-multi-view.component.spec.ts b/projects/igniteui-angular/calendar/src/calendar/calendar-multi-view.component.spec.ts index c62c2dd72a3..889c7f2fc80 100644 --- a/projects/igniteui-angular/calendar/src/calendar/calendar-multi-view.component.spec.ts +++ b/projects/igniteui-angular/calendar/src/calendar/calendar-multi-view.component.spec.ts @@ -9,9 +9,10 @@ import { ymd } from '../../../test-utils/helper-utils.spec'; import { UIInteractions, wait } from '../../../test-utils/ui-interactions.spec'; import { IgxCalendarComponent } from './calendar.component'; import { IgxDatePickerComponent } from 'igniteui-angular/date-picker'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; describe('Multi-View Calendar - ', () => { - let fixture: ComponentFixture + let fixture: ComponentFixture; let calendar: any; beforeEach(waitForAsync(() => { @@ -146,7 +147,7 @@ describe('Multi-View Calendar - ', () => { }); it('selected event should be fired when selecting a date', () => { - spyOn(calendar.selected, 'emit'); + vi.spyOn(calendar.selected, 'emit'); const viewDate = ymd('2019-09-06'); calendar.viewDate = viewDate; fixture.detectChanges(); @@ -198,7 +199,8 @@ describe('Multi-View Calendar - ', () => { { type: DateRangeType.Between, dateRange: [new Date(2019, 11, 15), new Date(2020, 0, 11)] }, { type: DateRangeType.Between, dateRange: [new Date(2020, 0, 19), new Date(2020, 0, 25)] }, { type: DateRangeType.Between, dateRange: [new Date(2020, 1, 1), new Date(2020, 1, 15)] }, - { type: DateRangeType.Between, dateRange: [new Date(2020, 1, 25), new Date(2020, 2, 11)] }]; + { type: DateRangeType.Between, dateRange: [new Date(2020, 1, 25), new Date(2020, 2, 11)] } + ]; beforeEach(fakeAsync(() => { fixture = TestBed.createComponent(MultiViewCalendarSampleComponent); @@ -598,7 +600,7 @@ describe('Multi-View Calendar - ', () => { HelperTestFunctions.verifyCalendarSubHeaders(fixture, [dates[i], dates[i + 1]]); } - for (let index = dates.length - 2; index > 0; index--) { + for (let index = dates.length - 2; index > 0; index--) { const arrowLeft = HelperTestFunctions.getPreviousArrowElement(fixture); UIInteractions.triggerKeyDownEvtUponElem('Enter', arrowLeft); fixture.detectChanges(); @@ -725,7 +727,7 @@ describe('Multi-View Calendar - ', () => { it('should select the days in only in of the months in single/multi selection mode', () => { - spyOn(calendar.selected, 'emit'); + vi.spyOn(calendar.selected, 'emit'); const fistMonthDates = HelperTestFunctions.getMonthViewDates(fixture, 0); const secondMonthDates = HelperTestFunctions.getMonthViewDates(fixture, 1); @@ -759,7 +761,7 @@ describe('Multi-View Calendar - ', () => { }); it('Multi Selection - select/deselect date in the view', () => { - spyOn(calendar.selected, 'emit'); + vi.spyOn(calendar.selected, 'emit'); calendar.selection = 'multi'; fixture.detectChanges(); @@ -968,7 +970,7 @@ describe('Multi-View Calendar - ', () => { }); it('outside days should NOT be selected in all month views, when hideOutsideDays is false and selection is range', () => { - spyOn(calendar.selected, 'emit'); + vi.spyOn(calendar.selected, 'emit'); calendar.selection = 'range'; fixture.detectChanges(); @@ -1116,7 +1118,8 @@ describe('Multi-View Calendar - ', () => { imports: [IgxCalendarComponent] }) export class MultiViewCalendarSampleComponent { - @ViewChild(IgxCalendarComponent, { static: true }) public calendar: IgxCalendarComponent; + @ViewChild(IgxCalendarComponent, { static: true }) + public calendar: IgxCalendarComponent; public monthViews = 3; } @@ -1127,7 +1130,8 @@ export class MultiViewCalendarSampleComponent { imports: [IgxDatePickerComponent] }) export class MultiViewDatePickerSampleComponent { - @ViewChild(IgxDatePickerComponent, { static: true }) public datePicker: IgxDatePickerComponent; + @ViewChild(IgxDatePickerComponent, { static: true }) + public datePicker: IgxDatePickerComponent; public date = ymd('2019-09-15'); public monthViews = 3; } @@ -1139,7 +1143,8 @@ export class MultiViewDatePickerSampleComponent { imports: [IgxCalendarComponent, FormsModule] }) export class MultiViewNgModelSampleComponent { - @ViewChild(IgxCalendarComponent, { static: true }) public calendar: IgxCalendarComponent; + @ViewChild(IgxCalendarComponent, { static: true }) + public calendar: IgxCalendarComponent; public monthViews = 3; public model = new Date(2019, 9, 10); } diff --git a/projects/igniteui-angular/calendar/src/calendar/calendar.component.spec.ts b/projects/igniteui-angular/calendar/src/calendar/calendar.component.spec.ts index c543d803d53..0f55ee5edf5 100644 --- a/projects/igniteui-angular/calendar/src/calendar/calendar.component.spec.ts +++ b/projects/igniteui-angular/calendar/src/calendar/calendar.component.spec.ts @@ -1,12 +1,5 @@ import { Component, DebugElement, LOCALE_ID, ViewChild } from "@angular/core"; -import { - TestBed, - tick, - fakeAsync, - flush, - waitForAsync, - ComponentFixture, -} from "@angular/core/testing"; +import { TestBed, tick, fakeAsync, flush, waitForAsync, ComponentFixture, } from "@angular/core/testing"; import { FormsModule } from "@angular/forms"; import { By } from "@angular/platform-browser"; import { NoopAnimationsModule } from "@angular/platform-browser/animations"; @@ -14,24 +7,14 @@ import { NoopAnimationsModule } from "@angular/platform-browser/animations"; import { registerLocaleData } from "@angular/common"; import localeFr from "@angular/common/locales/fr"; -import { - Calendar, - IgxCalendarComponent, - IgxCalendarView, - isLeap, - IViewDateChangeEventArgs, - monthRange, - weekDay, -} from "./public_api"; +import { Calendar, IgxCalendarComponent, IgxCalendarView, isLeap, IViewDateChangeEventArgs, monthRange, weekDay, } from "./public_api"; import { UIInteractions } from "../../../test-utils/ui-interactions.spec"; -import { - DateRangeDescriptor, - DateRangeType, -} from "../../../core/src/core/dates/dateRange"; +import { DateRangeDescriptor, DateRangeType, } from "../../../core/src/core/dates/dateRange"; import { IgxDayItemComponent } from "./days-view/day-item.component"; import { HelperTestFunctions } from "../../../test-utils/calendar-helper-utils"; import { WEEKDAYS } from "../../../core/src/core/enums"; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; describe("IgxCalendar - ", () => { registerLocaleData(localeFr); @@ -82,9 +65,7 @@ describe("IgxCalendar - ", () => { // Day timedelta newDate = calendar.timedelta(startDate, "day", 3); expect(newDate.getDate()).toEqual(4); - expect(calendar.timedelta(startDate, "day", 7).toDateString()).toEqual( - calendar.timedelta(startDate, "week", 1).toDateString(), - ); + expect(calendar.timedelta(startDate, "day", 7).toDateString()).toEqual(calendar.timedelta(startDate, "week", 1).toDateString()); newDate = calendar.timedelta(startDate, "day", -3); expect(newDate.getFullYear()).toEqual(2016); expect(newDate.getDate()).toEqual(29); @@ -163,9 +144,7 @@ describe("IgxCalendar - ", () => { }); it("Should initialize a calendar component with `id` property", () => { - const domCalendar = dom.query( - By.css(HelperTestFunctions.CALENDAR), - ).nativeElement; + const domCalendar = dom.query(By.css(HelperTestFunctions.CALENDAR)).nativeElement; expect(calendar.id).toContain("igx-calendar-"); expect(domCalendar.id).toContain("igx-calendar-"); @@ -192,12 +171,8 @@ describe("IgxCalendar - ", () => { calendar.value = new Date(today); fixture.detectChanges(); - expect( - (fixture.componentInstance.model as Date).toDateString(), - ).toMatch(today.toDateString()); - expect((calendar.value as Date).toDateString()).toMatch( - today.toDateString(), - ); + expect((fixture.componentInstance.model as Date).toDateString()).toMatch(today.toDateString()); + expect((calendar.value as Date).toDateString()).toMatch(today.toDateString()); expect(() => (calendar.selection = "non-existant")).toThrow(); @@ -209,12 +184,8 @@ describe("IgxCalendar - ", () => { calendar.value = new Date(todayIsoDate); fixture.detectChanges(); - expect( - (fixture.componentInstance.model as Date).toDateString(), - ).toMatch(new Date(todayIsoDate).toDateString()); - expect((calendar.value as Date).toDateString()).toMatch( - new Date(todayIsoDate).toDateString(), - ); + expect((fixture.componentInstance.model as Date).toDateString()).toMatch(new Date(todayIsoDate).toDateString()); + expect((calendar.value as Date).toDateString()).toMatch(new Date(todayIsoDate).toDateString()); }); describe("Rendered Component - ", () => { @@ -234,52 +205,22 @@ describe("IgxCalendar - ", () => { month: true, year: false, }; - const bodyMonth = dom.query( - By.css(HelperTestFunctions.CALENDAR_DATE_CSSCLASS), - ); - const headerTitle = dom.query( - By.css( - HelperTestFunctions.CALENDAR_HEADER_YEAR_CSSCLASS, - ), - ); - const bodyYear = dom.queryAll( - By.css(HelperTestFunctions.CALENDAR_DATE_CSSCLASS), - )[1]; - const headerWeekday = dom.queryAll( - By.css( - `${HelperTestFunctions.CALENDAR_HEADER_DATE_CSSCLASS} span`, - ), - )[0]; - const headerDate = dom.queryAll( - By.css( - `${HelperTestFunctions.CALENDAR_HEADER_DATE_CSSCLASS} span`, - ), - )[1]; + const bodyMonth = dom.query(By.css(HelperTestFunctions.CALENDAR_DATE_CSSCLASS)); + const headerTitle = dom.query(By.css(HelperTestFunctions.CALENDAR_HEADER_YEAR_CSSCLASS)); + const bodyYear = dom.queryAll(By.css(HelperTestFunctions.CALENDAR_DATE_CSSCLASS))[1]; + const headerWeekday = dom.queryAll(By.css(`${HelperTestFunctions.CALENDAR_HEADER_DATE_CSSCLASS} span`))[0]; + const headerDate = dom.queryAll(By.css(`${HelperTestFunctions.CALENDAR_HEADER_DATE_CSSCLASS} span`))[1]; calendar.selectDate(calendar.viewDate); fixture.detectChanges(); - expect(calendar.formatOptions).toEqual( - jasmine.objectContaining(defaultOptions), - ); - expect(calendar.formatViews).toEqual( - jasmine.objectContaining(defaultViews), - ); - expect( - headerTitle.nativeElement.textContent.trim(), - ).toMatch("Select Date"); - expect( - headerWeekday.nativeElement.textContent.trim(), - ).toMatch("S"); - expect(headerDate.nativeElement.textContent.trim()).toMatch( - "Sep 1", - ); - expect(bodyYear.nativeElement.textContent.trim()).toMatch( - "2018", - ); - expect(bodyMonth.nativeElement.textContent.trim()).toMatch( - "Sep", - ); + expect(calendar.formatOptions).toEqual(expect.objectContaining(defaultOptions)); + expect(calendar.formatViews).toEqual(expect.objectContaining(defaultViews)); + expect(headerTitle.nativeElement.textContent.trim()).toMatch("Select Date"); + expect(headerWeekday.nativeElement.textContent.trim()).toMatch("S"); + expect(headerDate.nativeElement.textContent.trim()).toMatch("Sep 1"); + expect(bodyYear.nativeElement.textContent.trim()).toMatch("2018"); + expect(bodyMonth.nativeElement.textContent.trim()).toMatch("Sep"); // change formatOptions and formatViews const formatOptions: any = { @@ -291,31 +232,13 @@ describe("IgxCalendar - ", () => { calendar.formatViews = formatViews; fixture.detectChanges(); - expect(calendar.formatOptions).toEqual( - jasmine.objectContaining( - Object.assign(defaultOptions, formatOptions), - ), - ); - expect(calendar.formatViews).toEqual( - jasmine.objectContaining( - Object.assign(defaultViews, formatViews), - ), - ); - expect( - headerTitle.nativeElement.textContent.trim(), - ).toMatch("Select Date"); - expect( - headerWeekday.nativeElement.textContent.trim(), - ).toMatch("S"); - expect(headerDate.nativeElement.textContent.trim()).toMatch( - "Sep 1", - ); - expect(bodyYear.nativeElement.textContent.trim()).toMatch( - "18", - ); - expect(bodyMonth.nativeElement.textContent.trim()).toMatch( - "September", - ); + expect(calendar.formatOptions).toEqual(expect.objectContaining(Object.assign(defaultOptions, formatOptions))); + expect(calendar.formatViews).toEqual(expect.objectContaining(Object.assign(defaultViews, formatViews))); + expect(headerTitle.nativeElement.textContent.trim()).toMatch("Select Date"); + expect(headerWeekday.nativeElement.textContent.trim()).toMatch("S"); + expect(headerDate.nativeElement.textContent.trim()).toMatch("Sep 1"); + expect(bodyYear.nativeElement.textContent.trim()).toMatch("18"); + expect(bodyMonth.nativeElement.textContent.trim()).toMatch("September"); // change formatOptions and formatViews formatOptions.year = "numeric"; @@ -325,74 +248,44 @@ describe("IgxCalendar - ", () => { calendar.formatViews = formatViews; fixture.detectChanges(); - expect(calendar.formatOptions).toEqual( - jasmine.objectContaining( - Object.assign(defaultOptions, formatOptions), - ), - ); - expect(calendar.formatViews).toEqual( - jasmine.objectContaining( - Object.assign(defaultViews, formatViews), - ), - ); - expect( - headerTitle.nativeElement.textContent.trim(), - ).toMatch("Select Date"); - expect( - headerWeekday.nativeElement.textContent.trim(), - ).toMatch("S"); - expect(headerDate.nativeElement.textContent.trim()).toMatch( - "Sep 1", - ); - expect(bodyYear.nativeElement.textContent.trim()).toMatch( - "2018", - ); - expect(bodyMonth.nativeElement.textContent.trim()).toMatch( - "8", - ); + expect(calendar.formatOptions).toEqual(expect.objectContaining(Object.assign(defaultOptions, formatOptions))); + expect(calendar.formatViews).toEqual(expect.objectContaining(Object.assign(defaultViews, formatViews))); + expect(headerTitle.nativeElement.textContent.trim()).toMatch("Select Date"); + expect(headerWeekday.nativeElement.textContent.trim()).toMatch("S"); + expect(headerDate.nativeElement.textContent.trim()).toMatch("Sep 1"); + expect(bodyYear.nativeElement.textContent.trim()).toMatch("2018"); + expect(bodyMonth.nativeElement.textContent.trim()).toMatch("8"); }); it("Should show right month when value is set", () => { - fixture = TestBed.createComponent( - IgxCalendarValueComponent, - ); + fixture = TestBed.createComponent(IgxCalendarValueComponent); fixture.detectChanges(); calendar = fixture.componentInstance.calendar; expect(calendar.weekStart).toEqual(WEEKDAYS.SUNDAY); expect(calendar.selection).toEqual("single"); - expect(calendar.viewDate.getMonth()).toEqual( - (calendar.value as Date).getMonth(), - ); + expect(calendar.viewDate.getMonth()).toEqual((calendar.value as Date).getMonth()); const date = new Date(2020, 8, 28); calendar.viewDate = date; fixture.detectChanges(); - expect(calendar.viewDate.getMonth()).toEqual( - date.getMonth(), - ); + expect(calendar.viewDate.getMonth()).toEqual(date.getMonth()); calendar.value = new Date(2020, 9, 15); fixture.detectChanges(); - expect(calendar.viewDate.getMonth()).toEqual( - date.getMonth(), - ); + expect(calendar.viewDate.getMonth()).toEqual(date.getMonth()); const isoStringDate = new Date(2020, 10, 10).toISOString(); calendar.viewDate = isoStringDate; fixture.detectChanges(); - expect(calendar.viewDate.getMonth()).toEqual( - new Date(isoStringDate).getMonth(), - ); + expect(calendar.viewDate.getMonth()).toEqual(new Date(isoStringDate).getMonth()); calendar.value = new Date(2020, 11, 15).toISOString(); fixture.detectChanges(); - expect(calendar.viewDate.getMonth()).toEqual( - new Date(isoStringDate).getMonth(), - ); + expect(calendar.viewDate.getMonth()).toEqual(new Date(isoStringDate).getMonth()); }); it("Should properly set locale", () => { @@ -400,86 +293,40 @@ describe("IgxCalendar - ", () => { fixture.componentInstance.model = new Date(); fixture.detectChanges(); - const bodyMonth = dom.query( - By.css(HelperTestFunctions.CALENDAR_DATE_CSSCLASS), - ); - const headerTitle = dom.query( - By.css( - HelperTestFunctions.CALENDAR_HEADER_YEAR_CSSCLASS, - ), - ); - const bodyYear = dom.queryAll( - By.css(HelperTestFunctions.CALENDAR_DATE_CSSCLASS), - )[1]; - const headerWeekday = dom.queryAll( - By.css( - `${HelperTestFunctions.CALENDAR_HEADER_DATE_CSSCLASS} span`, - ), - )[0]; - const headerDate = dom.queryAll( - By.css( - `${HelperTestFunctions.CALENDAR_HEADER_DATE_CSSCLASS} span`, - ), - )[1]; - let bodyWeekday = dom.query( - By.css(HelperTestFunctions.WEEKSTART_LABEL_CSSCLASS), - ); + const bodyMonth = dom.query(By.css(HelperTestFunctions.CALENDAR_DATE_CSSCLASS)); + const headerTitle = dom.query(By.css(HelperTestFunctions.CALENDAR_HEADER_YEAR_CSSCLASS)); + const bodyYear = dom.queryAll(By.css(HelperTestFunctions.CALENDAR_DATE_CSSCLASS))[1]; + const headerWeekday = dom.queryAll(By.css(`${HelperTestFunctions.CALENDAR_HEADER_DATE_CSSCLASS} span`))[0]; + const headerDate = dom.queryAll(By.css(`${HelperTestFunctions.CALENDAR_HEADER_DATE_CSSCLASS} span`))[1]; + let bodyWeekday = dom.query(By.css(HelperTestFunctions.WEEKSTART_LABEL_CSSCLASS)); calendar.selectDate(calendar.viewDate); fixture.detectChanges(); - expect( - headerTitle.nativeElement.textContent.trim(), - ).toMatch("Select Date"); - expect( - headerWeekday.nativeElement.textContent.trim(), - ).toMatch("S"); - expect(headerDate.nativeElement.textContent.trim()).toMatch( - "Sep 1", - ); - expect(bodyYear.nativeElement.textContent.trim()).toMatch( - "2018", - ); - expect(bodyMonth.nativeElement.textContent.trim()).toMatch( - "September", - ); - expect( - bodyWeekday.nativeElement.textContent.trim(), - ).toMatch("S"); + expect(headerTitle.nativeElement.textContent.trim()).toMatch("Select Date"); + expect(headerWeekday.nativeElement.textContent.trim()).toMatch("S"); + expect(headerDate.nativeElement.textContent.trim()).toMatch("Sep 1"); + expect(bodyYear.nativeElement.textContent.trim()).toMatch("2018"); + expect(bodyMonth.nativeElement.textContent.trim()).toMatch("September"); + expect(bodyWeekday.nativeElement.textContent.trim()).toMatch("S"); // change formatOptions and formatViews const locale = "fr"; calendar.locale = locale; fixture.detectChanges(); - bodyWeekday = dom.query( - By.css(HelperTestFunctions.WEEKSTART_LABEL_CSSCLASS), - ); + bodyWeekday = dom.query(By.css(HelperTestFunctions.WEEKSTART_LABEL_CSSCLASS)); expect(calendar.locale).toEqual(locale); - expect( - headerTitle.nativeElement.textContent.trim(), - ).toMatch("Select Date"); - expect( - headerWeekday.nativeElement.textContent.trim(), - ).toMatch("sam.,"); - expect(headerDate.nativeElement.textContent.trim()).toMatch( - "1 sept.", - ); - expect(bodyYear.nativeElement.textContent.trim()).toMatch( - "18", - ); - expect(bodyMonth.nativeElement.textContent.trim()).toMatch( - "sept.", - ); - expect( - bodyWeekday.nativeElement.textContent.trim(), - ).toMatch("L"); + expect(headerTitle.nativeElement.textContent.trim()).toMatch("Select Date"); + expect(headerWeekday.nativeElement.textContent.trim()).toMatch("sam.,"); + expect(headerDate.nativeElement.textContent.trim()).toMatch("1 sept."); + expect(bodyYear.nativeElement.textContent.trim()).toMatch("18"); + expect(bodyMonth.nativeElement.textContent.trim()).toMatch("sept."); + expect(bodyWeekday.nativeElement.textContent.trim()).toMatch("L"); }); it("Should default to today date when invalid date is passed", () => { - fixture = TestBed.createComponent( - IgxCalendarValueComponent, - ); + fixture = TestBed.createComponent(IgxCalendarValueComponent); fixture.detectChanges(); calendar = fixture.componentInstance.calendar; @@ -504,47 +351,25 @@ describe("IgxCalendar - ", () => { const today = new Date(Date.now()); calendar.viewDate = today; fixture.detectChanges(); - const calendarRows = dom.queryAll( - By.css(HelperTestFunctions.CALENDAR_ROW_CSSCLASS), - ); + const calendarRows = dom.queryAll(By.css(HelperTestFunctions.CALENDAR_ROW_CSSCLASS)); // 6 weeks + week header expect(calendarRows.length).toEqual(7); // 6 calendar rows * 7 elements in each - expect( - dom.queryAll( - By.css( - `${HelperTestFunctions.CALENDAR_ROW_CSSCLASS} > igx-day-item`, - ), - ).length, - ).toEqual(42); - expect( - dom.queryAll( - By.css( - `${HelperTestFunctions.CALENDAR_ROW_CSSCLASS} > span`, - ), - ).length, - ).toEqual(7); + expect(dom.queryAll(By.css(`${HelperTestFunctions.CALENDAR_ROW_CSSCLASS} > igx-day-item`)).length).toEqual(42); + expect(dom.queryAll(By.css(`${HelperTestFunctions.CALENDAR_ROW_CSSCLASS} > span`)).length).toEqual(7); // Today class applied - expect( - dom - .query( - By.css( - HelperTestFunctions.CURRENT_DATE_CSSCLASS, - ), - ) - .nativeElement.textContent.trim(), - ).toMatch(today.getDate().toString()); + expect(dom + .query(By.css(HelperTestFunctions.CURRENT_DATE_CSSCLASS)) + .nativeElement.textContent.trim()).toMatch(today.getDate().toString()); // Hide calendar header when not single selection calendar.selection = "multi"; fixture.detectChanges(); - const calendarHeader = dom.query( - By.css(HelperTestFunctions.CALENDAR_HEADER_CSSCLASS), - ); + const calendarHeader = dom.query(By.css(HelperTestFunctions.CALENDAR_HEADER_CSSCLASS)); expect(calendarHeader).toBeFalsy(); }); @@ -554,36 +379,16 @@ describe("IgxCalendar - ", () => { calendar.showWeekNumbers = true; fixture.detectChanges(); - const calendarRows = dom.queryAll( - By.css(HelperTestFunctions.CALENDAR_ROW_CSSCLASS), - ); + const calendarRows = dom.queryAll(By.css(HelperTestFunctions.CALENDAR_ROW_CSSCLASS)); expect(calendarRows.length).toEqual(7); // 6 calendar rows * 8 elements in each - expect( - dom.queryAll( - By.css( - `${HelperTestFunctions.CALENDAR_ROW_CSSCLASS} > igx-day-item`, - ), - ).length + - dom.queryAll( - By.css(`${HelperTestFunctions.CALENDAR_ROW_CSSCLASS} > - ${HelperTestFunctions.CALENDAR_WEEK_NUMBER_CLASS}`), - ).length, - ).toEqual(48); - - expect( - dom.queryAll( - By.css( - `${HelperTestFunctions.CALENDAR_ROW_CSSCLASS} > span`, - ), - ).length + - dom.queryAll( - By.css( - `${HelperTestFunctions.CALENDAR_ROW_CSSCLASS} > ${HelperTestFunctions.CALENDAR_WEEK_NUMBER_LABEL_CLASS}`, - ), - ).length, - ).toEqual(8); + expect(dom.queryAll(By.css(`${HelperTestFunctions.CALENDAR_ROW_CSSCLASS} > igx-day-item`)).length + + dom.queryAll(By.css(`${HelperTestFunctions.CALENDAR_ROW_CSSCLASS} > + ${HelperTestFunctions.CALENDAR_WEEK_NUMBER_CLASS}`)).length).toEqual(48); + + expect(dom.queryAll(By.css(`${HelperTestFunctions.CALENDAR_ROW_CSSCLASS} > span`)).length + + dom.queryAll(By.css(`${HelperTestFunctions.CALENDAR_ROW_CSSCLASS} > ${HelperTestFunctions.CALENDAR_WEEK_NUMBER_LABEL_CLASS}`)).length).toEqual(8); }); it("Week numbers should appear as first column", () => { @@ -592,17 +397,13 @@ describe("IgxCalendar - ", () => { calendar.showWeekNumbers = true; fixture.detectChanges(); - const calendarRows = dom.queryAll( - By.css(`${HelperTestFunctions.CALENDAR_ROW_CSSCLASS}`), - ); + const calendarRows = dom.queryAll(By.css(`${HelperTestFunctions.CALENDAR_ROW_CSSCLASS}`)); const expectedWeeks = ["W", "1", "2", "3", "4", "5", "6"]; calendarRows.forEach((row, idx) => { const firstRowItem = row.nativeElement.children[0]; - expect(firstRowItem.firstChild.innerText).toEqual( - expectedWeeks[idx], - ); + expect(firstRowItem.firstChild.innerText).toEqual(expectedWeeks[idx]); }); }); @@ -613,16 +414,12 @@ describe("IgxCalendar - ", () => { calendar.showWeekNumbers = true; fixture.detectChanges(); - const calendarRowsMar = dom.queryAll( - By.css(`${HelperTestFunctions.CALENDAR_ROW_CSSCLASS}`), - ); + const calendarRowsMar = dom.queryAll(By.css(`${HelperTestFunctions.CALENDAR_ROW_CSSCLASS}`)); calendarRowsMar.forEach((row, idx) => { const firstRowItem = row.nativeElement.children[0]; if (idx === 5) { - expect(firstRowItem.firstChild.innerText).toEqual( - "13", - ); + expect(firstRowItem.firstChild.innerText).toEqual("13"); } }); @@ -630,16 +427,12 @@ describe("IgxCalendar - ", () => { calendar.viewDate = firstDayOfOct; fixture.detectChanges(); - const calendarRowsOct = dom.queryAll( - By.css(`${HelperTestFunctions.CALENDAR_ROW_CSSCLASS}`), - ); + const calendarRowsOct = dom.queryAll(By.css(`${HelperTestFunctions.CALENDAR_ROW_CSSCLASS}`)); calendarRowsOct.forEach((row, idx) => { const firstRowItem = row.nativeElement.children[0]; if (idx === 5) { - expect(firstRowItem.firstChild.innerText).toEqual( - "44", - ); + expect(firstRowItem.firstChild.innerText).toEqual("44"); } }); @@ -647,17 +440,13 @@ describe("IgxCalendar - ", () => { calendar.viewDate = firstDayOfDec; fixture.detectChanges(); - const calendarRowsDec = dom.queryAll( - By.css(`${HelperTestFunctions.CALENDAR_ROW_CSSCLASS}`), - ); + const calendarRowsDec = dom.queryAll(By.css(`${HelperTestFunctions.CALENDAR_ROW_CSSCLASS}`)); calendarRowsDec.forEach((row, idx) => { const firstRowItem = row.nativeElement.children[0]; if (idx === 6) { // With simple counting for Sunday start, expect 53 - expect(firstRowItem.firstChild.innerText).toEqual( - "53", - ); + expect(firstRowItem.firstChild.innerText).toEqual("53"); } }); }); @@ -666,28 +455,14 @@ describe("IgxCalendar - ", () => { calendar.activeView = "year"; fixture.detectChanges(); - expect( - dom.query( - By.css( - HelperTestFunctions.CALENDAR_ROW_WRAP_CSSCLASS, - ), - ), - ).toBeDefined(); - const months = dom.queryAll( - By.css(HelperTestFunctions.MONTH_CSSCLASS), - ); - const currentMonth = dom.query( - By.css(HelperTestFunctions.CURRENT_MONTH_CSSCLASS), - ); + expect(dom.query(By.css(HelperTestFunctions.CALENDAR_ROW_WRAP_CSSCLASS))).toBeDefined(); + const months = dom.queryAll(By.css(HelperTestFunctions.MONTH_CSSCLASS)); + const currentMonth = dom.query(By.css(HelperTestFunctions.CURRENT_MONTH_CSSCLASS)); expect(months.length).toEqual(12); - expect( - currentMonth.nativeElement.textContent.trim(), - ).toMatch("June"); + expect(currentMonth.nativeElement.textContent.trim()).toMatch("June"); - months[0].nativeElement.dispatchEvent( - new Event("mousedown"), - ); + months[0].nativeElement.dispatchEvent(new Event("mousedown")); fixture.detectChanges(); expect(calendar.viewDate.getMonth()).toEqual(0); @@ -695,21 +470,13 @@ describe("IgxCalendar - ", () => { calendar.activeView = "decade"; fixture.detectChanges(); - const years = dom.queryAll( - By.css(HelperTestFunctions.YEAR_CSSCLASS), - ); - const currentYear = dom.query( - By.css(HelperTestFunctions.CURRENT_YEAR_CSSCLASS), - ); + const years = dom.queryAll(By.css(HelperTestFunctions.YEAR_CSSCLASS)); + const currentYear = dom.query(By.css(HelperTestFunctions.CURRENT_YEAR_CSSCLASS)); expect(years.length).toEqual(15); - expect( - currentYear.nativeElement.textContent.trim(), - ).toMatch("2017"); + expect(currentYear.nativeElement.textContent.trim()).toMatch("2017"); - years[0].nativeElement.dispatchEvent( - new Event("mousedown"), - ); + years[0].nativeElement.dispatchEvent(new Event("mousedown")); fixture.detectChanges(); expect(calendar.viewDate.getFullYear()).toEqual(2010); @@ -718,20 +485,14 @@ describe("IgxCalendar - ", () => { it("Calendar selection - single with event", () => { fixture.detectChanges(); - const target = dom.query( - By.css(HelperTestFunctions.SELECTED_DATE_CSSCLASS), - ); + const target = dom.query(By.css(HelperTestFunctions.SELECTED_DATE_CSSCLASS)); const weekDiv = target.parent; - const weekDays = weekDiv.queryAll( - By.css(HelperTestFunctions.DAY_CSSCLASS), - ); + const weekDays = weekDiv.queryAll(By.css(HelperTestFunctions.DAY_CSSCLASS)); const nextDay = new Date(2017, 5, 14); - expect((calendar.value as Date).toDateString()).toMatch( - new Date(2017, 5, 13).toDateString(), - ); + expect((calendar.value as Date).toDateString()).toMatch(new Date(2017, 5, 13).toDateString()); - spyOn(calendar.selected, "emit"); + vi.spyOn(calendar.selected, "emit"); // Select 14th const dateElement = weekDays[3].nativeElement.firstChild; @@ -740,136 +501,80 @@ describe("IgxCalendar - ", () => { fixture.detectChanges(); expect(calendar.selected.emit).toHaveBeenCalled(); - expect((calendar.value as Date).toDateString()).toMatch( - nextDay.toDateString(), - ); + expect((calendar.value as Date).toDateString()).toMatch(nextDay.toDateString()); HelperTestFunctions.verifyDateSelected(weekDays[3]); - expect( - ( - fixture.componentInstance.model as Date - ).toDateString(), - ).toMatch(nextDay.toDateString()); + expect((fixture.componentInstance.model as Date).toDateString()).toMatch(nextDay.toDateString()); HelperTestFunctions.verifyDateNotSelected(target); }); it("Calendar selection - outside of current month - next month", () => { - const parent = dom.query( - By.css( - `${HelperTestFunctions.CALENDAR_ROW_CSSCLASS}:last-child`, - ), - ); - const parentDates = parent.queryAll( - By.css(HelperTestFunctions.INACTIVE_DAYS_CSSCLASS), - ); + const parent = dom.query(By.css(`${HelperTestFunctions.CALENDAR_ROW_CSSCLASS}:last-child`)); + const parentDates = parent.queryAll(By.css(HelperTestFunctions.INACTIVE_DAYS_CSSCLASS)); const target = parentDates[parentDates.length - 1]; target.nativeElement.firstChild.click(); fixture.detectChanges(); - expect( - ( - fixture.componentInstance.model as Date - ).toDateString(), - ).toMatch(new Date(2017, 6, 8).toDateString()); + expect((fixture.componentInstance.model as Date).toDateString()).toMatch(new Date(2017, 6, 8).toDateString()); - expect( - dom - .query( - By.css( - HelperTestFunctions.CALENDAR_HEADER_DATE_CSSCLASS, - ), - ) - .nativeElement.textContent.includes("Jul"), - ).toBe(true); + expect(dom + .query(By.css(HelperTestFunctions.CALENDAR_HEADER_DATE_CSSCLASS)) + .nativeElement.textContent.includes("Jul")).toBe(true); }); it("Calendar selection - outside of current month - previous month", () => { - const parent = dom.queryAll( - By.css(HelperTestFunctions.CALENDAR_ROW_CSSCLASS), - )[1]; - const target = parent.queryAll( - By.css(HelperTestFunctions.INACTIVE_DAYS_CSSCLASS), - )[0]; + const parent = dom.queryAll(By.css(HelperTestFunctions.CALENDAR_ROW_CSSCLASS))[1]; + const target = parent.queryAll(By.css(HelperTestFunctions.INACTIVE_DAYS_CSSCLASS))[0]; target.nativeElement.firstChild.click(); fixture.detectChanges(); - expect( - ( - fixture.componentInstance.model as Date - ).toDateString(), - ).toMatch(new Date(2017, 4, 28).toDateString()); - expect( - dom - .query( - By.css( - HelperTestFunctions.CALENDAR_HEADER_DATE_CSSCLASS, - ), - ) - .nativeElement.textContent.includes("May"), - ).toBe(true); + expect((fixture.componentInstance.model as Date).toDateString()).toMatch(new Date(2017, 4, 28).toDateString()); + expect(dom + .query(By.css(HelperTestFunctions.CALENDAR_HEADER_DATE_CSSCLASS)) + .nativeElement.textContent.includes("May")).toBe(true); }); it("Calendar selection - single through API", () => { fixture.detectChanges(); - const target = dom.query( - By.css(HelperTestFunctions.SELECTED_DATE_CSSCLASS), - ); + const target = dom.query(By.css(HelperTestFunctions.SELECTED_DATE_CSSCLASS)); const weekDiv = target.parent; - const weekDays = weekDiv.queryAll( - By.css(HelperTestFunctions.DAY_CSSCLASS), - ); + const weekDays = weekDiv.queryAll(By.css(HelperTestFunctions.DAY_CSSCLASS)); let nextDay = new Date(2017, 5, 14); - expect((calendar.value as Date).toDateString()).toMatch( - new Date(2017, 5, 13).toDateString(), - ); + expect((calendar.value as Date).toDateString()).toMatch(new Date(2017, 5, 13).toDateString()); calendar.selectDate(new Date(2017, 5, 14)); fixture.detectChanges(); - expect((calendar.value as Date).toDateString()).toMatch( - nextDay.toDateString(), - ); + expect((calendar.value as Date).toDateString()).toMatch(nextDay.toDateString()); HelperTestFunctions.verifyDateSelected(weekDays[3]); - expect( - (fixture.componentInstance.model as Date).toDateString(), - ).toMatch(nextDay.toDateString()); + expect((fixture.componentInstance.model as Date).toDateString()).toMatch(nextDay.toDateString()); HelperTestFunctions.verifyDateNotSelected(target); nextDay = new Date(2017, 6, 15); calendar.selectDate(new Date(2017, 6, 15).toISOString()); fixture.detectChanges(); - expect((calendar.value as Date).toDateString()).toMatch( - nextDay.toDateString(), - ); + expect((calendar.value as Date).toDateString()).toMatch(nextDay.toDateString()); }); it("Calendar selection - multiple with event", () => { fixture.detectChanges(); - const target = dom.query( - By.css(HelperTestFunctions.SELECTED_DATE_CSSCLASS), - ); + const target = dom.query(By.css(HelperTestFunctions.SELECTED_DATE_CSSCLASS)); const weekDiv = target.parent; - const weekDays = weekDiv.queryAll( - By.css(HelperTestFunctions.DAY_CSSCLASS), - ); + const weekDays = weekDiv.queryAll(By.css(HelperTestFunctions.DAY_CSSCLASS)); calendar.selection = "multi"; fixture.detectChanges(); expect(calendar.value instanceof Array).toBeTruthy(); - expect( - fixture.componentInstance.model instanceof Array, - ).toBeTruthy(); + expect(fixture.componentInstance.model instanceof Array).toBeTruthy(); expect((calendar.value as Date[]).length).toEqual(0); - expect( - (fixture.componentInstance.model as Date[]).length, - ).toEqual(0); + expect((fixture.componentInstance.model as Date[]).length).toEqual(0); for (const day of weekDays) { day.nativeElement.firstChild.click(); @@ -877,9 +582,7 @@ describe("IgxCalendar - ", () => { } expect((calendar.value as Date[]).length).toEqual(7); - expect( - (fixture.componentInstance.model as Date[]).length, - ).toEqual(7); + expect((fixture.componentInstance.model as Date[]).length).toEqual(7); weekDays.forEach((el) => { HelperTestFunctions.verifyDateSelected(el); }); @@ -890,24 +593,16 @@ describe("IgxCalendar - ", () => { expect((calendar.value as Date[]).length).toEqual(6); - expect( - (fixture.componentInstance.model as Date[]).length, - ).toEqual(6); - HelperTestFunctions.verifyDateNotSelected( - weekDays.at(-1) - ); + expect((fixture.componentInstance.model as Date[]).length).toEqual(6); + HelperTestFunctions.verifyDateNotSelected(weekDays.at(-1)); }); it("Calendar selection - multiple through API", () => { fixture.detectChanges(); - const target = dom.query( - By.css(HelperTestFunctions.SELECTED_DATE_CSSCLASS), - ); + const target = dom.query(By.css(HelperTestFunctions.SELECTED_DATE_CSSCLASS)); const weekDiv = target.parent; - const weekDays = weekDiv.queryAll( - By.css(HelperTestFunctions.DAY_CSSCLASS), - ); + const weekDays = weekDiv.queryAll(By.css(HelperTestFunctions.DAY_CSSCLASS)); calendar.selection = "multi"; fixture.detectChanges(); @@ -918,17 +613,9 @@ describe("IgxCalendar - ", () => { calendar.selectDate(lastDay); fixture.detectChanges(); - expect( - ( - fixture.componentInstance.model as Date[] - )[0].toDateString(), - ).toMatch(lastDay.toDateString()); - expect(calendar.value[0].toDateString()).toMatch( - lastDay.toDateString(), - ); - HelperTestFunctions.verifyDateSelected( - weekDays[weekDays.length - 1], - ); + expect((fixture.componentInstance.model as Date[])[0].toDateString()).toMatch(lastDay.toDateString()); + expect(calendar.value[0].toDateString()).toMatch(lastDay.toDateString()); + HelperTestFunctions.verifyDateSelected(weekDays[weekDays.length - 1]); // Multiple dates calendar.selectDate([ @@ -937,9 +624,7 @@ describe("IgxCalendar - ", () => { ]); fixture.detectChanges(); - expect( - (fixture.componentInstance.model as Date[]).length, - ).toEqual(3); + expect((fixture.componentInstance.model as Date[]).length).toEqual(3); expect((calendar.value as Date[]).length).toEqual(3); // 11th June @@ -951,13 +636,9 @@ describe("IgxCalendar - ", () => { it("Calendar selection - range with event", () => { fixture.detectChanges(); - const target = dom.query( - By.css(HelperTestFunctions.SELECTED_DATE_CSSCLASS), - ); + const target = dom.query(By.css(HelperTestFunctions.SELECTED_DATE_CSSCLASS)); const weekDiv = target.parent; - const weekDays = weekDiv.queryAll( - By.css(HelperTestFunctions.DAY_CSSCLASS), - ); + const weekDays = weekDiv.queryAll(By.css(HelperTestFunctions.DAY_CSSCLASS)); calendar.selection = "range"; fixture.detectChanges(); @@ -969,24 +650,16 @@ describe("IgxCalendar - ", () => { weekDays[0].nativeElement.firstChild.click(); fixture.detectChanges(); - expect( - (fixture.componentInstance.model as Date[]).length, - ).toEqual(1); + expect((fixture.componentInstance.model as Date[]).length).toEqual(1); expect((calendar.value as Date[]).length).toEqual(1); - expect( - ( - fixture.componentInstance.model as Date[] - )[0].toDateString(), - ).toMatch(firstDay.toDateString()); + expect((fixture.componentInstance.model as Date[])[0].toDateString()).toMatch(firstDay.toDateString()); HelperTestFunctions.verifyDateSelected(weekDays[0]); // ...and cancel it weekDays[0].nativeElement.firstChild.click(); fixture.detectChanges(); - expect( - (fixture.componentInstance.model as Date[]).length, - ).toEqual(0); + expect((fixture.componentInstance.model as Date[]).length).toEqual(0); expect((calendar.value as Date[]).length).toEqual(0); HelperTestFunctions.verifyDateNotSelected(weekDays[0]); @@ -999,18 +672,10 @@ describe("IgxCalendar - ", () => { fixture.detectChanges(); - expect( - (fixture.componentInstance.model as Date[]).length, - ).toEqual(7); + expect((fixture.componentInstance.model as Date[]).length).toEqual(7); expect((calendar.value as Date[]).length).toEqual(7); - expect(calendar.value[0].toDateString()).toMatch( - firstDay.toDateString(), - ); - expect( - calendar.value[ - (calendar.value as Date[]).length - 1 - ].toDateString(), - ).toMatch(lastDay.toDateString()); + expect(calendar.value[0].toDateString()).toMatch(firstDay.toDateString()); + expect(calendar.value[(calendar.value as Date[]).length - 1].toDateString()).toMatch(lastDay.toDateString()); weekDays.forEach((el) => { HelperTestFunctions.verifyDateSelected(el); }); @@ -1019,13 +684,9 @@ describe("IgxCalendar - ", () => { it("Calendar selection - range through API", () => { fixture.detectChanges(); - const target = dom.query( - By.css(HelperTestFunctions.SELECTED_DATE_CSSCLASS), - ); + const target = dom.query(By.css(HelperTestFunctions.SELECTED_DATE_CSSCLASS)); const weekDiv = target.parent; - const weekDays = weekDiv.queryAll( - By.css(HelperTestFunctions.DAY_CSSCLASS), - ); + const weekDays = weekDiv.queryAll(By.css(HelperTestFunctions.DAY_CSSCLASS)); calendar.selection = "range"; fixture.detectChanges(); @@ -1037,18 +698,10 @@ describe("IgxCalendar - ", () => { calendar.selectDate([firstDay, lastDay]); fixture.detectChanges(); - expect( - (fixture.componentInstance.model as Date[]).length, - ).toEqual(7); + expect((fixture.componentInstance.model as Date[]).length).toEqual(7); expect((calendar.value as Date[]).length).toEqual(7); - expect(calendar.value[0].toDateString()).toMatch( - firstDay.toDateString(), - ); - expect( - calendar.value[ - (calendar.value as Date[]).length - 1 - ].toDateString(), - ).toMatch(lastDay.toDateString()); + expect(calendar.value[0].toDateString()).toMatch(firstDay.toDateString()); + expect(calendar.value[(calendar.value as Date[]).length - 1].toDateString()).toMatch(lastDay.toDateString()); weekDays.forEach((el) => { HelperTestFunctions.verifyDateSelected(el); }); @@ -1056,18 +709,10 @@ describe("IgxCalendar - ", () => { calendar.selectDate([firstDay, midDay]); fixture.detectChanges(); - expect( - (fixture.componentInstance.model as Date[]).length, - ).toEqual(4); + expect((fixture.componentInstance.model as Date[]).length).toEqual(4); expect((calendar.value as Date[]).length).toEqual(4); - expect(calendar.value[0].toDateString()).toMatch( - firstDay.toDateString(), - ); - expect( - calendar.value[ - (calendar.value as Date[]).length - 1 - ].toDateString(), - ).toMatch(midDay.toDateString()); + expect(calendar.value[0].toDateString()).toMatch(firstDay.toDateString()); + expect(calendar.value[(calendar.value as Date[]).length - 1].toDateString()).toMatch(midDay.toDateString()); for (const i of [0, 1, 2, 3]) { HelperTestFunctions.verifyDateSelected(weekDays[i]); } @@ -1077,27 +722,17 @@ describe("IgxCalendar - ", () => { fixture.detectChanges(); expect((calendar.value as Date[]).length).toEqual(1); - expect(calendar.value[0].toDateString()).toMatch( - lastDay.toDateString(), - ); + expect(calendar.value[0].toDateString()).toMatch(lastDay.toDateString()); HelperTestFunctions.verifyDateSelected(weekDays[6]); // Select with array of 3 days calendar.selectDate([midDay, lastDay, firstDay]); fixture.detectChanges(); - expect( - (fixture.componentInstance.model as Date[]).length, - ).toEqual(7); + expect((fixture.componentInstance.model as Date[]).length).toEqual(7); expect((calendar.value as Date[]).length).toEqual(7); - expect(calendar.value[0].toDateString()).toMatch( - firstDay.toDateString(), - ); - expect( - calendar.value[ - (calendar.value as Date[]).length - 1 - ].toDateString(), - ).toMatch(lastDay.toDateString()); + expect(calendar.value[0].toDateString()).toMatch(firstDay.toDateString()); + expect(calendar.value[(calendar.value as Date[]).length - 1].toDateString()).toMatch(lastDay.toDateString()); weekDays.forEach((el) => { HelperTestFunctions.verifyDateSelected(el); }); @@ -1108,80 +743,49 @@ describe("IgxCalendar - ", () => { let component: DebugElement; beforeEach(waitForAsync(() => { - component = dom.query( - By.css(HelperTestFunctions.CALENDAR_WRAPPER_CLASS), - ); + component = dom.query(By.css(HelperTestFunctions.CALENDAR_WRAPPER_CLASS)); component.nativeElement.focus(); })); it("Calendar keyboard navigation - PageUp/PageDown", () => { - UIInteractions.triggerKeyDownEvtUponElem( - "PageUp", - component.nativeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("PageUp", component.nativeElement); fixture.detectChanges(); expect(calendar.viewDate.getMonth()).toEqual(4); calendar.viewDate = new Date(2017, 5, 13); fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "PageDown", - component.nativeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("PageDown", component.nativeElement); fixture.detectChanges(); expect(calendar.viewDate.getMonth()).toEqual(6); - UIInteractions.triggerKeyDownEvtUponElem( - "PageUp", - component.nativeElement, - true, - false, - true, - ); + UIInteractions.triggerKeyDownEvtUponElem("PageUp", component.nativeElement, true, false, true); fixture.detectChanges(); expect(calendar.viewDate.getFullYear()).toEqual(2016); calendar.viewDate = new Date(2017, 5, 13); fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "PageDown", - component.nativeElement, - true, - false, - true, - ); + UIInteractions.triggerKeyDownEvtUponElem("PageDown", component.nativeElement, true, false, true); fixture.detectChanges(); expect(calendar.viewDate.getFullYear()).toEqual(2018); }); it("Calendar keyboard navigation - Home/End/Enter", () => { - const days = calendar.daysView.dates.filter( - (day) => day.isCurrentMonth, - ); + const days = calendar.daysView.dates.filter((day) => day.isCurrentMonth); const firstDay = days.at(0); const lastDay = days.at(-1); - UIInteractions.triggerKeyDownEvtUponElem( - "Home", - component.nativeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("Home", component.nativeElement); fixture.detectChanges(); expect(calendar.activeDate.getDate().toString()).toEqual(firstDay.nativeElement.textContent.trim()); - UIInteractions.triggerKeyDownEvtUponElem( - "End", - component.nativeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("End", component.nativeElement); fixture.detectChanges(); expect(calendar.activeDate.getDate().toString()).toEqual(lastDay.nativeElement.textContent.trim()); - UIInteractions.triggerKeyDownEvtUponElem( - "Enter", - component.nativeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("Enter", component.nativeElement); fixture.detectChanges(); expect(calendar.value).toEqual(lastDay.date.native); @@ -1194,57 +798,39 @@ describe("IgxCalendar - ", () => { expect(calendar.activeDate.getDate()).toEqual(1); // Go to the next row - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowDown", - component.nativeElement - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowDown", component.nativeElement); fixture.detectChanges(); expect(calendar.activeDate.getDate()).toEqual(8); // Go to the left - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowLeft", - component.nativeElement - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowLeft", component.nativeElement); fixture.detectChanges(); expect(calendar.activeDate.getDate()).toEqual(7); // Go to the right - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowRight", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowRight", document.activeElement); fixture.detectChanges(); expect(calendar.activeDate.getDate()).toEqual(8); // Go up a row - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowUp", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowUp", document.activeElement); fixture.detectChanges(); expect(calendar.activeDate.getDate()).toEqual(1); }); it("Calendar should persist focus when navigating between prev/next month.", () => { - UIInteractions.triggerKeyDownEvtUponElem( - "Home", - component.nativeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("Home", component.nativeElement); fixture.detectChanges(); // Ensure first of month day is active expect(calendar.activeDate.getDate()).toEqual(1); // Navigate to the previous month by pressing Arrow Left - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowLeft", - component.nativeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowLeft", component.nativeElement); fixture.detectChanges(); expect(calendar.viewDate.getMonth()).toEqual(calendar.activeDate.getMonth()); expect(calendar.activeDate.getDate()).toEqual(31); @@ -1257,10 +843,7 @@ describe("IgxCalendar - ", () => { expect(calendar.value).toEqual(calendar.activeDate); // Go to the next month - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowRight", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowRight", document.activeElement); fixture.detectChanges(); expect(calendar.value).not.toEqual(calendar.activeDate); @@ -1279,17 +862,11 @@ describe("IgxCalendar - ", () => { new Date(2017, 5, 1), new Date(2017, 5, 2), ]; - dateRangeDescriptors.push( - { type: DateRangeType.Specific, dateRange: specificDates }, - { type: DateRangeType.Weekends }, - ); + dateRangeDescriptors.push({ type: DateRangeType.Specific, dateRange: specificDates }, { type: DateRangeType.Weekends }); calendar.disabledDates = dateRangeDescriptors; fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "Home", - component.nativeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("Home", component.nativeElement); fixture.detectChanges(); expect(calendar.activeDate.getDate()).toEqual(5); }); @@ -1300,20 +877,14 @@ describe("IgxCalendar - ", () => { new Date(2017, 5, 28), new Date(2017, 5, 30), ]; - dateRangeDescriptors.push( - { type: DateRangeType.Between, dateRange: rangeDates }, - { - type: DateRangeType.Specific, - dateRange: [new Date(2017, 5, 27)], - }, - ); + dateRangeDescriptors.push({ type: DateRangeType.Between, dateRange: rangeDates }, { + type: DateRangeType.Specific, + dateRange: [new Date(2017, 5, 27)], + }); calendar.disabledDates = dateRangeDescriptors; fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "End", - component.nativeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("End", component.nativeElement); fixture.detectChanges(); expect(calendar.activeDate.getDate()).toEqual(26); }); @@ -1324,23 +895,14 @@ describe("IgxCalendar - ", () => { new Date(2017, 5, 23), new Date(2017, 5, 16), ]; - dateRangeDescriptors.push( - { type: DateRangeType.Specific, dateRange: specificDates }, - { type: DateRangeType.Weekends }, - ); + dateRangeDescriptors.push({ type: DateRangeType.Specific, dateRange: specificDates }, { type: DateRangeType.Weekends }); calendar.disabledDates = dateRangeDescriptors; fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "End", - component.nativeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("End", component.nativeElement); fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowUp", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowUp", document.activeElement); fixture.detectChanges(); expect(calendar.activeDate.getDate()).toEqual(9); }); @@ -1351,23 +913,14 @@ describe("IgxCalendar - ", () => { new Date(2017, 5, 8), new Date(2017, 5, 15), ]; - dateRangeDescriptors.push( - { type: DateRangeType.Specific, dateRange: specificDates }, - { type: DateRangeType.Weekends }, - ); + dateRangeDescriptors.push({ type: DateRangeType.Specific, dateRange: specificDates }, { type: DateRangeType.Weekends }); calendar.disabledDates = dateRangeDescriptors; fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "Home", - component.nativeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("Home", component.nativeElement); fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowDown", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowDown", document.activeElement); fixture.detectChanges(); expect(calendar.activeDate.getDate()).toEqual(22); }); @@ -1385,16 +938,10 @@ describe("IgxCalendar - ", () => { calendar.disabledDates = dateRangeDescriptors; fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "End", - component.nativeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("End", component.nativeElement); fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowLeft", - component.nativeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowLeft", component.nativeElement); fixture.detectChanges(); expect(calendar.activeDate.getDate()).toEqual(1); }); @@ -1411,16 +958,10 @@ describe("IgxCalendar - ", () => { }); calendar.disabledDates = dateRangeDescriptors; fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "Home", - component.nativeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("Home", component.nativeElement); fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowRight", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowRight", document.activeElement); fixture.detectChanges(); expect(calendar.activeDate.getDate()).toEqual(30); }); @@ -1440,18 +981,12 @@ describe("IgxCalendar - ", () => { fixture.detectChanges(); // Select range using keyboard events - const fromDate = calendar.daysView.dates.filter( - (d) => - getDate(d).getTime() === new Date(2017, 5, 5).getTime(), - )[0]; + const fromDate = calendar.daysView.dates.filter((d) => getDate(d).getTime() === new Date(2017, 5, 5).getTime())[0]; UIInteractions.simulateClickAndSelectEvent(fromDate.nativeElement.firstChild); fixture.detectChanges(); - const toDate = calendar.daysView.dates.filter( - (d) => - getDate(d).getTime() === - new Date(2017, 5, 20).getTime(), - )[0]; + const toDate = calendar.daysView.dates.filter((d) => getDate(d).getTime() === + new Date(2017, 5, 20).getTime())[0]; UIInteractions.simulateClickAndSelectEvent(toDate.nativeElement.firstChild); fixture.detectChanges(); @@ -1459,14 +994,12 @@ describe("IgxCalendar - ", () => { const selectedDates = calendar.daysView.dates .toArray() .filter((d) => { - const dateTime = getDate(d).getTime(); - return ( - (dateTime >= new Date(2017, 5, 5).getTime() && - dateTime <= new Date(2017, 5, 9).getTime()) || - (dateTime >= new Date(2017, 5, 16).getTime() && - dateTime <= new Date(2017, 5, 20).getTime()) - ); - }); + const dateTime = getDate(d).getTime(); + return ((dateTime >= new Date(2017, 5, 5).getTime() && + dateTime <= new Date(2017, 5, 9).getTime()) || + (dateTime >= new Date(2017, 5, 16).getTime() && + dateTime <= new Date(2017, 5, 20).getTime())); + }); selectedDates.forEach((d) => { expect(d.selected).toBe(true); @@ -1475,12 +1008,10 @@ describe("IgxCalendar - ", () => { const notSelectedDates = calendar.daysView.dates .toArray() .filter((d) => { - const dateTime = getDate(d).getTime(); - return ( - dateTime >= new Date(2017, 5, 10).getTime() && - dateTime <= new Date(2017, 5, 15).getTime() - ); - }); + const dateTime = getDate(d).getTime(); + return (dateTime >= new Date(2017, 5, 10).getTime() && + dateTime <= new Date(2017, 5, 15).getTime()); + }); notSelectedDates.forEach((d) => { expect(d.selected).toBe(false); @@ -1490,181 +1021,107 @@ describe("IgxCalendar - ", () => { describe("Disabled dates - ", () => { it('Should disable date when using "After" date descriptor.', () => { - DateRangesPropertiesTester.testAfter( - DateRangesPropertiesTester.assignDisableDatesDescriptors, - DateRangesPropertiesTester.testDisabledDates, - ); + DateRangesPropertiesTester.testAfter(DateRangesPropertiesTester.assignDisableDatesDescriptors, DateRangesPropertiesTester.testDisabledDates); }); it('Should disable date when using "Before" date descriptor.', () => { - DateRangesPropertiesTester.testBefore( - DateRangesPropertiesTester.assignDisableDatesDescriptors, - DateRangesPropertiesTester.testDisabledDates, - ); + DateRangesPropertiesTester.testBefore(DateRangesPropertiesTester.assignDisableDatesDescriptors, DateRangesPropertiesTester.testDisabledDates); }); it('Should disable date when using "Between" date descriptor with min date declared first.', () => { - DateRangesPropertiesTester.testBetweenWithMinDateFirst( - DateRangesPropertiesTester.assignDisableDatesDescriptors, - DateRangesPropertiesTester.testDisabledDates, - ); + DateRangesPropertiesTester.testBetweenWithMinDateFirst(DateRangesPropertiesTester.assignDisableDatesDescriptors, DateRangesPropertiesTester.testDisabledDates); }); it('Should disable date when using "Between" date descriptor with max date declared first.', () => { - DateRangesPropertiesTester.testBetweenWithMaxDateFirst( - DateRangesPropertiesTester.assignDisableDatesDescriptors, - DateRangesPropertiesTester.testDisabledDates, - ); + DateRangesPropertiesTester.testBetweenWithMaxDateFirst(DateRangesPropertiesTester.assignDisableDatesDescriptors, DateRangesPropertiesTester.testDisabledDates); }); it('Should disable date when using "Between" date descriptor with min and max the same.', () => { - DateRangesPropertiesTester.testBetweenWithMinMaxTheSame( - DateRangesPropertiesTester.assignDisableDatesDescriptors, - DateRangesPropertiesTester.testDisabledDates, - ); + DateRangesPropertiesTester.testBetweenWithMinMaxTheSame(DateRangesPropertiesTester.assignDisableDatesDescriptors, DateRangesPropertiesTester.testDisabledDates); }); it('Should disable date when using overlapping "Between" ranges.', () => { - DateRangesPropertiesTester.testOverlappingBetweens( - DateRangesPropertiesTester.assignDisableDatesDescriptors, - DateRangesPropertiesTester.testDisabledDates, - ); + DateRangesPropertiesTester.testOverlappingBetweens(DateRangesPropertiesTester.assignDisableDatesDescriptors, DateRangesPropertiesTester.testDisabledDates); }); it('Should disable date when using "Specific" date descriptor.', () => { - DateRangesPropertiesTester.testSpecific( - DateRangesPropertiesTester.assignDisableDatesDescriptors, - DateRangesPropertiesTester.testDisabledDates, - ); + DateRangesPropertiesTester.testSpecific(DateRangesPropertiesTester.assignDisableDatesDescriptors, DateRangesPropertiesTester.testDisabledDates); }); it('Should disable date when using "Weekdays" date descriptor.', () => { - DateRangesPropertiesTester.testWeekdays( - DateRangesPropertiesTester.assignDisableDatesDescriptors, - DateRangesPropertiesTester.testDisabledDates, - ); + DateRangesPropertiesTester.testWeekdays(DateRangesPropertiesTester.assignDisableDatesDescriptors, DateRangesPropertiesTester.testDisabledDates); }); it('Should disable date when using "Weekends" date descriptor.', () => { - DateRangesPropertiesTester.testWeekends( - DateRangesPropertiesTester.assignDisableDatesDescriptors, - DateRangesPropertiesTester.testDisabledDates, - ); + DateRangesPropertiesTester.testWeekends(DateRangesPropertiesTester.assignDisableDatesDescriptors, DateRangesPropertiesTester.testDisabledDates); }); it("Should disable dates when using multiple ranges.", () => { - DateRangesPropertiesTester.testMultipleRanges( - DateRangesPropertiesTester.assignDisableDatesDescriptors, - DateRangesPropertiesTester.testDisabledDates, - ); + DateRangesPropertiesTester.testMultipleRanges(DateRangesPropertiesTester.assignDisableDatesDescriptors, DateRangesPropertiesTester.testDisabledDates); }); it("Should be able to change disable dates runtime.", () => { - DateRangesPropertiesTester.testRangeUpdateRuntime( - DateRangesPropertiesTester.assignDisableDatesDescriptors, - DateRangesPropertiesTester.testDisabledDates, - ); + DateRangesPropertiesTester.testRangeUpdateRuntime(DateRangesPropertiesTester.assignDisableDatesDescriptors, DateRangesPropertiesTester.testDisabledDates); }); it('Should disable previous month with "before" date descriptor', () => { - DateRangesPropertiesTester.testPreviousMonthRange( - DateRangesPropertiesTester.assignDisableDatesDescriptors, - DateRangesPropertiesTester.testDisabledDates, - ); + DateRangesPropertiesTester.testPreviousMonthRange(DateRangesPropertiesTester.assignDisableDatesDescriptors, DateRangesPropertiesTester.testDisabledDates); }); }); describe("Special dates - ", () => { it('Should mark date as special when using "After" date descriptor.', () => { - DateRangesPropertiesTester.testAfter( - DateRangesPropertiesTester.assignSpecialDatesDescriptors, - DateRangesPropertiesTester.testSpecialDates, - ); + DateRangesPropertiesTester.testAfter(DateRangesPropertiesTester.assignSpecialDatesDescriptors, DateRangesPropertiesTester.testSpecialDates); }); it('Should mark date as special when using "Before" date descriptor.', () => { - DateRangesPropertiesTester.testBefore( - DateRangesPropertiesTester.assignSpecialDatesDescriptors, - DateRangesPropertiesTester.testSpecialDates, - ); + DateRangesPropertiesTester.testBefore(DateRangesPropertiesTester.assignSpecialDatesDescriptors, DateRangesPropertiesTester.testSpecialDates); }); it('Should mark date as special when using "Between" date descriptor with min date declared first.', () => { - DateRangesPropertiesTester.testBetweenWithMinDateFirst( - DateRangesPropertiesTester.assignSpecialDatesDescriptors, - DateRangesPropertiesTester.testSpecialDates, - ); + DateRangesPropertiesTester.testBetweenWithMinDateFirst(DateRangesPropertiesTester.assignSpecialDatesDescriptors, DateRangesPropertiesTester.testSpecialDates); }); it('Should mark date as special when using "Between" date descriptor with max date declared first.', () => { - DateRangesPropertiesTester.testBetweenWithMaxDateFirst( - DateRangesPropertiesTester.assignSpecialDatesDescriptors, - DateRangesPropertiesTester.testSpecialDates, - ); + DateRangesPropertiesTester.testBetweenWithMaxDateFirst(DateRangesPropertiesTester.assignSpecialDatesDescriptors, DateRangesPropertiesTester.testSpecialDates); }); it('Should mark date as special when using "Between" date descriptor with min and max the same.', () => { - DateRangesPropertiesTester.testBetweenWithMinMaxTheSame( - DateRangesPropertiesTester.assignSpecialDatesDescriptors, - DateRangesPropertiesTester.testSpecialDates, - ); + DateRangesPropertiesTester.testBetweenWithMinMaxTheSame(DateRangesPropertiesTester.assignSpecialDatesDescriptors, DateRangesPropertiesTester.testSpecialDates); }); it('Should mark date as special when using overlapping "Between" ranges.', () => { - DateRangesPropertiesTester.testOverlappingBetweens( - DateRangesPropertiesTester.assignSpecialDatesDescriptors, - DateRangesPropertiesTester.testSpecialDates, - ); + DateRangesPropertiesTester.testOverlappingBetweens(DateRangesPropertiesTester.assignSpecialDatesDescriptors, DateRangesPropertiesTester.testSpecialDates); }); it('Should mark date as special when using "Specific" date descriptor.', () => { - DateRangesPropertiesTester.testSpecific( - DateRangesPropertiesTester.assignSpecialDatesDescriptors, - DateRangesPropertiesTester.testSpecialDates, - ); + DateRangesPropertiesTester.testSpecific(DateRangesPropertiesTester.assignSpecialDatesDescriptors, DateRangesPropertiesTester.testSpecialDates); }); it('Should mark date as special when using "Weekdays" date descriptor.', () => { - DateRangesPropertiesTester.testWeekdays( - DateRangesPropertiesTester.assignSpecialDatesDescriptors, - DateRangesPropertiesTester.testSpecialDates, - ); + DateRangesPropertiesTester.testWeekdays(DateRangesPropertiesTester.assignSpecialDatesDescriptors, DateRangesPropertiesTester.testSpecialDates); }); it('Should mark date as special when using "Weekends" date descriptor.', () => { - DateRangesPropertiesTester.testWeekends( - DateRangesPropertiesTester.assignSpecialDatesDescriptors, - DateRangesPropertiesTester.testSpecialDates, - ); + DateRangesPropertiesTester.testWeekends(DateRangesPropertiesTester.assignSpecialDatesDescriptors, DateRangesPropertiesTester.testSpecialDates); }); it("Should mark dates as special when using multiple ranges.", () => { - DateRangesPropertiesTester.testMultipleRanges( - DateRangesPropertiesTester.assignSpecialDatesDescriptors, - DateRangesPropertiesTester.testSpecialDates, - ); + DateRangesPropertiesTester.testMultipleRanges(DateRangesPropertiesTester.assignSpecialDatesDescriptors, DateRangesPropertiesTester.testSpecialDates); }); it('Should mark as special previous month with "before" date descriptor', () => { - DateRangesPropertiesTester.testPreviousMonthRange( - DateRangesPropertiesTester.assignSpecialDatesDescriptors, - DateRangesPropertiesTester.testSpecialDates, - ); + DateRangesPropertiesTester.testPreviousMonthRange(DateRangesPropertiesTester.assignSpecialDatesDescriptors, DateRangesPropertiesTester.testSpecialDates); }); it("Should be able to change special dates runtime.", () => { - DateRangesPropertiesTester.testRangeUpdateRuntime( - DateRangesPropertiesTester.assignSpecialDatesDescriptors, - DateRangesPropertiesTester.testSpecialDates, - ); + DateRangesPropertiesTester.testRangeUpdateRuntime(DateRangesPropertiesTester.assignSpecialDatesDescriptors, DateRangesPropertiesTester.testSpecialDates); }); }); describe("Disabled special dates - ", () => { beforeEach(waitForAsync(() => { - fixture = TestBed.createComponent( - IgxCalendarDisabledSpecialDatesComponent, - ); + fixture = TestBed.createComponent(IgxCalendarDisabledSpecialDatesComponent); fixture.detectChanges(); calendar = fixture.componentInstance.calendar; })); @@ -1688,12 +1145,10 @@ describe("IgxCalendar - ", () => { let specialDates = calendar.daysView.dates .toArray() .filter((d) => { - const dateTime = getDate(d).getTime(); - return ( - dateTime >= new Date(2017, 5, 1).getTime() && - dateTime <= new Date(2017, 5, 6).getTime() - ); - }); + const dateTime = getDate(d).getTime(); + return (dateTime >= new Date(2017, 5, 1).getTime() && + dateTime <= new Date(2017, 5, 6).getTime()); + }); specialDates.forEach((d) => { expect(d.isSpecial).toBe(true); @@ -1702,12 +1157,10 @@ describe("IgxCalendar - ", () => { let disabledDates = calendar.daysView.dates .toArray() .filter((d) => { - const dateTime = getDate(d).getTime(); - return ( - dateTime >= new Date(2017, 5, 23).getTime() && - dateTime <= new Date(2017, 5, 29).getTime() - ); - }); + const dateTime = getDate(d).getTime(); + return (dateTime >= new Date(2017, 5, 23).getTime() && + dateTime <= new Date(2017, 5, 29).getTime()); + }); disabledDates.forEach((d) => { expect(d.isDisabled).toBe(true); @@ -1756,9 +1209,9 @@ describe("IgxCalendar - ", () => { disabledDates = calendar.daysView.dates .toArray() .filter((d) => { - const dateTime = getDate(d).getTime(); - return dateTime <= new Date(2017, 5, 9).getTime(); - }); + const dateTime = getDate(d).getTime(); + return dateTime <= new Date(2017, 5, 9).getTime(); + }); disabledDates.forEach((d) => { expect(d.isDisabled).toBe(true); @@ -1858,10 +1311,7 @@ describe("IgxCalendar - ", () => { expect(selectedDates.length).toBe(5); for (const selectedDate of selectedDates) { - const fdate = oddDates.some( - (date: Date) => - date.getTime() === selectedDate.getTime(), - ); + const fdate = oddDates.some((date: Date) => date.getTime() === selectedDate.getTime()); expect(fdate).toBeTruthy(); } @@ -1871,10 +1321,7 @@ describe("IgxCalendar - ", () => { selectedDates = calendar.value as Date[]; expect(selectedDates.length).toBe(5); for (const selectedDate of selectedDates) { - const fdate = oddDates.some( - (date: Date) => - date.getTime() === selectedDate.getTime(), - ); + const fdate = oddDates.some((date: Date) => date.getTime() === selectedDate.getTime()); expect(fdate).toBeTruthy(); } @@ -1884,10 +1331,7 @@ describe("IgxCalendar - ", () => { selectedDates = calendar.value as Date[]; expect(selectedDates.length).toBe(4); for (const selectedDate of selectedDates) { - const fdate = oddDates.some( - (date: Date) => - date.getTime() === selectedDate.getTime(), - ); + const fdate = oddDates.some((date: Date) => date.getTime() === selectedDate.getTime()); expect(fdate).toBeTruthy(); } @@ -2127,9 +1571,7 @@ describe("IgxCalendar - ", () => { calendar.selection = "range"; fixture.detectChanges(); - const days = calendar.daysView.dates.filter( - (day) => day.isCurrentMonth, - ); + const days = calendar.daysView.dates.filter((day) => day.isCurrentMonth); const june11th = days[10]; const june13th = days[12]; const june15th = days[14]; @@ -2144,12 +1586,8 @@ describe("IgxCalendar - ", () => { calendarValue = calendar.value as Date[]; expect(calendarValue.length).toEqual(3); - expect(calendarValue[0].toDateString()).toMatch( - new Date(2017, 5, 13).toDateString(), - ); - expect( - calendarValue[calendarValue.length - 1].toDateString(), - ).toMatch(new Date(2017, 5, 15).toDateString()); + expect(calendarValue[0].toDateString()).toMatch(new Date(2017, 5, 13).toDateString()); + expect(calendarValue[calendarValue.length - 1].toDateString()).toMatch(new Date(2017, 5, 15).toDateString()); // extend the range to June 17th (June 13th - June 17th) UIInteractions.simulateClickAndSelectEvent(june17th.nativeElement.firstChild, true); @@ -2157,9 +1595,7 @@ describe("IgxCalendar - ", () => { calendarValue = calendar.value as Date[]; expect(calendarValue.length).toEqual(5); - expect( - calendarValue[calendarValue.length - 1].toDateString(), - ).toMatch(new Date(2017, 5, 17).toDateString()); + expect(calendarValue[calendarValue.length - 1].toDateString()).toMatch(new Date(2017, 5, 17).toDateString()); // extend the range to June 11th (June 11th - June 17th) UIInteractions.simulateClickAndSelectEvent(june11th.nativeElement.firstChild, true); @@ -2167,18 +1603,14 @@ describe("IgxCalendar - ", () => { calendarValue = calendar.value as Date[]; expect(calendarValue.length).toEqual(7); - expect(calendarValue[0].toDateString()).toMatch( - new Date(2017, 5, 11).toDateString(), - ); + expect(calendarValue[0].toDateString()).toMatch(new Date(2017, 5, 11).toDateString()); }); it("Should shorten the range when selecting a date inside of it with shift click.", () => { calendar.selection = "range"; fixture.detectChanges(); - const days = calendar.daysView.dates.filter( - (day) => day.isCurrentMonth, - ); + const days = calendar.daysView.dates.filter((day) => day.isCurrentMonth); const june11th = days[10]; const june13th = days[12]; const june15th = days[14]; @@ -2193,12 +1625,8 @@ describe("IgxCalendar - ", () => { calendarValue = calendar.value as Date[]; expect(calendarValue.length).toEqual(5); - expect(calendarValue[0].toDateString()).toMatch( - new Date(2017, 5, 13).toDateString(), - ); - expect( - calendarValue[calendarValue.length - 1].toDateString(), - ).toMatch(new Date(2017, 5, 17).toDateString()); + expect(calendarValue[0].toDateString()).toMatch(new Date(2017, 5, 13).toDateString()); + expect(calendarValue[calendarValue.length - 1].toDateString()).toMatch(new Date(2017, 5, 17).toDateString()); // shorten the range to June 15th (June 13th - June 15th) UIInteractions.simulateClickAndSelectEvent(june15th.nativeElement.firstChild, true); @@ -2206,9 +1634,7 @@ describe("IgxCalendar - ", () => { calendarValue = calendar.value as Date[]; expect(calendarValue.length).toEqual(3); - expect( - calendarValue[calendarValue.length - 1].toDateString(), - ).toMatch(new Date(2017, 5, 15).toDateString()); + expect(calendarValue[calendarValue.length - 1].toDateString()).toMatch(new Date(2017, 5, 15).toDateString()); // extend the range to June 11th (June 11th - June 15th) UIInteractions.simulateClickAndSelectEvent(june11th.nativeElement.firstChild, true); @@ -2216,12 +1642,8 @@ describe("IgxCalendar - ", () => { calendarValue = calendar.value as Date[]; expect(calendarValue.length).toEqual(5); - expect(calendarValue[0].toDateString()).toMatch( - new Date(2017, 5, 11).toDateString(), - ); - expect( - calendarValue[calendarValue.length - 1].toDateString(), - ).toMatch(new Date(2017, 5, 15).toDateString()); + expect(calendarValue[0].toDateString()).toMatch(new Date(2017, 5, 11).toDateString()); + expect(calendarValue[calendarValue.length - 1].toDateString()).toMatch(new Date(2017, 5, 15).toDateString()); // shorten the range to June 13th (June 13th - June 15th) UIInteractions.simulateClickAndSelectEvent(june13th.nativeElement.firstChild, true); @@ -2229,18 +1651,14 @@ describe("IgxCalendar - ", () => { calendarValue = calendar.value as Date[]; expect(calendarValue.length).toEqual(3); - expect(calendarValue[0].toDateString()).toMatch( - new Date(2017, 5, 13).toDateString(), - ); + expect(calendarValue[0].toDateString()).toMatch(new Date(2017, 5, 13).toDateString()); }); it('Should select all dates from last selected to shift clicked date in "multi" mode.', () => { calendar.selection = "multi"; fixture.detectChanges(); - const days = calendar.daysView.dates.filter( - (day) => day.isCurrentMonth, - ); + const days = calendar.daysView.dates.filter((day) => day.isCurrentMonth); const june11th = days[10]; const june13th = days[12]; const june15th = days[14]; @@ -2264,9 +1682,7 @@ describe("IgxCalendar - ", () => { new Date(2017, 5, 17), ]; - expect(JSON.stringify(calendar.value as Date[])).toEqual( - JSON.stringify(expected), - ); + expect(JSON.stringify(calendar.value as Date[])).toEqual(JSON.stringify(expected)); // select all dates from June 17th (last selected) to June 11th UIInteractions.simulateClickAndSelectEvent(june11th.nativeElement.firstChild, true); @@ -2281,18 +1697,14 @@ describe("IgxCalendar - ", () => { expected.push(new Date(year, month, i)); } - expect(JSON.stringify(calendar.value as Date[])).toEqual( - JSON.stringify(expected), - ); + expect(JSON.stringify(calendar.value as Date[])).toEqual(JSON.stringify(expected)); }); it('Should deselect all dates from last clicked to shift clicked date in "multi" mode.', () => { calendar.selection = "multi"; fixture.detectChanges(); - const days = calendar.daysView.dates.filter( - (day) => day.isCurrentMonth, - ); + const days = calendar.daysView.dates.filter((day) => day.isCurrentMonth); const june11th = days[10]; const june13th = days[12]; const june15th = days[14]; @@ -2315,18 +1727,14 @@ describe("IgxCalendar - ", () => { UIInteractions.simulateClickAndSelectEvent(june13th.nativeElement.firstChild, true); fixture.detectChanges(); expect((calendar.value as Date[]).length).toEqual(5); - expect(JSON.stringify(calendar.value as Date[])).toEqual( - JSON.stringify(dates.slice(2)), - ); + expect(JSON.stringify(calendar.value as Date[])).toEqual(JSON.stringify(dates.slice(2))); // deselect all dates from June 17th (last clicked) to June 15th UIInteractions.simulateClickAndSelectEvent(june17th.nativeElement.firstChild); UIInteractions.simulateClickAndSelectEvent(june15th.nativeElement.firstChild, true); fixture.detectChanges(); expect((calendar.value as Date[]).length).toEqual(3); - expect(JSON.stringify(calendar.value as Date[])).toEqual( - JSON.stringify(dates.slice(2, 5)), - ); + expect(JSON.stringify(calendar.value as Date[])).toEqual(JSON.stringify(dates.slice(2, 5))); }); }); @@ -2339,37 +1747,24 @@ describe("IgxCalendar - ", () => { })); it("Should navigate to the previous/next month via KB.", fakeAsync(() => { - const prev = dom.queryAll( - By.css(HelperTestFunctions.CALENDAR_PREV_BUTTON_CSSCLASS), - )[0]; + const prev = dom.queryAll(By.css(HelperTestFunctions.CALENDAR_PREV_BUTTON_CSSCLASS))[0]; prev.nativeElement.focus(); expect(prev.nativeElement).toBe(document.activeElement); - UIInteractions.triggerKeyDownEvtUponElem( - "Enter", - prev.nativeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("Enter", prev.nativeElement); fixture.detectChanges(); tick(100); expect(calendar.viewDate.getMonth()).toEqual(4); - const next = dom.queryAll( - By.css(HelperTestFunctions.CALENDAR_NEXT_BUTTON_CSSCLASS), - )[0]; + const next = dom.queryAll(By.css(HelperTestFunctions.CALENDAR_NEXT_BUTTON_CSSCLASS))[0]; next.nativeElement.focus(); expect(next.nativeElement).toBe(document.activeElement); - UIInteractions.triggerKeyDownEvtUponElem( - "Enter", - next.nativeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("Enter", next.nativeElement); fixture.detectChanges(); tick(100); - UIInteractions.triggerKeyDownEvtUponElem( - "Enter", - next.nativeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("Enter", next.nativeElement); tick(100); fixture.detectChanges(); @@ -2377,80 +1772,44 @@ describe("IgxCalendar - ", () => { })); it("Should open years view, navigate through and select an year via KB.", fakeAsync(() => { - const year = dom.queryAll( - By.css(HelperTestFunctions.CALENDAR_DATE_CSSCLASS), - )[1]; + const year = dom.queryAll(By.css(HelperTestFunctions.CALENDAR_DATE_CSSCLASS))[1]; year.nativeElement.focus(); expect(year.nativeElement).toBe(document.activeElement); - spyOn(calendar.activeViewChanged, "emit").and.callThrough(); + vi.spyOn(calendar.activeViewChanged, "emit"); - UIInteractions.triggerKeyDownEvtUponElem( - "Enter", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("Enter", document.activeElement); fixture.detectChanges(); tick(); - expect(calendar.activeViewChanged.emit).toHaveBeenCalledTimes( - 1, - ); - expect(calendar.activeViewChanged.emit).toHaveBeenCalledWith( - IgxCalendarView.Decade, - ); + expect(calendar.activeViewChanged.emit).toHaveBeenCalledTimes(1); + expect(calendar.activeViewChanged.emit).toHaveBeenCalledWith(IgxCalendarView.Decade); - const years = dom.queryAll( - By.css(HelperTestFunctions.YEAR_CSSCLASS), - ); - let currentYear = dom.query( - By.css(HelperTestFunctions.CURRENT_YEAR_CSSCLASS), - ); + const years = dom.queryAll(By.css(HelperTestFunctions.YEAR_CSSCLASS)); + let currentYear = dom.query(By.css(HelperTestFunctions.CURRENT_YEAR_CSSCLASS)); expect(years.length).toEqual(15); - expect(currentYear.nativeElement.textContent.trim()).toMatch( - "2017", - ); - - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowRight", - document.activeElement, - ); - fixture.detectChanges(); - - currentYear = dom.query( - By.css(HelperTestFunctions.CURRENT_YEAR_CSSCLASS), - ); - expect(currentYear.nativeElement.textContent.trim()).toMatch( - "2018", - ); - - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowLeft", - document.activeElement, - ); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowLeft", - document.activeElement, - ); - fixture.detectChanges(); - - currentYear = dom.query( - By.css(HelperTestFunctions.CURRENT_YEAR_CSSCLASS), - ); - expect(currentYear.nativeElement.textContent.trim()).toMatch( - "2016", - ); - - const previousValue = - fixture.componentInstance.calendar.viewDate; - spyOn(calendar.viewDateChanged, "emit").and.callThrough(); + expect(currentYear.nativeElement.textContent.trim()).toMatch("2017"); + + UIInteractions.triggerKeyDownEvtUponElem("ArrowRight", document.activeElement); + fixture.detectChanges(); + + currentYear = dom.query(By.css(HelperTestFunctions.CURRENT_YEAR_CSSCLASS)); + expect(currentYear.nativeElement.textContent.trim()).toMatch("2018"); + + UIInteractions.triggerKeyDownEvtUponElem("ArrowLeft", document.activeElement); + UIInteractions.triggerKeyDownEvtUponElem("ArrowLeft", document.activeElement); + fixture.detectChanges(); + + currentYear = dom.query(By.css(HelperTestFunctions.CURRENT_YEAR_CSSCLASS)); + expect(currentYear.nativeElement.textContent.trim()).toMatch("2016"); + + const previousValue = fixture.componentInstance.calendar.viewDate; + vi.spyOn(calendar.viewDateChanged, "emit"); // Should open the year view - UIInteractions.triggerKeyDownEvtUponElem( - "Enter", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("Enter", document.activeElement); fixture.detectChanges(); tick(); @@ -2460,97 +1819,55 @@ describe("IgxCalendar - ", () => { currentValue: fixture.componentInstance.calendar.viewDate, }; expect(calendar.viewDateChanged.emit).toHaveBeenCalledTimes(1); - expect(calendar.viewDateChanged.emit).toHaveBeenCalledWith( - eventArgs, - ); + expect(calendar.viewDateChanged.emit).toHaveBeenCalledWith(eventArgs); expect(calendar.viewDate.getFullYear()).toEqual(2016); })); it("Should open months view, navigate through and select a month via KB.", fakeAsync(() => { - const month = dom.queryAll( - By.css(HelperTestFunctions.CALENDAR_DATE_CSSCLASS), - )[0]; + const month = dom.queryAll(By.css(HelperTestFunctions.CALENDAR_DATE_CSSCLASS))[0]; month.nativeElement.focus(); - spyOn(calendar.activeViewChanged, "emit").and.callThrough(); + vi.spyOn(calendar.activeViewChanged, "emit"); expect(month.nativeElement).toBe(document.activeElement); - UIInteractions.triggerKeyDownEvtUponElem( - "Enter", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("Enter", document.activeElement); fixture.detectChanges(); tick(); - expect(calendar.activeViewChanged.emit).toHaveBeenCalledTimes( - 1, - ); - expect(calendar.activeViewChanged.emit).toHaveBeenCalledWith( - IgxCalendarView.Year, - ); + expect(calendar.activeViewChanged.emit).toHaveBeenCalledTimes(1); + expect(calendar.activeViewChanged.emit).toHaveBeenCalledWith(IgxCalendarView.Year); - const months = dom.queryAll( - By.css(HelperTestFunctions.MONTH_CSSCLASS), - ); - const currentMonth = dom.query( - By.css(HelperTestFunctions.CURRENT_MONTH_CSSCLASS), - ); + const months = dom.queryAll(By.css(HelperTestFunctions.MONTH_CSSCLASS)); + const currentMonth = dom.query(By.css(HelperTestFunctions.CURRENT_MONTH_CSSCLASS)); expect(months.length).toEqual(12); - expect(currentMonth.nativeElement.textContent.trim()).toMatch( - "June", - ); + expect(currentMonth.nativeElement.textContent.trim()).toMatch("June"); - UIInteractions.triggerKeyDownEvtUponElem( - "Home", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("Home", document.activeElement); fixture.detectChanges(); - expect(document.activeElement.textContent.trim()).toMatch( - "January", - ); + expect(document.activeElement.textContent.trim()).toMatch("January"); - UIInteractions.triggerKeyDownEvtUponElem( - "End", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("End", document.activeElement); fixture.detectChanges(); - expect(document.activeElement.textContent.trim()).toMatch( - "December", - ); + expect(document.activeElement.textContent.trim()).toMatch("December"); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowLeft", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowLeft", document.activeElement); fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowUp", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowUp", document.activeElement); fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowRight", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowRight", document.activeElement); fixture.detectChanges(); - expect(document.activeElement.textContent.trim()).toMatch( - "September", - ); + expect(document.activeElement.textContent.trim()).toMatch("September"); - const previousValue = - fixture.componentInstance.calendar.viewDate; - spyOn(calendar.viewDateChanged, "emit").and.callThrough(); + const previousValue = fixture.componentInstance.calendar.viewDate; + vi.spyOn(calendar.viewDateChanged, "emit"); - UIInteractions.triggerKeyDownEvtUponElem( - "Enter", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("Enter", document.activeElement); fixture.detectChanges(); tick(); @@ -2560,9 +1877,7 @@ describe("IgxCalendar - ", () => { currentValue: fixture.componentInstance.calendar.viewDate, }; expect(calendar.viewDateChanged.emit).toHaveBeenCalledTimes(1); - expect(calendar.viewDateChanged.emit).toHaveBeenCalledWith( - eventArgs, - ); + expect(calendar.viewDateChanged.emit).toHaveBeenCalledWith(eventArgs); expect(calendar.viewDate.getMonth()).toEqual(8); })); @@ -2581,36 +1896,22 @@ describe("IgxCalendar - ", () => { calendar.disabledDates = dateRangeDescriptors; fixture.detectChanges(); - const calendarNativeElement = dom.query( - By.css(HelperTestFunctions.CALENDAR_WRAPPER_CLASS), - ).nativeElement; + const calendarNativeElement = dom.query(By.css(HelperTestFunctions.CALENDAR_WRAPPER_CLASS)).nativeElement; calendarNativeElement.focus(); - UIInteractions.triggerKeyDownEvtUponElem( - "Home", - calendarNativeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("Home", calendarNativeElement); fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowUp", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowUp", document.activeElement); fixture.detectChanges(); let date = new Date(2017, 4, 18); expect(calendar.activeDate).toEqual(date); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowUp", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowUp", document.activeElement); fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowUp", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowUp", document.activeElement); fixture.detectChanges(); date = new Date(2017, 3, 27); @@ -2632,55 +1933,26 @@ describe("IgxCalendar - ", () => { calendar.disabledDates = dateRangeDescriptors; fixture.detectChanges(); - const calendarNativeElement = dom.query( - By.css(HelperTestFunctions.CALENDAR_WRAPPER_CLASS), - ).nativeElement; + const calendarNativeElement = dom.query(By.css(HelperTestFunctions.CALENDAR_WRAPPER_CLASS)).nativeElement; calendarNativeElement.focus(); - UIInteractions.triggerKeyDownEvtUponElem( - "Home", - calendarNativeElement, - ); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowLeft", - document.activeElement, - ); - fixture.detectChanges(); - - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowLeft", - document.activeElement, - ); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowLeft", - document.activeElement, - ); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowLeft", - document.activeElement, - ); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowLeft", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("Home", calendarNativeElement); + UIInteractions.triggerKeyDownEvtUponElem("ArrowLeft", document.activeElement); + fixture.detectChanges(); + + UIInteractions.triggerKeyDownEvtUponElem("ArrowLeft", document.activeElement); + UIInteractions.triggerKeyDownEvtUponElem("ArrowLeft", document.activeElement); + UIInteractions.triggerKeyDownEvtUponElem("ArrowLeft", document.activeElement); + UIInteractions.triggerKeyDownEvtUponElem("ArrowLeft", document.activeElement); fixture.detectChanges(); let date = new Date(2017, 4, 26); expect(calendar.activeDate).toEqual(date); - UIInteractions.triggerKeyDownEvtUponElem( - "Home", - calendarNativeElement, - ); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowLeft", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("Home", calendarNativeElement); + UIInteractions.triggerKeyDownEvtUponElem("ArrowLeft", document.activeElement); fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowLeft", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowLeft", document.activeElement); fixture.detectChanges(); date = new Date(2017, 3, 29); @@ -2702,38 +1974,21 @@ describe("IgxCalendar - ", () => { calendar.disabledDates = dateRangeDescriptors; fixture.detectChanges(); - const calendarNativeElement = dom.query( - By.css(HelperTestFunctions.CALENDAR_WRAPPER_CLASS), - ).nativeElement; + const calendarNativeElement = dom.query(By.css(HelperTestFunctions.CALENDAR_WRAPPER_CLASS)).nativeElement; calendarNativeElement.focus(); - UIInteractions.triggerKeyDownEvtUponElem( - "End", - calendarNativeElement, - ); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowDown", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("End", calendarNativeElement); + UIInteractions.triggerKeyDownEvtUponElem("ArrowDown", document.activeElement); fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowDown", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowDown", document.activeElement); fixture.detectChanges(); let date = new Date(2017, 6, 21); expect(calendar.activeDate).toEqual(date); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowDown", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowDown", document.activeElement); fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowDown", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowDown", document.activeElement); fixture.detectChanges(); date = new Date(2017, 7, 11); @@ -2754,38 +2009,21 @@ describe("IgxCalendar - ", () => { calendar.disabledDates = dateRangeDescriptors; - const calendarNativeElement = dom.query( - By.css(HelperTestFunctions.CALENDAR_WRAPPER_CLASS), - ).nativeElement; + const calendarNativeElement = dom.query(By.css(HelperTestFunctions.CALENDAR_WRAPPER_CLASS)).nativeElement; calendarNativeElement.focus(); - UIInteractions.triggerKeyDownEvtUponElem( - "End", - calendarNativeElement, - ); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowDown", - document.activeElement, - ); - fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowRight", - document.activeElement, - ); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowRight", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("End", calendarNativeElement); + UIInteractions.triggerKeyDownEvtUponElem("ArrowDown", document.activeElement); + fixture.detectChanges(); + UIInteractions.triggerKeyDownEvtUponElem("ArrowRight", document.activeElement); + UIInteractions.triggerKeyDownEvtUponElem("ArrowRight", document.activeElement); fixture.detectChanges(); let date = new Date(2017, 6, 11); expect(calendar.activeDate).toEqual(date); calendar.activeDate = new Date(2017, 7, 5); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowRight", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowRight", document.activeElement); fixture.detectChanges(); date = new Date(2017, 7, 6); @@ -2793,56 +2031,33 @@ describe("IgxCalendar - ", () => { }); it("Should preserve the active date on (shift) pageup and pagedown.", () => { - const calendarNativeElement = dom.query( - By.css(HelperTestFunctions.CALENDAR_WRAPPER_CLASS), - ).nativeElement; + const calendarNativeElement = dom.query(By.css(HelperTestFunctions.CALENDAR_WRAPPER_CLASS)).nativeElement; calendarNativeElement.focus(); - UIInteractions.triggerKeyDownEvtUponElem( - "Home", - calendarNativeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("Home", calendarNativeElement); let date = new Date(2017, 5, 1); expect(calendar.activeDate).toEqual(date); - UIInteractions.triggerKeyDownEvtUponElem( - "PageUp", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("PageUp", document.activeElement); fixture.detectChanges(); date = new Date(2017, 4, 1); expect(calendar.activeDate).toEqual(date); - UIInteractions.triggerKeyDownEvtUponElem( - "PageDown", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("PageDown", document.activeElement); fixture.detectChanges(); date = new Date(2017, 5, 1); expect(calendar.activeDate).toEqual(date); - UIInteractions.triggerKeyDownEvtUponElem( - "PageUp", - document.activeElement, - true, - false, - true, - ); + UIInteractions.triggerKeyDownEvtUponElem("PageUp", document.activeElement, true, false, true); fixture.detectChanges(); date = new Date(2016, 5, 1); expect(calendar.activeDate).toEqual(date); - UIInteractions.triggerKeyDownEvtUponElem( - "PageDown", - document.activeElement, - true, - false, - true, - ); + UIInteractions.triggerKeyDownEvtUponElem("PageDown", document.activeElement, true, false, true); fixture.detectChanges(); date = new Date(2017, 5, 1); @@ -2866,47 +2081,23 @@ describe("IgxCalendar - ", () => { dom = fixture.debugElement; calendar = fixture.componentInstance.calendar; - prevMonthBtn = dom.queryAll( - By.css(HelperTestFunctions.CALENDAR_PREV_BUTTON_CSSCLASS), - )[0].nativeElement; - nextMonthBtn = dom.queryAll( - By.css(HelperTestFunctions.CALENDAR_NEXT_BUTTON_CSSCLASS), - )[0].nativeElement; + prevMonthBtn = dom.queryAll(By.css(HelperTestFunctions.CALENDAR_PREV_BUTTON_CSSCLASS))[0].nativeElement; + nextMonthBtn = dom.queryAll(By.css(HelperTestFunctions.CALENDAR_NEXT_BUTTON_CSSCLASS))[0].nativeElement; })); it("Should increment/decrement months continuously on mousedown.", fakeAsync(() => { expect(calendar.viewDate.getMonth()).toEqual(5); // Have no idea how this test worked before, // changing expectation based on my udnerstanding of that the test does - UIInteractions.simulateMouseEvent( - "mousedown", - prevMonthBtn, - 0, - 0, - ); + UIInteractions.simulateMouseEvent("mousedown", prevMonthBtn, 0, 0); tick(); - UIInteractions.simulateMouseEvent( - "mouseup", - prevMonthBtn, - 0, - 0, - ); + UIInteractions.simulateMouseEvent("mouseup", prevMonthBtn, 0, 0); fixture.detectChanges(); expect(calendar.viewDate.getMonth()).toEqual(4); - UIInteractions.simulateMouseEvent( - "mousedown", - nextMonthBtn, - 0, - 0, - ); + UIInteractions.simulateMouseEvent("mousedown", nextMonthBtn, 0, 0); tick(); - UIInteractions.simulateMouseEvent( - "mouseup", - nextMonthBtn, - 0, - 0, - ); + UIInteractions.simulateMouseEvent("mouseup", nextMonthBtn, 0, 0); fixture.detectChanges(); flush(); expect(calendar.viewDate.getMonth()).toEqual(5); @@ -2948,7 +2139,7 @@ describe("IgxCalendar - ", () => { try { calendar.locale = "frrr"; fixture.detectChanges(); - } catch(err) { + } catch (err) { errorThrown = err; } @@ -2972,50 +2163,22 @@ describe("IgxCalendar - ", () => { year: "numeric", }; const defaultViews = { day: false, month: true, year: false }; - const bodyMonth = dom.query( - By.css(HelperTestFunctions.CALENDAR_DATE_CSSCLASS), - ); - const headerYear = dom.query( - By.css(HelperTestFunctions.CALENDAR_HEADER_YEAR_CSSCLASS), - ); - const bodyYear = dom.queryAll( - By.css(HelperTestFunctions.CALENDAR_DATE_CSSCLASS), - )[1]; - const headerWeekday = dom.queryAll( - By.css( - `${HelperTestFunctions.CALENDAR_HEADER_DATE_CSSCLASS} span`, - ), - )[0]; - const headerDate = dom.queryAll( - By.css( - `${HelperTestFunctions.CALENDAR_HEADER_DATE_CSSCLASS} span`, - ), - )[1]; + const bodyMonth = dom.query(By.css(HelperTestFunctions.CALENDAR_DATE_CSSCLASS)); + const headerYear = dom.query(By.css(HelperTestFunctions.CALENDAR_HEADER_YEAR_CSSCLASS)); + const bodyYear = dom.queryAll(By.css(HelperTestFunctions.CALENDAR_DATE_CSSCLASS))[1]; + const headerWeekday = dom.queryAll(By.css(`${HelperTestFunctions.CALENDAR_HEADER_DATE_CSSCLASS} span`))[0]; + const headerDate = dom.queryAll(By.css(`${HelperTestFunctions.CALENDAR_HEADER_DATE_CSSCLASS} span`))[1]; calendar.selectDate(calendar.viewDate); fixture.detectChanges(); - expect(calendar.formatOptions).toEqual( - jasmine.objectContaining(defaultOptions), - ); - expect(calendar.formatViews).toEqual( - jasmine.objectContaining(defaultViews), - ); - expect(headerYear.nativeElement.textContent.trim()).toMatch( - "Select Date", - ); - expect(headerWeekday.nativeElement.textContent.trim()).toMatch( - "mer", - ); - expect(headerDate.nativeElement.textContent.trim()).toMatch( - "1 juin", - ); - expect(bodyYear.nativeElement.textContent.trim()).toMatch( - "2022", - ); - expect(bodyMonth.nativeElement.textContent.trim()).toMatch( - "juin", - ); + expect(calendar.formatOptions).toEqual(expect.objectContaining(defaultOptions)); + expect(calendar.formatViews).toEqual(expect.objectContaining(defaultViews)); + expect(headerYear.nativeElement.textContent.trim()).toMatch("Select Date"); + expect(headerWeekday.nativeElement.textContent.trim()).toMatch("mer"); + expect(headerDate.nativeElement.textContent.trim()).toMatch("1 juin"); + expect(bodyYear.nativeElement.textContent.trim()).toMatch("2022"); + expect(bodyMonth.nativeElement.textContent.trim()).toMatch("juin"); flush(); })); @@ -3091,28 +2254,16 @@ export class IgxCalendarValueComponent { class DateTester { // tests whether a date is disabled or not - public static testDatesAvailability( - dates: IgxDayItemComponent[], - disabled: boolean, - ) { + public static testDatesAvailability(dates: IgxDayItemComponent[], disabled: boolean) { for (const day of dates) { - expect(day.isDisabled).toBe( - disabled, - day.date.native.toLocaleDateString() + " is not disabled", - ); - expect(day.isDisabledCSS).toBe( - disabled, - day.date.native.toLocaleDateString() + - " is not with disabled style", - ); + expect(day.isDisabled).toBe(disabled, day.date.native.toLocaleDateString() + " is not disabled"); + expect(day.isDisabledCSS).toBe(disabled, day.date.native.toLocaleDateString() + + " is not with disabled style"); } } // tests whether a dates is special or not - public static testDatesSpeciality( - dates: IgxDayItemComponent[], - special: boolean, - ): void { + public static testDatesSpeciality(dates: IgxDayItemComponent[], special: boolean): void { for (const date of dates) { if (!date.isInactive) { expect(date.isSpecial).toBe(special); @@ -3121,20 +2272,11 @@ class DateTester { } } -type assignDateRangeDescriptors = ( - component: IgxCalendarComponent, - dateRangeDescriptors: DateRangeDescriptor[], -) => void; -type testDatesRange = ( - inRange: IgxDayItemComponent[], - outOfRange: IgxDayItemComponent[], -) => void; +type assignDateRangeDescriptors = (component: IgxCalendarComponent, dateRangeDescriptors: DateRangeDescriptor[]) => void; +type testDatesRange = (inRange: IgxDayItemComponent[], outOfRange: IgxDayItemComponent[]) => void; class DateRangesPropertiesTester { - public static testAfter( - assignFunc: assignDateRangeDescriptors, - testRangesFunc: testDatesRange, - ) { + public static testAfter(assignFunc: assignDateRangeDescriptors, testRangesFunc: testDatesRange) { const fixture = TestBed.createComponent(IgxCalendarSampleComponent); const calendar = fixture.componentInstance.calendar; const dateRangeDescriptors: DateRangeDescriptor[] = []; @@ -3148,19 +2290,12 @@ class DateRangesPropertiesTester { fixture.detectChanges(); const dates = calendar.daysView.dates.toArray(); - const inRangeDates = dates.filter( - (d) => getDate(d).getTime() > afterDate.getTime(), - ); - const outOfRangeDates = dates.filter( - (d) => getDate(d).getTime() <= afterDate.getTime(), - ); + const inRangeDates = dates.filter((d) => getDate(d).getTime() > afterDate.getTime()); + const outOfRangeDates = dates.filter((d) => getDate(d).getTime() <= afterDate.getTime()); testRangesFunc(inRangeDates, outOfRangeDates); } - public static testBefore( - assignFunc: assignDateRangeDescriptors, - testRangesFunc: testDatesRange, - ) { + public static testBefore(assignFunc: assignDateRangeDescriptors, testRangesFunc: testDatesRange) { const fixture = TestBed.createComponent(IgxCalendarSampleComponent); const calendar = fixture.componentInstance.calendar; const dateRangeDescriptors: DateRangeDescriptor[] = []; @@ -3174,55 +2309,24 @@ class DateRangesPropertiesTester { fixture.detectChanges(); const dates = calendar.daysView.dates.toArray(); - const inRangeDates = dates.filter( - (d) => getDate(d).getTime() < beforeDate.getTime(), - ); - const outOfRangeDates = dates.filter( - (d) => getDate(d).getTime() >= beforeDate.getTime(), - ); + const inRangeDates = dates.filter((d) => getDate(d).getTime() < beforeDate.getTime()); + const outOfRangeDates = dates.filter((d) => getDate(d).getTime() >= beforeDate.getTime()); testRangesFunc(inRangeDates, outOfRangeDates); } - public static testBetweenWithMinDateFirst( - assignFunc: assignDateRangeDescriptors, - testRangesFunc: testDatesRange, - ) { - this.testBetween( - assignFunc, - testRangesFunc, - new Date(2017, 5, 13), - new Date(2017, 5, 20), - ); + public static testBetweenWithMinDateFirst(assignFunc: assignDateRangeDescriptors, testRangesFunc: testDatesRange) { + this.testBetween(assignFunc, testRangesFunc, new Date(2017, 5, 13), new Date(2017, 5, 20)); } - public static testBetweenWithMaxDateFirst( - assignFunc: assignDateRangeDescriptors, - testRangesFunc: testDatesRange, - ) { - this.testBetween( - assignFunc, - testRangesFunc, - new Date(2017, 5, 20), - new Date(2017, 5, 13), - ); + public static testBetweenWithMaxDateFirst(assignFunc: assignDateRangeDescriptors, testRangesFunc: testDatesRange) { + this.testBetween(assignFunc, testRangesFunc, new Date(2017, 5, 20), new Date(2017, 5, 13)); } - public static testBetweenWithMinMaxTheSame( - assignFunc: assignDateRangeDescriptors, - testRangesFunc: testDatesRange, - ) { - this.testBetween( - assignFunc, - testRangesFunc, - new Date(2017, 5, 20), - new Date(2017, 5, 20), - ); + public static testBetweenWithMinMaxTheSame(assignFunc: assignDateRangeDescriptors, testRangesFunc: testDatesRange) { + this.testBetween(assignFunc, testRangesFunc, new Date(2017, 5, 20), new Date(2017, 5, 20)); } - public static testSpecific( - assignFunc: assignDateRangeDescriptors, - testRangesFunc: testDatesRange, - ) { + public static testSpecific(assignFunc: assignDateRangeDescriptors, testRangesFunc: testDatesRange) { const fixture = TestBed.createComponent(IgxCalendarSampleComponent); const calendar = fixture.componentInstance.calendar; const dateRangeDescriptors: DateRangeDescriptor[] = []; @@ -3243,19 +2347,12 @@ class DateRangesPropertiesTester { const specificDatesSet = new Set(); specificDates.map((d) => specificDatesSet.add(d.getTime())); const dates = calendar.daysView.dates.toArray(); - const inRangeDates = dates.filter((d) => - specificDatesSet.has(getDate(d).getTime()), - ); - const outOfRangeDates = dates.filter( - (d) => !specificDatesSet.has(getDate(d).getTime()), - ); + const inRangeDates = dates.filter((d) => specificDatesSet.has(getDate(d).getTime())); + const outOfRangeDates = dates.filter((d) => !specificDatesSet.has(getDate(d).getTime())); testRangesFunc(inRangeDates, outOfRangeDates); } - public static testWeekdays( - assignFunc: assignDateRangeDescriptors, - testRangesFunc: testDatesRange, - ) { + public static testWeekdays(assignFunc: assignDateRangeDescriptors, testRangesFunc: testDatesRange) { const fixture = TestBed.createComponent(IgxCalendarSampleComponent); const calendar = fixture.componentInstance.calendar; const dateRangeDescriptors: DateRangeDescriptor[] = [ @@ -3265,19 +2362,12 @@ class DateRangesPropertiesTester { fixture.detectChanges(); const dates = calendar.daysView.dates.toArray(); - const inRangeDates = dates.filter( - (d) => d.date.day !== 0 && d.date.day !== 6, - ); - const outOfRangeDates = dates.filter( - (d) => d.date.day === 0 || d.date.day === 6, - ); + const inRangeDates = dates.filter((d) => d.date.day !== 0 && d.date.day !== 6); + const outOfRangeDates = dates.filter((d) => d.date.day === 0 || d.date.day === 6); testRangesFunc(inRangeDates, outOfRangeDates); } - public static testWeekends( - assignFunc: assignDateRangeDescriptors, - testRangesFunc: testDatesRange, - ) { + public static testWeekends(assignFunc: assignDateRangeDescriptors, testRangesFunc: testDatesRange) { const fixture = TestBed.createComponent(IgxCalendarSampleComponent); const calendar = fixture.componentInstance.calendar; const dateRangeDescriptors: DateRangeDescriptor[] = [ @@ -3287,19 +2377,12 @@ class DateRangesPropertiesTester { fixture.detectChanges(); const dates = calendar.daysView.dates.toArray(); - const inRangeDates = dates.filter( - (d) => d.date.day === 0 || d.date.day === 6, - ); - const outOfRangeDates = dates.filter( - (d) => d.date.day !== 0 && d.date.day !== 6, - ); + const inRangeDates = dates.filter((d) => d.date.day === 0 || d.date.day === 6); + const outOfRangeDates = dates.filter((d) => d.date.day !== 0 && d.date.day !== 6); testRangesFunc(inRangeDates, outOfRangeDates); } - public static testOverlappingBetweens( - assignFunc: assignDateRangeDescriptors, - testRangesFunc: testDatesRange, - ) { + public static testOverlappingBetweens(assignFunc: assignDateRangeDescriptors, testRangesFunc: testDatesRange) { const fixture = TestBed.createComponent(IgxCalendarSampleComponent); const calendar = fixture.componentInstance.calendar; const dateRangeDescriptors: DateRangeDescriptor[] = []; @@ -3319,23 +2402,14 @@ class DateRangesPropertiesTester { fixture.detectChanges(); const dates = calendar.daysView.dates.toArray(); - const inRangeDates = dates.filter( - (d) => - getDate(d).getTime() >= firstBetweenMin.getTime() && - getDate(d).getTime() <= secondBetweenMax.getTime(), - ); - const outOfRangeDates = dates.filter( - (d) => - getDate(d).getTime() < firstBetweenMin.getTime() && - getDate(d).getTime() > secondBetweenMax.getTime(), - ); + const inRangeDates = dates.filter((d) => getDate(d).getTime() >= firstBetweenMin.getTime() && + getDate(d).getTime() <= secondBetweenMax.getTime()); + const outOfRangeDates = dates.filter((d) => getDate(d).getTime() < firstBetweenMin.getTime() && + getDate(d).getTime() > secondBetweenMax.getTime()); testRangesFunc(inRangeDates, outOfRangeDates); } - public static testMultipleRanges( - assignFunc: assignDateRangeDescriptors, - testRangesFunc: testDatesRange, - ) { + public static testMultipleRanges(assignFunc: assignDateRangeDescriptors, testRangesFunc: testDatesRange) { const fixture = TestBed.createComponent(IgxCalendarSampleComponent); const calendar = fixture.componentInstance.calendar; const dateRangeDescriptors: DateRangeDescriptor[] = []; @@ -3361,19 +2435,12 @@ class DateRangesPropertiesTester { const dates = calendar.daysView.dates.toArray(); const enabledDateTime = new Date(2017, 5, 29).getTime(); - const inRangesDates = dates.filter( - (d) => getDate(d).getTime() !== enabledDateTime, - ); - const outOfRangeDates = dates.filter( - (d) => getDate(d).getTime() === enabledDateTime, - ); + const inRangesDates = dates.filter((d) => getDate(d).getTime() !== enabledDateTime); + const outOfRangeDates = dates.filter((d) => getDate(d).getTime() === enabledDateTime); testRangesFunc(inRangesDates, outOfRangeDates); } - public static testRangeUpdateRuntime( - assignFunc: assignDateRangeDescriptors, - testRangesFunc: testDatesRange, - ) { + public static testRangeUpdateRuntime(assignFunc: assignDateRangeDescriptors, testRangesFunc: testDatesRange) { const fixture = TestBed.createComponent(IgxCalendarSampleComponent); const calendar = fixture.componentInstance.calendar; const dateRangeDescriptors: DateRangeDescriptor[] = []; @@ -3386,12 +2453,8 @@ class DateRangesPropertiesTester { fixture.detectChanges(); const dates = calendar.daysView.dates.toArray(); - let inRangesDates = dates.filter( - (d) => getDate(d).getTime() === specificDate.getTime(), - ); - let outOfRangesDates = dates.filter( - (d) => getDate(d).getTime() !== specificDate.getTime(), - ); + let inRangesDates = dates.filter((d) => getDate(d).getTime() === specificDate.getTime()); + let outOfRangesDates = dates.filter((d) => getDate(d).getTime() !== specificDate.getTime()); testRangesFunc(inRangesDates, outOfRangesDates); const newSpecificDate = new Date(2017, 5, 16); @@ -3403,19 +2466,12 @@ class DateRangesPropertiesTester { assignFunc(calendar, newDateRangeDescriptors); fixture.detectChanges(); - inRangesDates = dates.filter( - (d) => getDate(d).getTime() === newSpecificDate.getTime(), - ); - outOfRangesDates = dates.filter( - (d) => getDate(d).getTime() !== newSpecificDate.getTime(), - ); + inRangesDates = dates.filter((d) => getDate(d).getTime() === newSpecificDate.getTime()); + outOfRangesDates = dates.filter((d) => getDate(d).getTime() !== newSpecificDate.getTime()); testRangesFunc(inRangesDates, outOfRangesDates); } - public static testPreviousMonthRange( - assignFunc: assignDateRangeDescriptors, - testRangesFunc: testDatesRange, - ) { + public static testPreviousMonthRange(assignFunc: assignDateRangeDescriptors, testRangesFunc: testDatesRange) { const fixture = TestBed.createComponent(IgxCalendarSampleComponent); const calendar = fixture.componentInstance.calendar; const dateRangeDescriptors: DateRangeDescriptor[] = []; @@ -3430,62 +2486,38 @@ class DateRangesPropertiesTester { const debugEl = fixture.debugElement; - const component = debugEl.query( - By.css(HelperTestFunctions.CALENDAR_WRAPPER_CLASS), - ); + const component = debugEl.query(By.css(HelperTestFunctions.CALENDAR_WRAPPER_CLASS)); - UIInteractions.triggerKeyDownEvtUponElem( - "PageUp", - component.nativeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("PageUp", component.nativeElement); fixture.detectChanges(); testRangesFunc(calendar.daysView.dates.toArray(), []); } - public static assignDisableDatesDescriptors( - component: IgxCalendarComponent, - dateRangeDescriptors: DateRangeDescriptor[], - ) { + public static assignDisableDatesDescriptors(component: IgxCalendarComponent, dateRangeDescriptors: DateRangeDescriptor[]) { component.disabledDates = dateRangeDescriptors; } - public static testDisabledDates( - inRange: IgxDayItemComponent[], - outOfRange: IgxDayItemComponent[], - ) { + public static testDisabledDates(inRange: IgxDayItemComponent[], outOfRange: IgxDayItemComponent[]) { DateTester.testDatesAvailability(inRange, true); DateTester.testDatesAvailability(outOfRange, false); } - public static assignSpecialDatesDescriptors( - component: IgxCalendarComponent, - dateRangeDescriptors: DateRangeDescriptor[], - ) { + public static assignSpecialDatesDescriptors(component: IgxCalendarComponent, dateRangeDescriptors: DateRangeDescriptor[]) { component.specialDates = dateRangeDescriptors; } - public static testSpecialDates( - inRange: IgxDayItemComponent[], - outOfRange: IgxDayItemComponent[], - ) { + public static testSpecialDates(inRange: IgxDayItemComponent[], outOfRange: IgxDayItemComponent[]) { DateTester.testDatesSpeciality(inRange, true); DateTester.testDatesSpeciality(outOfRange, false); } - private static testBetween( - assignFunc: assignDateRangeDescriptors, - testRangesFunc: testDatesRange, - firstDate: Date, - secondDate: Date, - ) { + private static testBetween(assignFunc: assignDateRangeDescriptors, testRangesFunc: testDatesRange, firstDate: Date, secondDate: Date) { const fixture = TestBed.createComponent(IgxCalendarSampleComponent); const calendar = fixture.componentInstance.calendar; const dateRangeDescriptors: DateRangeDescriptor[] = []; - const betweenMin = - firstDate.getTime() > secondDate.getTime() ? secondDate : firstDate; - const betweenMax = - firstDate.getTime() > secondDate.getTime() ? firstDate : secondDate; + const betweenMin = firstDate.getTime() > secondDate.getTime() ? secondDate : firstDate; + const betweenMax = firstDate.getTime() > secondDate.getTime() ? firstDate : secondDate; dateRangeDescriptors.push({ type: DateRangeType.Between, dateRange: [betweenMax, betweenMin], @@ -3494,16 +2526,10 @@ class DateRangesPropertiesTester { fixture.detectChanges(); const dates = calendar.daysView.dates.toArray(); - const inRangeDates = dates.filter( - (d) => - getDate(d).getTime() >= betweenMin.getTime() && - getDate(d).getTime() <= betweenMax.getTime(), - ); - const outOfRangeDates = dates.filter( - (d) => - getDate(d).getTime() < betweenMin.getTime() && - getDate(d).getTime() > betweenMax.getTime(), - ); + const inRangeDates = dates.filter((d) => getDate(d).getTime() >= betweenMin.getTime() && + getDate(d).getTime() <= betweenMax.getTime()); + const outOfRangeDates = dates.filter((d) => getDate(d).getTime() < betweenMin.getTime() && + getDate(d).getTime() > betweenMax.getTime()); testRangesFunc(inRangeDates, outOfRangeDates); } } diff --git a/projects/igniteui-angular/calendar/src/calendar/days-view/days-view.component.spec.ts b/projects/igniteui-angular/calendar/src/calendar/days-view/days-view.component.spec.ts index c4c8a3ff4b4..875266a2471 100644 --- a/projects/igniteui-angular/calendar/src/calendar/days-view/days-view.component.spec.ts +++ b/projects/igniteui-angular/calendar/src/calendar/days-view/days-view.component.spec.ts @@ -8,6 +8,7 @@ import { KeyboardNavigationService } from '../calendar.services'; import { CalendarDay } from 'igniteui-angular/core'; import { UIInteractions } from '../../../../test-utils/ui-interactions.spec'; import { DayDigitPipe } from "igniteui-angular/calendar/src/calendar/day-digit.pipe"; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const TODAY = new Date(2024, 6, 12); @@ -27,9 +28,7 @@ describe("Days View Component", () => { const fixture = TestBed.createComponent(InitDaysViewComponent); fixture.detectChanges(); const { instance } = fixture.componentInstance; - const { nativeElement: hostEl } = fixture.debugElement.query( - By.css(baseClass), - ); + const { nativeElement: hostEl } = fixture.debugElement.query(By.css(baseClass)); expect(instance.id).toContain(`${baseClass}-`); expect(hostEl.id).toContain(`${baseClass}-`); @@ -76,11 +75,7 @@ describe("Days View Component", () => { }); it("should set activeDate to the first day of the current month when no value is provided", () => { - const firstMonthDay = new Date( - TODAY.getFullYear(), - TODAY.getMonth(), - 1, - ); + const firstMonthDay = new Date(TODAY.getFullYear(), TODAY.getMonth(), 1); const fixture = TestBed.createComponent(InitDaysViewComponent); const { instance } = fixture.componentInstance; fixture.detectChanges(); @@ -93,8 +88,7 @@ describe("Days View Component", () => { const { instance } = fixture.componentInstance; fixture.detectChanges(); - const { leading: initialLeading, trailing: initialTrailing } = - getInactiveDays(fixture); + const { leading: initialLeading, trailing: initialTrailing } = getInactiveDays(fixture); instance.hideLeadingDays = true; fixture.detectChanges(); @@ -131,19 +125,19 @@ describe("Days View Component", () => { get() { return { format: () => '25日', - } as Intl.DateTimeFormat + } as Intl.DateTimeFormat; } }); // 1. Verify Programmatic Access (formattedDate method) // Should return the raw formatted string from the formatter (with suffix) const programmaticResult = daysView.formattedDate(date); - expect(programmaticResult).toBe('25日', 'Programmatic API should return the full locale string (including suffix, in this case 日)'); + expect(programmaticResult, 'Programmatic API should return the full locale string (including suffix, in this case 日)').toBe('25日'); // 2. Verify Pipe Logic // The pipe takes the formatted string "25日" and strips non-digits to return "25" const pipeResult = pipe.transform(programmaticResult, daysView.formatViews); - expect(pipeResult).toBe('25', 'Pipe should strip non-numeric characters from the input string'); + expect(pipeResult, 'Pipe should strip non-numeric characters from the input string').toBe('25'); // 3. Confirm the difference implies the pipe did its job expect(programmaticResult).not.toEqual(pipeResult); @@ -153,18 +147,12 @@ describe("Days View Component", () => { let fixture: ComponentFixture; let el: HTMLElement; let instance: IgxDaysViewComponent; - const firstDay = CalendarDay.from( - new Date(TODAY.getFullYear(), TODAY.getMonth(), 1), - ); - const lastDay = CalendarDay.from( - new Date(TODAY.getFullYear(), TODAY.getMonth() + 1, 0), - ); + const firstDay = CalendarDay.from(new Date(TODAY.getFullYear(), TODAY.getMonth(), 1)); + const lastDay = CalendarDay.from(new Date(TODAY.getFullYear(), TODAY.getMonth() + 1, 0)); beforeEach(waitForAsync(() => { fixture = TestBed.createComponent(InitDaysViewComponent); - el = fixture.debugElement.query( - By.css("igx-days-view"), - ).nativeElement; + el = fixture.debugElement.query(By.css("igx-days-view")).nativeElement; instance = fixture.componentInstance.instance; fixture.detectChanges(); @@ -173,40 +161,28 @@ describe("Days View Component", () => { })); it("should navigate to the next day when pressing the right arrow key", () => { - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowRight", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowRight", document.activeElement); fixture.detectChanges(); expect(instance.activeDate).toEqual(firstDay.add("day", 1).native); }); it("should navigate to the previous day when pressing the left arrow key", () => { - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowLeft", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowLeft", document.activeElement); fixture.detectChanges(); expect(instance.activeDate).toEqual(firstDay.add("day", -1).native); }); it("should navigate to same day next week when pressing the down arrow key", () => { - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowDown", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowDown", document.activeElement); fixture.detectChanges(); expect(instance.activeDate).toEqual(firstDay.add("day", 7).native); }); it("should navigate to same day prev week when pressing the up arrow key", () => { - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowUp", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowUp", document.activeElement); fixture.detectChanges(); expect(instance.activeDate).toEqual(firstDay.add("day", -7).native); @@ -216,41 +192,30 @@ describe("Days View Component", () => { instance.activeDate = firstDay.add("day", 10).native; fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "Home", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("Home", document.activeElement); fixture.detectChanges(); expect(instance.activeDate).toEqual(firstDay.native); }); it("should navigate to the last active date in the month when pressing the End key", () => { - UIInteractions.triggerKeyDownEvtUponElem( - "End", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("End", document.activeElement); fixture.detectChanges(); expect(instance.activeDate).toEqual(lastDay.native); }); it("should select the activeDate when pressing the enter key", () => { - spyOn(instance.dateSelected, "emit"); - spyOn(instance.selected, "emit"); + vi.spyOn(instance.dateSelected, "emit"); + vi.spyOn(instance.selected, "emit"); instance.activeDate = firstDay.add("day", 4).native; fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "Enter", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("Enter", document.activeElement); fixture.detectChanges(); - expect(instance.dateSelected.emit).toHaveBeenCalledWith( - instance.activeDate, - ); + expect(instance.dateSelected.emit).toHaveBeenCalledWith(instance.activeDate); expect(instance.selected.emit).toHaveBeenCalledWith([ instance.activeDate, ]); @@ -261,44 +226,29 @@ describe("Days View Component", () => { instance.activeDate = firstDay.add("day", 10).native; fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowRight", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowRight", document.activeElement); fixture.detectChanges(); expect(instance.activeDate).toEqual(firstDay.add("day", 12).native); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowLeft", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowLeft", document.activeElement); expect(instance.activeDate).toEqual(firstDay.add("day", 10).native); instance.activeDate = firstDay.add("day", 4).native; - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowDown", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowDown", document.activeElement); expect(instance.activeDate).toEqual(firstDay.add("day", 18).native); - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowUp", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowUp", document.activeElement); expect(instance.activeDate).toEqual(firstDay.add("day", 4).native); }); it("should emit pageChaged event when the active date is in the previous/next months", () => { - spyOn(instance.pageChanged, "emit"); + vi.spyOn(instance.pageChanged, "emit"); instance.activeDate = firstDay.native; fixture.detectChanges(); // Movo to previous month - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowLeft", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowLeft", document.activeElement); expect(instance.pageChanged.emit).toHaveBeenCalledWith({ monthAction: ScrollDirection.PREV, @@ -307,10 +257,7 @@ describe("Days View Component", () => { }); // Movo to next month - UIInteractions.triggerKeyDownEvtUponElem( - "ArrowRight", - document.activeElement, - ); + UIInteractions.triggerKeyDownEvtUponElem("ArrowRight", document.activeElement); expect(instance.pageChanged.emit).toHaveBeenCalledWith({ monthAction: ScrollDirection.NEXT, @@ -327,9 +274,7 @@ describe("Days View Component", () => { beforeEach(waitForAsync(() => { fixture = TestBed.createComponent(InitDaysViewComponent); - el = fixture.debugElement.query( - By.css("igx-days-view"), - ).nativeElement; + el = fixture.debugElement.query(By.css("igx-days-view")).nativeElement; instance = fixture.componentInstance.instance; fixture.detectChanges(); @@ -338,21 +283,15 @@ describe("Days View Component", () => { })); it("should select the clicked date", () => { - spyOn(instance.dateSelected, "emit"); - spyOn(instance.selected, "emit"); + vi.spyOn(instance.dateSelected, "emit"); + vi.spyOn(instance.selected, "emit"); - const day = fixture.debugElement.query( - By.css( - ".igx-days-view__date:not(.igx-days-view__date--inactive)", - ), - ); + const day = fixture.debugElement.query(By.css(".igx-days-view__date:not(.igx-days-view__date--inactive)")); UIInteractions.simulateClickAndSelectEvent(day.nativeElement.firstChild); fixture.detectChanges(); - expect(instance.dateSelected.emit).toHaveBeenCalledWith( - instance.activeDate, - ); + expect(instance.dateSelected.emit).toHaveBeenCalledWith(instance.activeDate); expect(instance.selected.emit).toHaveBeenCalledWith([ instance.activeDate, @@ -362,15 +301,11 @@ describe("Days View Component", () => { }); it("should emit pageChanged when clicking on a date outside the previous/next months", () => { - spyOn(instance.pageChanged, "emit"); + vi.spyOn(instance.pageChanged, "emit"); - let days = fixture.debugElement.queryAll( - By.css(".igx-days-view__date--inactive"), - ); + let days = fixture.debugElement.queryAll(By.css(".igx-days-view__date--inactive")); - UIInteractions.simulateClickAndSelectEvent( - days.at(0).nativeElement.firstChild, - ); + UIInteractions.simulateClickAndSelectEvent(days.at(0).nativeElement.firstChild); fixture.detectChanges(); expect(instance.pageChanged.emit).toHaveBeenCalledWith({ @@ -379,13 +314,9 @@ describe("Days View Component", () => { nextDate: instance.activeDate, }); - days = fixture.debugElement.queryAll( - By.css(".igx-days-view__date--inactive"), - ); + days = fixture.debugElement.queryAll(By.css(".igx-days-view__date--inactive")); - UIInteractions.simulateClickAndSelectEvent( - days.at(-1).nativeElement.firstChild, - ); + UIInteractions.simulateClickAndSelectEvent(days.at(-1).nativeElement.firstChild); fixture.detectChanges(); expect(instance.pageChanged.emit).toHaveBeenCalledWith({ @@ -399,21 +330,11 @@ describe("Days View Component", () => { function getInactiveDays(fixture: ComponentFixture) { const days = fixture.debugElement.queryAll(By.css(".igx-days-view__date")); - const inactiveDays = fixture.debugElement.queryAll( - By.css( - ".igx-days-view__date--inactive:not(igx-dasy-view__date--hidden)", - ), - ); - - const firstActiveIndex = days.findIndex( - (d: DebugElement) => - !d.nativeElement.classList.contains( - "igx-days-view__date--inactive", - ), - ); - - const notHidden = (d: DebugElement) => - !d.nativeElement.classList.contains("igx-days-view__date--hidden"); + const inactiveDays = fixture.debugElement.queryAll(By.css(".igx-days-view__date--inactive:not(igx-dasy-view__date--hidden)")); + + const firstActiveIndex = days.findIndex((d: DebugElement) => !d.nativeElement.classList.contains("igx-days-view__date--inactive")); + + const notHidden = (d: DebugElement) => !d.nativeElement.classList.contains("igx-days-view__date--hidden"); const leading = inactiveDays.slice(0, firstActiveIndex).filter(notHidden); const trailing = inactiveDays diff --git a/projects/igniteui-angular/calendar/src/calendar/month-picker/month-picker.component.spec.ts b/projects/igniteui-angular/calendar/src/calendar/month-picker/month-picker.component.spec.ts index 0fdd6733c63..e7371336f8a 100644 --- a/projects/igniteui-angular/calendar/src/calendar/month-picker/month-picker.component.spec.ts +++ b/projects/igniteui-angular/calendar/src/calendar/month-picker/month-picker.component.spec.ts @@ -6,6 +6,7 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { UIInteractions } from '../../../../test-utils/ui-interactions.spec'; import { IgxMonthPickerComponent } from './month-picker.component'; import { IFormattingOptions, IgxCalendarView } from '../calendar'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxMonthPicker', () => { @@ -125,8 +126,8 @@ describe('IgxMonthPicker', () => { const yearBtn = dom.query(By.css('.igx-calendar-picker__date')); const month = dom.queryAll(By.css('.igx-calendar-view__item'))[0]; - expect(monthPicker.formatOptions).toEqual(jasmine.objectContaining(defaultOptions)); - expect(monthPicker.formatViews).toEqual(jasmine.objectContaining(defaultViews)); + expect(monthPicker.formatOptions).toEqual(expect.objectContaining(defaultOptions)); + expect(monthPicker.formatViews).toEqual(expect.objectContaining(defaultViews)); expect(yearBtn.nativeElement.textContent.trim()).toMatch('2019'); expect(month.nativeElement.textContent.trim()).toMatch('Jan'); @@ -139,8 +140,8 @@ describe('IgxMonthPicker', () => { const march = dom.queryAll(By.css('.igx-calendar-view__item'))[2]; - expect(monthPicker.formatOptions).toEqual(jasmine.objectContaining(Object.assign(defaultOptions, formatOptions))); - expect(monthPicker.formatViews).toEqual(jasmine.objectContaining(Object.assign(defaultViews, formatViews))); + expect(monthPicker.formatOptions).toEqual(expect.objectContaining(Object.assign(defaultOptions, formatOptions))); + expect(monthPicker.formatViews).toEqual(expect.objectContaining(Object.assign(defaultViews, formatViews))); expect(yearBtn.nativeElement.textContent.trim()).toMatch('19'); expect(march.nativeElement.textContent.trim()).toMatch('March'); @@ -178,7 +179,7 @@ describe('IgxMonthPicker', () => { const months = dom.queryAll(By.css('.igx-calendar-view__item')); - spyOn(monthPicker.selected, 'emit'); + vi.spyOn(monthPicker.selected, 'emit'); UIInteractions.simulateMouseDownEvent(months[2].nativeElement.firstChild); fixture.detectChanges(); @@ -329,7 +330,7 @@ describe('IgxMonthPicker', () => { const dom = fixture.debugElement; const monthPicker = fixture.componentInstance.monthPicker; - spyOn(monthPicker.selected, 'emit').and.callThrough(); + vi.spyOn(monthPicker.selected, 'emit'); const next = dom.query(By.css('.igx-calendar-picker__next')); let yearBtn = dom.query(By.css('.igx-calendar-picker__date')); @@ -352,7 +353,7 @@ describe('IgxMonthPicker', () => { const dom = fixture.debugElement; const monthPicker = fixture.componentInstance.monthPicker; - spyOn(monthPicker.selected, 'emit').and.callThrough(); + vi.spyOn(monthPicker.selected, 'emit'); const prev = dom.query(By.css('.igx-calendar-picker__prev')); let yearBtn = dom.query(By.css('.igx-calendar-picker__date')); @@ -375,7 +376,7 @@ describe('IgxMonthPicker', () => { const dom = fixture.debugElement; const monthPicker = fixture.componentInstance.monthPicker; - spyOn(monthPicker.selected, 'emit').and.callThrough(); + vi.spyOn(monthPicker.selected, 'emit'); let yearBtn = dom.query(By.css('.igx-calendar-picker__date')); expect(yearBtn.nativeElement.textContent.trim()).toMatch('2019'); @@ -407,20 +408,20 @@ describe('IgxMonthPicker', () => { let selectedYear = dom.query(By.css('.igx-calendar-view__item--selected')); expect(selectedYear.nativeElement.textContent.trim()).toMatch('2019'); - UIInteractions.triggerKeyDownEvtUponElem('ArrowDown' , document.activeElement); + UIInteractions.triggerKeyDownEvtUponElem('ArrowDown', document.activeElement); fixture.detectChanges(); selectedYear = dom.query(By.css('.igx-calendar-view__item--selected')); expect(selectedYear.nativeElement.textContent.trim()).toMatch('2022'); - UIInteractions.triggerKeyDownEvtUponElem('ArrowUp' , document.activeElement); - UIInteractions.triggerKeyDownEvtUponElem('ArrowUp' , document.activeElement); + UIInteractions.triggerKeyDownEvtUponElem('ArrowUp', document.activeElement); + UIInteractions.triggerKeyDownEvtUponElem('ArrowUp', document.activeElement); fixture.detectChanges(); selectedYear = dom.query(By.css('.igx-calendar-view__item--selected')); expect(selectedYear.nativeElement.textContent.trim()).toMatch('2016'); - UIInteractions.triggerKeyDownEvtUponElem('Enter' , document.activeElement); + UIInteractions.triggerKeyDownEvtUponElem('Enter', document.activeElement); fixture.detectChanges(); expect(monthPicker.viewDate.getFullYear()).toEqual(2016); @@ -443,32 +444,32 @@ describe('IgxMonthPicker', () => { monthsView.nativeElement.focus(); expect(monthsView.nativeElement).toBe(document.activeElement); - UIInteractions.triggerKeyDownEvtUponElem('Home' , document.activeElement); + UIInteractions.triggerKeyDownEvtUponElem('Home', document.activeElement); fixture.detectChanges(); currentMonth = dom.query(By.css('.igx-calendar-view__item--selected')); expect(months.at(0).nativeElement.classList).toContain('igx-calendar-view__item--selected'); expect(currentMonth.nativeElement.textContent.trim()).toMatch('Jan'); - UIInteractions.triggerKeyDownEvtUponElem('End' , currentMonth.nativeElement ); + UIInteractions.triggerKeyDownEvtUponElem('End', currentMonth.nativeElement); fixture.detectChanges(); currentMonth = dom.query(By.css('.igx-calendar-view__item--selected')); expect(months.at(-1).nativeElement.classList).toContain('igx-calendar-view__item--selected'); expect(currentMonth.nativeElement.textContent.trim()).toMatch('Dec'); - UIInteractions.triggerKeyDownEvtUponElem('ArrowLeft' , document.activeElement ); + UIInteractions.triggerKeyDownEvtUponElem('ArrowLeft', document.activeElement); fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem('ArrowUp' , document.activeElement ); + UIInteractions.triggerKeyDownEvtUponElem('ArrowUp', document.activeElement); fixture.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem('ArrowRight' , document.activeElement ); + UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', document.activeElement); fixture.detectChanges(); currentMonth = dom.query(By.css('.igx-calendar-view__item--selected')); expect(currentMonth.nativeElement.textContent.trim()).toMatch('Sep'); - UIInteractions.triggerKeyDownEvtUponElem('Enter' , document.activeElement ); + UIInteractions.triggerKeyDownEvtUponElem('Enter', document.activeElement); fixture.detectChanges(); expect(monthPicker.viewDate.getMonth()).toEqual(8); @@ -477,7 +478,7 @@ describe('IgxMonthPicker', () => { it('should update the view date and throw viewDateChanged event on page changes', () => { const fixture = TestBed.createComponent(IgxMonthPickerSampleComponent); const monthPicker = fixture.componentInstance.monthPicker; - spyOn(monthPicker.viewDateChanged, 'emit'); + vi.spyOn(monthPicker.viewDateChanged, 'emit'); fixture.detectChanges(); const dom = fixture.debugElement; @@ -504,7 +505,7 @@ describe('IgxMonthPicker', () => { it('should emit an activeViewChanged event whenever the view changes', () => { const fixture = TestBed.createComponent(IgxMonthPickerSampleComponent); const monthPicker = fixture.componentInstance.monthPicker; - spyOn(monthPicker.activeViewChanged, 'emit'); + vi.spyOn(monthPicker.activeViewChanged, 'emit'); fixture.detectChanges(); const dom = fixture.debugElement; @@ -527,7 +528,7 @@ describe('IgxMonthPicker', () => { it('should emit viewDateChanged event when changing year with arrow buttons', () => { const fixture = TestBed.createComponent(IgxMonthPickerSampleComponent); const monthPicker = fixture.componentInstance.monthPicker; - spyOn(monthPicker.viewDateChanged, 'emit'); + vi.spyOn(monthPicker.viewDateChanged, 'emit'); fixture.detectChanges(); @@ -563,7 +564,8 @@ describe('IgxMonthPicker', () => { imports: [FormsModule, IgxMonthPickerComponent] }) export class IgxMonthPickerSampleComponent { - @ViewChild(IgxMonthPickerComponent, { static: true }) public monthPicker: IgxMonthPickerComponent; + @ViewChild(IgxMonthPickerComponent, { static: true }) + public monthPicker: IgxMonthPickerComponent; public model: Date = new Date(2019, 1, 7); public viewDate = new Date(2019, 1, 7); diff --git a/projects/igniteui-angular/card/src/card/card.spec.ts b/projects/igniteui-angular/card/src/card/card.spec.ts index 3c148b30d43..c5012fe5371 100644 --- a/projects/igniteui-angular/card/src/card/card.spec.ts +++ b/projects/igniteui-angular/card/src/card/card.spec.ts @@ -1,20 +1,12 @@ import { Component, ViewChild } from '@angular/core'; import { TestBed, waitForAsync } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; -import { - IgxCardComponent, - IgxCardThumbnailDirective, - IgxCardHeaderTitleDirective, - IgxCardHeaderSubtitleDirective, - IgxCardActionsComponent, - IgxCardMediaDirective, - IgxCardHeaderComponent, - IgxCardContentDirective, -} from './card.component'; +import { IgxCardComponent, IgxCardThumbnailDirective, IgxCardHeaderTitleDirective, IgxCardHeaderSubtitleDirective, IgxCardActionsComponent, IgxCardMediaDirective, IgxCardHeaderComponent, IgxCardContentDirective, } from './card.component'; import { IgxButtonDirective } from '../../../directives/src/directives/button/button.directive'; import { IgxIconComponent } from 'igniteui-angular/icon'; import { IgxIconButtonDirective } from '../../../directives/src/directives/button/icon-button.directive'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Card', () => { // TODO: Refactor card tests to reuse components @@ -82,9 +74,9 @@ describe('Card', () => { expect(card).toBeDefined(); expect(card.getAttribute('role')).toEqual('group'); - expect(card).toHaveClass(`${baseClass}`); - expect(card).not.toHaveClass(classes.elevated); - expect(card).not.toHaveClass(classes.horizontal); + expect(card.classList.contains(`${baseClass}`)).toBe(true); + expect(card.classList.contains(classes.elevated)).toBe(false); + expect(card.classList.contains(classes.horizontal)).toBe(false); expect(card.id).toContain(`${baseClass}-`); }); @@ -96,7 +88,7 @@ describe('Card', () => { const card = fixture.debugElement.query(By.css(baseClass)).nativeElement; expect(instance.horizontal).toEqual(true); - expect(card).toHaveClass(classes.horizontal); + expect(card.classList.contains(classes.horizontal)).toBe(true); }); it('Initializes card header', () => { @@ -110,8 +102,8 @@ describe('Card', () => { // expect(header.getAttribute('role')).toEqual('header'); expect(header.getAttribute('role')).toBeNull(); - expect(header).toHaveClass(classes.header.base); - expect(header).not.toHaveClass(classes.header.vertical); + expect(header.classList.contains(classes.header.base)).toBe(true); + expect(header.classList.contains(classes.header.vertical)).toBe(false); }); it('Initializes vertical card header', () => { @@ -119,7 +111,7 @@ describe('Card', () => { fixture.detectChanges(); const header = fixture.debugElement.query(By.css('igx-card-header')).nativeElement; - expect(header).toHaveClass(classes.header.vertical); + expect(header.classList.contains(classes.header.vertical)).toBe(true); }); it('Initializes title, subtitle, and thumb in header', () => { @@ -131,15 +123,15 @@ describe('Card', () => { const subtitle = fixture.debugElement.query(By.directive(IgxCardHeaderSubtitleDirective)); // Check to see if thumbnail has been inserted in the thumbnail section; - expect(thumb.parent.nativeElement).toHaveClass(classes.header.thumb); + expect(thumb.parent.nativeElement.classList.contains(classes.header.thumb)).toBe(true); // Check to see if the title and subtitle have been // inserted in the titles section; - expect(title.parent.nativeElement).toHaveClass(classes.header.titles); - expect(subtitle.parent.nativeElement).toHaveClass(classes.header.titles); + expect(title.parent.nativeElement.classList.contains(classes.header.titles)).toBe(true); + expect(subtitle.parent.nativeElement.classList.contains(classes.header.titles)).toBe(true); - expect(title.nativeElement).toHaveClass(classes.header.title); - expect(subtitle.nativeElement).toHaveClass(classes.header.subtitle); + expect(title.nativeElement.classList.contains(classes.header.title)).toBe(true); + expect(subtitle.nativeElement.classList.contains(classes.header.subtitle)).toBe(true); // Validate Content expect(thumb.nativeElement.textContent).toEqual('Thumb'); @@ -166,7 +158,7 @@ describe('Card', () => { expect(media).toBeDefined(); expect(mediaContent.textContent).toEqual('media'); - expect(media.nativeElement).toHaveClass(classes.media); + expect(media.nativeElement.classList.contains(classes.media)).toBe(true); }); it('Initializes actions with buttons', () => { @@ -176,9 +168,9 @@ describe('Card', () => { const actions = fixture.debugElement.query(By.css('igx-card-actions')).nativeElement; expect(actions).toBeDefined(); - expect(actions).toHaveClass(classes.actions.base); - expect(actions).not.toHaveClass(classes.actions.justify); - expect(actions).not.toHaveClass(classes.actions.vertical); + expect(actions.classList.contains(classes.actions.base)).toBe(true); + expect(actions.classList.contains(classes.actions.justify)).toBe(false); + expect(actions.classList.contains(classes.actions.vertical)).toBe(false); }); it('Should use Material Icons font-family for igx-icon in card content', () => { @@ -199,7 +191,7 @@ describe('Card', () => { const actionsElement = fixture.debugElement.query(By.css('igx-card-actions')).nativeElement; expect(actionsInstance.vertical).toEqual(true); - expect(actionsElement).toHaveClass(classes.actions.vertical); + expect(actionsElement.classList.contains(classes.actions.vertical)).toBe(true); }); it('Should align actions horizontally and vertically when explicitly set', () => { @@ -213,7 +205,7 @@ describe('Card', () => { fixture.detectChanges(); expect(actionsInstance.vertical).toEqual(false); - expect(actionsElement).not.toHaveClass(classes.actions.vertical); + expect(actionsElement.classList.contains(classes.actions.vertical)).toBe(false); }); it('Should display icon buttons after regular buttons by default', () => { @@ -236,7 +228,8 @@ describe('Card', () => { template: ``, imports: [IgxCardComponent] }) -class InitCardComponent { } +class InitCardComponent { +} @Component({ template: ``, @@ -253,7 +246,8 @@ class InitOutlinedCardComponent { `, imports: [IgxCardComponent, IgxCardHeaderComponent] }) -class CardWithHeaderComponent { } +class CardWithHeaderComponent { +} @Component({ template: ` @@ -263,7 +257,8 @@ class CardWithHeaderComponent { } `, imports: [IgxCardComponent, IgxCardContentDirective, IgxIconComponent] }) -class CardContentIconComponent { } +class CardContentIconComponent { +} @Component({ template: ` @@ -301,7 +296,8 @@ class CardContentIconComponent { } ] }) class VerticalCardComponent { - @ViewChild(IgxCardMediaDirective, { static: true }) public media: IgxCardMediaDirective; + @ViewChild(IgxCardMediaDirective, { static: true }) + public media: IgxCardMediaDirective; } @Component({ @@ -317,6 +313,8 @@ class VerticalCardComponent { imports: [IgxCardComponent, IgxCardActionsComponent, IgxButtonDirective, IgxIconComponent, IgxIconButtonDirective] }) class HorizontalCardComponent { - @ViewChild(IgxCardComponent, { static: true }) public card: IgxCardComponent; - @ViewChild(IgxCardActionsComponent, { static: true }) public actions: IgxCardActionsComponent; + @ViewChild(IgxCardComponent, { static: true }) + public card: IgxCardComponent; + @ViewChild(IgxCardActionsComponent, { static: true }) + public actions: IgxCardActionsComponent; } diff --git a/projects/igniteui-angular/carousel/src/carousel/carousel.component.spec.ts b/projects/igniteui-angular/carousel/src/carousel/carousel.component.spec.ts index 74ddfc755c9..a47df83dcec 100644 --- a/projects/igniteui-angular/carousel/src/carousel/carousel.component.spec.ts +++ b/projects/igniteui-angular/carousel/src/carousel/carousel.component.spec.ts @@ -1,15 +1,13 @@ import { Component, ViewChild, TemplateRef, ChangeDetectionStrategy, ElementRef } from '@angular/core'; import { TestBed, fakeAsync, tick, waitForAsync } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; -import { - IgxCarouselComponent, - ISlideEventArgs -} from './carousel.component'; +import { IgxCarouselComponent, ISlideEventArgs } from './carousel.component'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxSlideComponent } from './slide.component'; import { IgxCarouselIndicatorDirective, IgxCarouselNextButtonDirective, IgxCarouselPrevButtonDirective } from './carousel.directives'; import { CarouselIndicatorsOrientation, CarouselAnimationType } from './enums'; import { UIInteractions, wait } from 'igniteui-angular/test-utils/ui-interactions.spec'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; describe('Carousel', () => { let fixture; @@ -175,7 +173,7 @@ describe('Carousel', () => { }); it('emit events', () => { - spyOn(carousel.slideChanged, 'emit'); + vi.spyOn(carousel.slideChanged, 'emit'); carousel.next(); fixture.detectChanges(); let args: ISlideEventArgs = { @@ -203,7 +201,7 @@ describe('Carousel', () => { expect(carousel.slideChanged.emit).toHaveBeenCalledWith(args); expect(carousel.slideChanged.emit).toHaveBeenCalledTimes(3); - spyOn(carousel.slideAdded, 'emit'); + vi.spyOn(carousel.slideAdded, 'emit'); const newSlide = TestBed.inject(IgxSlideComponent); carousel.add(newSlide); fixture.detectChanges(); @@ -213,7 +211,7 @@ describe('Carousel', () => { }; expect(carousel.slideAdded.emit).toHaveBeenCalledWith(args); - spyOn(carousel.slideRemoved, 'emit'); + vi.spyOn(carousel.slideRemoved, 'emit'); args = { carousel, slide: carousel.get(carousel.current) @@ -222,12 +220,12 @@ describe('Carousel', () => { fixture.detectChanges(); expect(carousel.slideRemoved.emit).toHaveBeenCalledWith(args); - spyOn(carousel.carouselPaused, 'emit'); + vi.spyOn(carousel.carouselPaused, 'emit'); carousel.stop(); fixture.detectChanges(); expect(carousel.carouselPaused.emit).toHaveBeenCalledWith(carousel); - spyOn(carousel.carouselPlaying, 'emit'); + vi.spyOn(carousel.carouselPlaying, 'emit'); carousel.play(); fixture.detectChanges(); expect(carousel.carouselPlaying.emit).toHaveBeenCalledWith(carousel); @@ -237,19 +235,19 @@ describe('Carousel', () => { const nextNav = HelperTestFunctions.getNextButton(fixture); const prevNav = HelperTestFunctions.getPreviousButton(fixture); - spyOn(carousel, 'prev'); + vi.spyOn(carousel, 'prev'); prevNav.dispatchEvent(new Event('click')); fixture.detectChanges(); expect(carousel.prev).toHaveBeenCalled(); - spyOn(carousel, 'next'); + vi.spyOn(carousel, 'next'); nextNav.dispatchEvent(new Event('click')); fixture.detectChanges(); expect(carousel.next).toHaveBeenCalled(); }); it('keyboard navigation test', () => { - spyOn(carousel.slideChanged, 'emit'); + vi.spyOn(carousel.slideChanged, 'emit'); carousel.pause = true; const indicators = HelperTestFunctions.getIndicatorsContainer(fixture); @@ -293,7 +291,7 @@ describe('Carousel', () => { }); it('changing slides with navigation buttons', () => { - spyOn(carousel.slideChanged, 'emit'); + vi.spyOn(carousel.slideChanged, 'emit'); carousel.pause = true; const prevNav = HelperTestFunctions.getPreviousButton(fixture); @@ -333,7 +331,7 @@ describe('Carousel', () => { }); it('changing slides with indicators buttons', () => { - spyOn(carousel.slideChanged, 'emit'); + vi.spyOn(carousel.slideChanged, 'emit'); carousel.pause = true; const indicators = HelperTestFunctions.getIndicators(fixture); @@ -429,8 +427,8 @@ describe('Carousel', () => { carousel.play(); fixture.detectChanges(); - spyOn(carousel.carouselPaused, 'emit'); - spyOn(carousel.carouselPlaying, 'emit'); + vi.spyOn(carousel.carouselPaused, 'emit'); + vi.spyOn(carousel.carouselPlaying, 'emit'); expect(carousel.isPlaying).toBeTruthy(); @@ -507,8 +505,8 @@ describe('Carousel', () => { const nextNav = HelperTestFunctions.getNextButton(fixture); const prevNav = HelperTestFunctions.getPreviousButton(fixture); - spyOn(carousel, 'next'); - spyOn(carousel, 'prev'); + vi.spyOn(carousel, 'next'); + vi.spyOn(carousel, 'prev'); UIInteractions.triggerKeyDownEvtUponElem('Enter', nextNav, true); UIInteractions.triggerKeyDownEvtUponElem(' ', nextNav, true); @@ -801,7 +799,7 @@ describe('Carousel', () => { it('should add slides to the carousel when collection is changed', fakeAsync(() => { tick(); - spyOn(carousel.slideAdded, 'emit'); + vi.spyOn(carousel.slideAdded, 'emit'); // add a slide slides.push({ text: 'Slide 5' }); @@ -823,7 +821,7 @@ describe('Carousel', () => { it('should remove slides in the carousel', fakeAsync(() => { tick(); - spyOn(carousel.slideRemoved, 'emit'); + vi.spyOn(carousel.slideRemoved, 'emit'); // remove a slide slides.pop(); @@ -880,8 +878,8 @@ describe('Carousel', () => { carousel.play(); fixture.detectChanges(); - spyOn(carousel.carouselPaused, 'emit'); - spyOn(carousel.carouselPlaying, 'emit'); + vi.spyOn(carousel.carouselPaused, 'emit'); + vi.spyOn(carousel.carouselPlaying, 'emit'); expect(carousel.isPlaying).toBeTruthy(); @@ -1114,7 +1112,7 @@ class HelperTestFunctions { public static simulateTap(fixture, carousel) { const activeSlide = carousel.get(carousel.current).nativeElement; const carouselElement = fixture.debugElement.query(By.css('igx-carousel')); - carouselElement.triggerEventHandler('tap', {target: activeSlide}); + carouselElement.triggerEventHandler('tap', { target: activeSlide }); // Simulator.gestures.press(activeSlide, { duration: 180 }); } @@ -1135,7 +1133,7 @@ class HelperTestFunctions { deltaY, duration: 100, velocity, - preventDefault: ( () => { }) + preventDefault: (() => { }) }; carouselElement.triggerEventHandler(event, panOptions); @@ -1156,7 +1154,8 @@ class HelperTestFunctions { imports: [IgxCarouselComponent, IgxSlideComponent] }) class CarouselTestComponent { - @ViewChild('carousel', { static: true }) public carousel: IgxCarouselComponent; + @ViewChild('carousel', { static: true }) + public carousel: IgxCarouselComponent; public loop = true; public pause = true; @@ -1176,7 +1175,8 @@ class CarouselTestComponent { changeDetection: ChangeDetectionStrategy.OnPush }) class CarouselAnimationsComponent { - @ViewChild('carousel', { static: true }) public carousel: IgxCarouselComponent; + @ViewChild('carousel', { static: true }) + public carousel: IgxCarouselComponent; } @@ -1204,7 +1204,8 @@ class CarouselAnimationsComponent { imports: [IgxCarouselComponent, IgxSlideComponent, IgxCarouselIndicatorDirective, IgxCarouselNextButtonDirective, IgxCarouselPrevButtonDirective] }) class CarouselTemplateSetInMarkupTestComponent { - @ViewChild('carousel', { static: true }) public carousel: IgxCarouselComponent; + @ViewChild('carousel', { static: true }) + public carousel: IgxCarouselComponent; } @Component({ @@ -1240,7 +1241,8 @@ class CarouselTemplateSetInMarkupTestComponent { imports: [IgxCarouselComponent, IgxSlideComponent] }) class CarouselTemplateSetInTypescriptTestComponent { - @ViewChild('carousel', { static: true }) public carousel: IgxCarouselComponent; + @ViewChild('carousel', { static: true }) + public carousel: IgxCarouselComponent; @ViewChild('customIndicatorTemplate1', { read: TemplateRef, static: false }) public customIndicatorTemplate1; @ViewChild('customIndicatorTemplate2', { read: TemplateRef, static: false }) @@ -1264,18 +1266,14 @@ class CarouselTemplateSetInTypescriptTestComponent { imports: [IgxCarouselComponent, IgxSlideComponent] }) class CarouselDynamicSlidesComponent { - @ViewChild('carousel', { static: true }) public carousel: IgxCarouselComponent; + @ViewChild('carousel', { static: true }) + public carousel: IgxCarouselComponent; public loop = true; public slides = []; constructor() { - this.slides.push( - { text: 'Slide 1', active: false }, - { text: 'Slide 2', active: false }, - { text: 'Slide 3', active: true }, - { text: 'Slide 4', active: false } - ); + this.slides.push({ text: 'Slide 1', active: false }, { text: 'Slide 2', active: false }, { text: 'Slide 3', active: true }, { text: 'Slide 4', active: false }); } public removeAllSlides() { @@ -1283,9 +1281,6 @@ class CarouselDynamicSlidesComponent { } public addSlides() { - this.slides.push( - { text: 'Slide 1' }, - { text: 'Slide 2' } - ); + this.slides.push({ text: 'Slide 1' }, { text: 'Slide 2' }); } } diff --git a/projects/igniteui-angular/chat-extras/src/markdown-pipe.spec.ts b/projects/igniteui-angular/chat-extras/src/markdown-pipe.spec.ts index 93611cdb4d9..87e20f5ebdd 100644 --- a/projects/igniteui-angular/chat-extras/src/markdown-pipe.spec.ts +++ b/projects/igniteui-angular/chat-extras/src/markdown-pipe.spec.ts @@ -2,7 +2,7 @@ import { DomSanitizer } from '@angular/platform-browser'; import { TestBed } from '@angular/core/testing'; import { IgxChatMarkdownService } from './markdown-service'; import { MarkdownPipe } from './markdown-pipe'; -import Spy = jasmine.Spy; +import { describe, it, expect, beforeEach, vi } from 'vitest'; // Mock the Service: We trust the service to provide safe HTML from Shiki. const mockSafeHtml = ` @@ -19,7 +19,7 @@ class MockChatMarkdownService { describe('MarkdownPipe', () => { let pipe: MarkdownPipe; let sanitizer: DomSanitizer; - let bypassSpy: Spy; + let bypassSpy: ReturnType; beforeEach(() => { TestBed.configureTestingModule({ @@ -31,7 +31,7 @@ describe('MarkdownPipe', () => { pipe = TestBed.inject(MarkdownPipe); sanitizer = TestBed.inject(DomSanitizer); - bypassSpy = spyOn(sanitizer, 'bypassSecurityTrustHtml').and.callThrough(); + bypassSpy = vi.spyOn(sanitizer, 'bypassSecurityTrustHtml'); }); it('should be created', () => { @@ -58,6 +58,6 @@ describe('MarkdownPipe', () => { it('should handle undefined input text', async () => { await pipe.transform(undefined); - expect(sanitizer.bypassSecurityTrustHtml).toHaveBeenCalled(); + expect(bypassSpy).toHaveBeenCalled(); }); }); diff --git a/projects/igniteui-angular/chat-extras/src/markdown-service.spec.ts b/projects/igniteui-angular/chat-extras/src/markdown-service.spec.ts index a54b1f30db4..1bdf2e5e97e 100644 --- a/projects/igniteui-angular/chat-extras/src/markdown-service.spec.ts +++ b/projects/igniteui-angular/chat-extras/src/markdown-service.spec.ts @@ -1,5 +1,6 @@ import { TestBed } from '@angular/core/testing'; import { IgxChatMarkdownService } from './markdown-service'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('IgxChatMarkdownService', () => { let service: IgxChatMarkdownService; diff --git a/projects/igniteui-angular/chat/src/chat.spec.ts b/projects/igniteui-angular/chat/src/chat.spec.ts index 2977d06f194..0c9db068cd2 100644 --- a/projects/igniteui-angular/chat/src/chat.spec.ts +++ b/projects/igniteui-angular/chat/src/chat.spec.ts @@ -1,7 +1,8 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing' -import { IgxChatComponent, IgxChatMessageContextDirective, type IgxChatTemplates } from './chat.component' +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { IgxChatComponent, IgxChatMessageContextDirective, type IgxChatTemplates } from './chat.component'; import { Component, signal, TemplateRef, viewChild } from '@angular/core'; import type { IgcChatComponent, IgcChatMessage, IgcTextareaComponent } from 'igniteui-webcomponents'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Chat wrapper', () => { @@ -20,7 +21,7 @@ describe('Chat wrapper', () => { chatComponent = fixture.componentInstance; chatElement = getChatElement(fixture); fixture.detectChanges(); - }) + }); it('is created', () => { expect(chatComponent).toBeDefined(); @@ -127,10 +128,10 @@ describe('Chat dynamic templates binding', () => { }) class ChatTemplatesBed { public messages = signal([{ - id: '1', - sender: 'user', - text: 'Hello world' - }]); + id: '1', + sender: 'user', + text: 'Hello world' + }]); public messageTemplate = viewChild.required>('message'); } @@ -146,10 +147,10 @@ class ChatTemplatesBed { class ChatDynamicTemplatesBed { public templates = signal(null); public messages = signal([{ - id: '1', - sender: 'user', - text: 'Hello world' - }]); + id: '1', + sender: 'user', + text: 'Hello world' + }]); public messageTemplate = viewChild.required>('message'); public bindTemplates(): void { diff --git a/projects/igniteui-angular/checkbox/src/checkbox/checkbox.component.spec.ts b/projects/igniteui-angular/checkbox/src/checkbox/checkbox.component.spec.ts index 1c0cd7e15f7..5c391cb0946 100644 --- a/projects/igniteui-angular/checkbox/src/checkbox/checkbox.component.spec.ts +++ b/projects/igniteui-angular/checkbox/src/checkbox/checkbox.component.spec.ts @@ -5,6 +5,7 @@ import { By } from '@angular/platform-browser'; import { IgxCheckboxComponent } from './checkbox.component'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('IgxCheckbox', () => { beforeEach(waitForAsync(() => { @@ -417,7 +418,8 @@ describe('IgxCheckbox', () => { imports: [IgxCheckboxComponent] }) class InitCheckboxComponent { - @ViewChild('cb', { static: true }) public cb: IgxCheckboxComponent; + @ViewChild('cb', { static: true }) + public cb: IgxCheckboxComponent; } @Component({ @@ -426,7 +428,8 @@ class InitCheckboxComponent { imports: [IgxCheckboxComponent, FormsModule] }) class CheckboxSimpleComponent { - @ViewChild('cb', { static: true }) public cb: IgxCheckboxComponent; + @ViewChild('cb', { static: true }) + public cb: IgxCheckboxComponent; public changeEventCalled = false; public subscribed = false; public clickCounter = 0; @@ -445,7 +448,8 @@ class CheckboxSimpleComponent { imports: [IgxCheckboxComponent, FormsModule] }) class CheckboxIndeterminateComponent { - @ViewChild('cb', { static: true }) public cb: IgxCheckboxComponent; + @ViewChild('cb', { static: true }) + public cb: IgxCheckboxComponent; public subscribed = false; } @@ -455,7 +459,8 @@ class CheckboxIndeterminateComponent { imports: [IgxCheckboxComponent] }) class CheckboxRequiredComponent { - @ViewChild('cb', { static: true }) public cb: IgxCheckboxComponent; + @ViewChild('cb', { static: true }) + public cb: IgxCheckboxComponent; } @Component({ @@ -467,7 +472,8 @@ class CheckboxRequiredComponent { imports: [IgxCheckboxComponent, FormsModule] }) class CheckboxReadonlyComponent { - @ViewChild('cb', { static: true }) public cb: IgxCheckboxComponent; + @ViewChild('cb', { static: true }) + public cb: IgxCheckboxComponent; public subscribed = false; } @@ -478,7 +484,8 @@ class CheckboxReadonlyComponent { imports: [IgxCheckboxComponent] }) class CheckboxExternalLabelComponent { - @ViewChild('cb', { static: true }) public cb: IgxCheckboxComponent; + @ViewChild('cb', { static: true }) + public cb: IgxCheckboxComponent; public label = 'My Label'; } @@ -487,7 +494,8 @@ class CheckboxExternalLabelComponent { imports: [IgxCheckboxComponent] }) class CheckboxInvisibleLabelComponent { - @ViewChild('cb', { static: true }) public cb: IgxCheckboxComponent; + @ViewChild('cb', { static: true }) + public cb: IgxCheckboxComponent; public label = 'Invisible Label'; } @@ -496,7 +504,8 @@ class CheckboxInvisibleLabelComponent { imports: [IgxCheckboxComponent] }) class CheckboxDisabledTransitionsComponent { - @ViewChild('cb', { static: true }) public cb: IgxCheckboxComponent; + @ViewChild('cb', { static: true }) + public cb: IgxCheckboxComponent; } @Component({ @@ -506,7 +515,8 @@ class CheckboxDisabledTransitionsComponent { class CheckboxFormGroupComponent { private fb = inject(UntypedFormBuilder); - @ViewChild('cb', { static: true }) public cb: IgxCheckboxComponent; + @ViewChild('cb', { static: true }) + public cb: IgxCheckboxComponent; public myForm = this.fb.group({ checkbox: ['', Validators.required] }); } diff --git a/projects/igniteui-angular/chips/src/chips/chip.spec.ts b/projects/igniteui-angular/chips/src/chips/chip.spec.ts index b7c54bf7951..53aaf980cff 100644 --- a/projects/igniteui-angular/chips/src/chips/chip.spec.ts +++ b/projects/igniteui-angular/chips/src/chips/chip.spec.ts @@ -10,6 +10,7 @@ import { IgxIconComponent } from 'igniteui-angular/icon'; import { getComponentSize } from 'igniteui-angular/core'; import { ControlsFunction } from 'igniteui-angular/test-utils/controls-functions.spec'; import { UIInteractions, wait } from 'igniteui-angular/test-utils/ui-interactions.spec'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; @Component({ template: ` @@ -133,7 +134,7 @@ describe('IgxChip', () => { const igxChipItem = igxChip[1].nativeElement; const chipRemoveButton = ControlsFunction.getChipRemoveButton(igxChipItem); - expect(igxChipItem.children[0].children[2].children[0]).toHaveClass('igx-chip__remove'); + expect(igxChipItem.children[0].children[2].children[0].classList.contains('igx-chip__remove')).toBe(true); expect(chipRemoveButton).toBeTruthy(); }); @@ -148,7 +149,7 @@ describe('IgxChip', () => { fixture.detectChanges(); expect(igxChip.variant).toMatch('danger'); - expect(igxChip.nativeElement).toHaveClass('igx-chip--danger'); + expect(igxChip.nativeElement.classList.contains('igx-chip--danger')).toBe(true); }); it('should set text in chips correctly', () => { @@ -219,7 +220,7 @@ describe('IgxChip', () => { it('should not trigger remove event when delete button is pressed when not removable', () => { const firstChipComp = fix.componentInstance.chips.toArray()[0]; - spyOn(firstChipComp.remove, 'emit'); + vi.spyOn(firstChipComp.remove, 'emit'); UIInteractions.triggerKeyDownEvtUponElem('Delete', firstChipComp.chipArea.nativeElement, true); fix.detectChanges(); @@ -229,7 +230,7 @@ describe('IgxChip', () => { it('should trigger remove event when delete button is pressed when removable', () => { const secondChipComp = fix.componentInstance.chips.toArray()[1]; - spyOn(secondChipComp.remove, 'emit'); + vi.spyOn(secondChipComp.remove, 'emit'); UIInteractions.triggerKeyDownEvtUponElem('Delete', secondChipComp.chipArea.nativeElement, true); fix.detectChanges(); @@ -290,8 +291,8 @@ describe('IgxChip', () => { it('should fire selectedChanging event when selectable is true', () => { const secondChipComp = fix.componentInstance.chips.toArray()[1]; - spyOn(secondChipComp.selectedChanging, 'emit'); - spyOn(secondChipComp.selectedChanged, 'emit'); + vi.spyOn(secondChipComp.selectedChanging, 'emit'); + vi.spyOn(secondChipComp.selectedChanged, 'emit'); UIInteractions.triggerKeyDownEvtUponElem(' ', secondChipComp.chipArea.nativeElement, true); fix.detectChanges(); @@ -305,7 +306,7 @@ describe('IgxChip', () => { }); expect(secondChipComp.selectedChanging.emit).toHaveBeenCalledWith({ - originalEvent: jasmine.anything(), + originalEvent: expect.anything(), owner: secondChipComp, cancel: false, selected: true @@ -316,8 +317,8 @@ describe('IgxChip', () => { pending('This should be tested in the e2e test'); const secondChipComp: IgxChipComponent = fix.componentInstance.chips.toArray()[1]; - spyOn(secondChipComp.selectedChanging, 'emit'); - spyOn(secondChipComp.selectedChanged, 'emit'); + vi.spyOn(secondChipComp.selectedChanging, 'emit'); + vi.spyOn(secondChipComp.selectedChanged, 'emit'); secondChipComp.chipArea.nativeElement.focus(); UIInteractions.triggerKeyDownEvtUponElem(' ', secondChipComp.chipArea.nativeElement, true); @@ -342,8 +343,8 @@ describe('IgxChip', () => { it('should not fire selectedChanging event when selectable is false', () => { const firstChipComp: IgxChipComponent = fix.componentInstance.chips.toArray()[0]; - spyOn(firstChipComp.selectedChanging, 'emit'); - spyOn(firstChipComp.selectedChanged, 'emit'); + vi.spyOn(firstChipComp.selectedChanging, 'emit'); + vi.spyOn(firstChipComp.selectedChanged, 'emit'); firstChipComp.nativeElement.focus(); UIInteractions.triggerKeyDownEvtUponElem(' ', firstChipComp.chipArea.nativeElement, true); @@ -355,8 +356,8 @@ describe('IgxChip', () => { it('should not fire selectedChanging event when the remove button is clicked', () => { const secondChipComp: IgxChipComponent = fix.componentInstance.chips.toArray()[1]; - spyOn(secondChipComp.selectedChanging, 'emit'); - spyOn(secondChipComp.selectedChanged, 'emit'); + vi.spyOn(secondChipComp.selectedChanging, 'emit'); + vi.spyOn(secondChipComp.selectedChanged, 'emit'); const chipRemoveButton = ControlsFunction.getChipRemoveButton(secondChipComp.chipArea.nativeElement); diff --git a/projects/igniteui-angular/chips/src/chips/chips-area.spec.ts b/projects/igniteui-angular/chips/src/chips/chips-area.spec.ts index 75cd1090f56..f62002859a5 100644 --- a/projects/igniteui-angular/chips/src/chips/chips-area.spec.ts +++ b/projects/igniteui-angular/chips/src/chips/chips-area.spec.ts @@ -1,4 +1,4 @@ -import { Component, ViewChild, ViewChildren, QueryList, ChangeDetectorRef, inject } from '@angular/core'; +import { Component, ViewChild, ViewChildren, QueryList, ChangeDetectorRef, inject } from '@angular/core'; import { TestBed, waitForAsync } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { IgxChipComponent } from './chip.component'; @@ -6,6 +6,7 @@ import { IgxChipsAreaComponent } from './chips-area.component'; import { IgxIconComponent } from 'igniteui-angular/icon'; import { IgxPrefixDirective } from 'igniteui-angular/input-group'; import { UIInteractions, wait } from 'igniteui-angular/test-utils/ui-interactions.spec'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; @Component({ @@ -40,13 +41,13 @@ class TestChipComponent { @Component({ template: ` - + first chip - + second chip - + third chip @@ -127,7 +128,9 @@ describe('IgxChipsArea ', () => { }); it('should add chips when adding data items ', () => { - expect(chipAreaElement.nativeElement.classList).toEqual(jasmine.arrayWithExactContents(['customClass', CHIP_AREA_CLASS])); + // TODO: vitest-migration: Verify this matches strict array content (multiset equality). Vitest's arrayContaining is a subset check. + expect(chipAreaElement.nativeElement.classList).toHaveLength(2); + expect(chipAreaElement.nativeElement.classList).toEqual(expect.arrayContaining(['customClass', CHIP_AREA_CLASS])); expect(chipAreaElement.nativeElement.children.length).toEqual(2); fix.componentInstance.chipList.push({ id: 'Town', text: 'Town', removable: true, selectable: true, draggable: true }); @@ -177,7 +180,7 @@ describe('IgxChipsArea ', () => { fix = TestBed.createComponent(TestChipSelectComponent); chipArea = fix.componentInstance.chipsArea; - spyOn(chipArea.selectionChange, 'emit'); + vi.spyOn(chipArea.selectionChange, 'emit'); fix.detectChanges(); @@ -235,7 +238,7 @@ describe('IgxChipsArea ', () => { const secondChipComp: IgxChipComponent = fix.componentInstance.chips.toArray()[1]; const chipAreaComp: IgxChipsAreaComponent = fix.debugElement.query(By.directive(IgxChipsAreaComponent)).componentInstance; - spyOn(chipAreaComp.selectionChange, 'emit'); + vi.spyOn(chipAreaComp.selectionChange, 'emit'); secondChipComp.onChipKeyDown(spaceKeyEvent); fix.detectChanges(); @@ -273,7 +276,7 @@ describe('IgxChipsArea ', () => { chipAreaComponent.chipList.push({ id: 'Town', text: 'Town', removable: true, selectable: true, draggable: true }); fix.detectChanges(); - spyOn(chipAreaComponent.chipsArea.selectionChange, `emit`); + vi.spyOn(chipAreaComponent.chipsArea.selectionChange, `emit`); chipAreaComponent.chipsArea.chipsList.toArray()[1].selected = true; fix.detectChanges(); chipAreaComponent.chipsArea.chipsList.toArray()[2].selected = true; @@ -306,7 +309,7 @@ describe('IgxChipsArea ', () => { fix = TestBed.createComponent(TestChipSelectComponent); chipArea = fix.componentInstance.chipsArea; - spyOn(chipArea.selectionChange, 'emit'); + vi.spyOn(chipArea.selectionChange, 'emit'); fix.detectChanges(); @@ -329,7 +332,7 @@ describe('IgxChipsArea ', () => { fix.detectChanges(); expect(igxChip.selected).toBe(true); - expect(igxChipItem).toHaveClass(`igx-chip__item--selected`); + expect(igxChipItem.classList.contains(`igx-chip__item--selected`)).toBe(true); }); it('should fire only onSelection event for chip area when selecting a chip using spacebar', () => { @@ -340,10 +343,10 @@ describe('IgxChipsArea ', () => { chipArea = fix.componentInstance.chipsArea; const secondChip = fix.componentInstance.chips.toArray()[1]; - spyOn(chipArea.reorder, 'emit'); - spyOn(chipArea.selectionChange, 'emit'); - spyOn(chipArea.moveStart, 'emit'); - spyOn(chipArea.moveEnd, 'emit'); + vi.spyOn(chipArea.reorder, 'emit'); + vi.spyOn(chipArea.selectionChange, 'emit'); + vi.spyOn(chipArea.moveStart, 'emit'); + vi.spyOn(chipArea.moveEnd, 'emit'); secondChip.onChipKeyDown(spaceKeyEvent); @@ -363,7 +366,7 @@ describe('IgxChipsArea ', () => { const secondChip = fix.componentInstance.chips.toArray()[1]; const pointerUpEvt = new PointerEvent('pointerup'); - spyOn(chipArea.selectionChange, 'emit'); + vi.spyOn(chipArea.selectionChange, 'emit'); fix.detectChanges(); secondChip.onChipDragClicked({ @@ -437,44 +440,42 @@ describe('IgxChipsArea ', () => { expect(newSecondChipLeft).toEqual(secondChipLeft); }); - it('should reorder chips and keeps focus when Shift + Left Arrow is pressed and Shift + Right Arrow is pressed twice', - (async () => { - chipArea = fix.componentInstance.chipsArea; - const chipComponents = fix.debugElement.queryAll(By.directive(IgxChipComponent)); - const targetChip = chipComponents[2].componentInstance; - const targetChipElem = targetChip.nativeElement; + it('should reorder chips and keeps focus when Shift + Left Arrow is pressed and Shift + Right Arrow is pressed twice', (async () => { + chipArea = fix.componentInstance.chipsArea; + const chipComponents = fix.debugElement.queryAll(By.directive(IgxChipComponent)); + const targetChip = chipComponents[2].componentInstance; + const targetChipElem = targetChip.nativeElement; - targetChipElem.focus(); - fix.detectChanges(); + targetChipElem.focus(); + fix.detectChanges(); - expect(document.activeElement).toBe(targetChipElem); - expect(chipArea.chipsList.toArray()[2].id).toEqual('Town'); - expect(chipArea.chipsList.toArray()[3].id).toEqual('FirstName'); + expect(document.activeElement).toBe(targetChipElem); + expect(chipArea.chipsList.toArray()[2].id).toEqual('Town'); + expect(chipArea.chipsList.toArray()[3].id).toEqual('FirstName'); - targetChip.onChipKeyDown(rightKeyEvent); - fix.detectChanges(); + targetChip.onChipKeyDown(rightKeyEvent); + fix.detectChanges(); - expect(document.activeElement).toBe(targetChipElem); - expect(chipArea.chipsList.toArray()[2].id).toEqual('FirstName'); - expect(chipArea.chipsList.toArray()[3].id).toEqual('Town'); + expect(document.activeElement).toBe(targetChipElem); + expect(chipArea.chipsList.toArray()[2].id).toEqual('FirstName'); + expect(chipArea.chipsList.toArray()[3].id).toEqual('Town'); - targetChip.onChipKeyDown(leftKeyEvent); - fix.detectChanges(); - await wait(); + targetChip.onChipKeyDown(leftKeyEvent); + fix.detectChanges(); + await wait(); - expect(document.activeElement).toBe(targetChipElem); - expect(chipArea.chipsList.toArray()[2].id).toEqual('Town'); - expect(chipArea.chipsList.toArray()[3].id).toEqual('FirstName'); + expect(document.activeElement).toBe(targetChipElem); + expect(chipArea.chipsList.toArray()[2].id).toEqual('Town'); + expect(chipArea.chipsList.toArray()[3].id).toEqual('FirstName'); - targetChip.onChipKeyDown(leftKeyEvent); - fix.detectChanges(); - await wait(); + targetChip.onChipKeyDown(leftKeyEvent); + fix.detectChanges(); + await wait(); - expect(document.activeElement).toBe(targetChipElem); - expect(chipArea.chipsList.toArray()[2].id).toEqual('City'); - expect(chipArea.chipsList.toArray()[3].id).toEqual('FirstName'); - }) - ); + expect(document.activeElement).toBe(targetChipElem); + expect(chipArea.chipsList.toArray()[2].id).toEqual('City'); + expect(chipArea.chipsList.toArray()[3].id).toEqual('FirstName'); + })); it('should not reorder chips for shift + leftarrow when the chip is going out of bounds', () => { const chipComponents = fix.debugElement.queryAll(By.directive(IgxChipComponent)); @@ -529,11 +530,11 @@ describe('IgxChipsArea ', () => { chipArea = fix.componentInstance.chipsArea; const secondChip = fix.componentInstance.chips.toArray()[1]; - spyOn(chipArea.reorder, 'emit'); - spyOn(chipArea.selectionChange, 'emit'); - spyOn(chipArea.moveStart, 'emit'); - spyOn(chipArea.moveEnd, 'emit'); - spyOn(secondChip.remove, 'emit'); + vi.spyOn(chipArea.reorder, 'emit'); + vi.spyOn(chipArea.selectionChange, 'emit'); + vi.spyOn(chipArea.moveStart, 'emit'); + vi.spyOn(chipArea.moveEnd, 'emit'); + vi.spyOn(secondChip.remove, 'emit'); secondChip.onChipKeyDown(deleteKeyEvent); fix.detectChanges(); @@ -640,7 +641,7 @@ describe('IgxChipsArea ', () => { fix.detectChanges(); const firstChipComp: IgxChipComponent = fix.componentInstance.chips.toArray()[1]; - spyOn(firstChipComp.chipClick, 'emit'); + vi.spyOn(firstChipComp.chipClick, 'emit'); UIInteractions.clickDragDirective(fix, firstChipComp.dragDirective); diff --git a/projects/igniteui-angular/combo/src/combo/combo.component.spec.ts b/projects/igniteui-angular/combo/src/combo/combo.component.spec.ts index 3f3be0f1da7..3e0a4b03f3e 100644 --- a/projects/igniteui-angular/combo/src/combo/combo.component.spec.ts +++ b/projects/igniteui-angular/combo/src/combo/combo.component.spec.ts @@ -1,9 +1,8 @@ +import type { Mock } from "vitest"; import { AsyncPipe } from '@angular/common'; import { AfterViewInit, ChangeDetectorRef, Component, DebugElement, ElementRef, Injectable, Injector, OnDestroy, OnInit, ViewChild, inject } from '@angular/core'; import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing'; -import { - FormsModule, NgForm, NgModel, ReactiveFormsModule, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators -} from '@angular/forms'; +import { FormsModule, NgForm, NgModel, ReactiveFormsModule, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms'; import { By } from '@angular/platform-browser'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { BehaviorSubject, Observable, firstValueFrom } from 'rxjs'; @@ -19,14 +18,13 @@ import { IgxComboAddItemComponent } from './combo-add-item.component'; import { IgxComboDropDownComponent } from './combo-dropdown.component'; import { IgxComboItemComponent } from './combo-item.component'; import { IComboFilteringOptions, IGX_COMBO_COMPONENT } from './combo.common'; -import { - IComboItemAdditionEvent, IComboSearchInputEventArgs, IComboSelectionChangingEventArgs, IgxComboComponent -} from './combo.component'; +import { IComboItemAdditionEvent, IComboSearchInputEventArgs, IComboSelectionChangingEventArgs, IgxComboComponent } from './combo.component'; import { IgxComboFooterDirective, IgxComboHeaderDirective, IgxComboItemDirective } from './combo.directives'; import { IgxComboFilteringPipe, comboIgnoreDiacriticsFilter } from './combo.pipes'; import { IgxDropDownItemBaseDirective } from '../../../drop-down/src/drop-down/drop-down-item.base'; import { UIInteractions, wait } from 'igniteui-angular/test-utils/ui-interactions.spec'; import { IgxComboAPIService } from './combo.api'; +import { describe, it, expect, beforeEach, afterAll, vi } from 'vitest'; const CSS_CLASS_COMBO = 'igx-combo'; const CSS_CLASS_COMBO_DROPDOWN = 'igx-combo__drop-down'; @@ -77,15 +75,31 @@ describe('igxCombo', () => { ]; const elementRef = { nativeElement: null }; const mockSelection: { - [key: string]: jasmine.Spy; - } = jasmine.createSpyObj('IgxSelectionAPIService', ['get', 'set', 'add_items', 'select_items', 'delete']); - const mockCdr = jasmine.createSpyObj('ChangeDetectorRef', ['markForCheck', 'detectChanges']); - const mockComboService = jasmine.createSpyObj('IgxComboAPIService', ['register', 'clear']); - const mockNgControl = jasmine.createSpyObj('NgControl', ['registerOnChangeCb', 'registerOnTouchedCb']); - const mockInjector = jasmine.createSpyObj('Injector', ['get']); - mockInjector.get.and.returnValue(mockNgControl); - mockSelection.get.and.returnValue(new Set([])); - jasmine.getEnv().allowRespy(true); + [key: string]: Mock; + } = { + get: vi.fn().mockName("IgxSelectionAPIService.get"), + set: vi.fn().mockName("IgxSelectionAPIService.set"), + add_items: vi.fn().mockName("IgxSelectionAPIService.add_items"), + select_items: vi.fn().mockName("IgxSelectionAPIService.select_items"), + delete: vi.fn().mockName("IgxSelectionAPIService.delete") + }; + const mockCdr = { + markForCheck: vi.fn().mockName("ChangeDetectorRef.markForCheck"), + detectChanges: vi.fn().mockName("ChangeDetectorRef.detectChanges") + }; + const mockComboService = { + register: vi.fn().mockName("IgxComboAPIService.register"), + clear: vi.fn().mockName("IgxComboAPIService.clear") + }; + const mockNgControl = { + registerOnChangeCb: vi.fn().mockName("NgControl.registerOnChangeCb"), + registerOnTouchedCb: vi.fn().mockName("NgControl.registerOnTouchedCb") + }; + const mockInjector = { + get: vi.fn().mockName("Injector.get") + }; + mockInjector.get.mockReturnValue(mockNgControl); + mockSelection.get.mockReturnValue(new Set([])); beforeEach(() => { TestBed.configureTestingModule({ @@ -100,13 +114,13 @@ describe('igxCombo', () => { ] }) .overrideComponent(IgxComboComponent, { - set: { - providers: [ - { provide: IgxComboAPIService, useValue: mockComboService }, - { provide: IGX_COMBO_COMPONENT, useExisting: IgxComboComponent } - ] - } - }) + set: { + providers: [ + { provide: IgxComboAPIService, useValue: mockComboService }, + { provide: IGX_COMBO_COMPONENT, useExisting: IgxComboComponent } + ] + } + }) .compileComponents(); fixture = TestBed.createComponent(IgxComboComponent); @@ -122,10 +136,6 @@ describe('igxCombo', () => { } }); - afterAll(() => { - jasmine.getEnv().allowRespy(false); - }); - it('should correctly implement interface methods - ControlValueAccessor ', () => { combo.ngOnInit(); expect(combo['ngControl']).toBeDefined(); @@ -134,8 +144,8 @@ describe('igxCombo', () => { // writeValue expect(combo.displayValue).toEqual(''); - mockSelection.get.and.returnValue(new Set(['test'])); - spyOnProperty(combo, 'isRemote').and.returnValue(false); + mockSelection.get.mockReturnValue(new Set(['test'])); + vi.spyOn(combo as any, 'isRemote').mockReturnValue(false); combo.writeValue(['test']); expect(mockNgControl.registerOnChangeCb).not.toHaveBeenCalled(); expect(mockSelection.select_items).toHaveBeenCalledWith(combo.id, ['test'], true); @@ -149,37 +159,41 @@ describe('igxCombo', () => { expect(combo.disabled).toBe(false); // OnChange callback - mockSelection.add_items.and.returnValue(new Set(['simpleValue'])); + mockSelection.add_items.mockReturnValue(new Set(['simpleValue'])); combo.select(['simpleValue']); expect(mockSelection.add_items).toHaveBeenCalledWith(combo.id, ['simpleValue'], undefined); expect(mockSelection.select_items).toHaveBeenCalledWith(combo.id, ['simpleValue'], true); expect(mockNgControl.registerOnChangeCb).toHaveBeenCalledWith(['simpleValue']); // OnTouched callback - spyOnProperty(combo, 'collapsed').and.returnValue(true); - spyOnProperty(combo, 'valid', 'set'); + vi.spyOn(combo as any, 'collapsed').mockReturnValue(true); + vi.spyOn(combo, 'valid', 'set'); combo.onBlur(); expect(mockNgControl.registerOnTouchedCb).toHaveBeenCalledTimes(1); }); it('should properly call dropdown methods on toggle', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['open', 'close', 'toggle']); + const dropdown = { + open: vi.fn().mockName("IgxComboDropDownComponent.open"), + close: vi.fn().mockName("IgxComboDropDownComponent.close"), + toggle: vi.fn().mockName("IgxComboDropDownComponent.toggle") + }; combo.ngOnInit(); - combo.dropdown = dropdown; - dropdown.collapsed = true; + combo.dropdown = dropdown as any; + (dropdown as any).collapsed = true; combo.open(); - dropdown.collapsed = false; + (dropdown as any).collapsed = false; expect(combo.dropdown.open).toHaveBeenCalledTimes(1); expect(combo.collapsed).toBe(false); combo.close(); - dropdown.collapsed = true; + (dropdown as any).collapsed = true; expect(combo.dropdown.close).toHaveBeenCalledTimes(1); expect(combo.collapsed).toBe(true); combo.toggle(); - dropdown.collapsed = false; + (dropdown as any).collapsed = false; expect(combo.dropdown.toggle).toHaveBeenCalledTimes(1); expect(combo.collapsed).toBe(false); }); @@ -187,7 +201,7 @@ describe('igxCombo', () => { const dropdownContainer = { nativeElement: { focus: () => { } } }; combo['dropdownContainer'] = dropdownContainer; - spyOn(combo, 'focusSearchInput'); + vi.spyOn(combo, 'focusSearchInput'); combo.autoFocusSearch = false; combo.handleOpened(); @@ -203,9 +217,11 @@ describe('igxCombo', () => { }); it('should call dropdown toggle with correct overlaySettings', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['toggle']); + const dropdown = { + toggle: vi.fn().mockName("IgxComboDropDownComponent.toggle") + }; combo.ngOnInit(); - combo.dropdown = dropdown; + combo.dropdown = dropdown as any; const defaultSettings = (combo as any)._overlaySettings; combo.toggle(); expect(combo.dropdown.toggle).toHaveBeenCalledWith(defaultSettings || {}); @@ -231,8 +247,8 @@ describe('igxCombo', () => { combo.ngOnInit(); combo.data = data; - mockSelection.select_items.calls.reset(); - spyOnProperty(combo, 'isRemote').and.returnValue(false); + mockSelection.select_items.mockClear(); + vi.spyOn(combo as any, 'isRemote').mockReturnValue(false); combo.writeValue(['EXAMPLE']); expect(mockSelection.select_items).toHaveBeenCalledTimes(1); @@ -247,8 +263,8 @@ describe('igxCombo', () => { it('should emit owner on `opening` and `closing`', () => { combo.ngOnInit(); - spyOn(combo.opening, 'emit').and.callThrough(); - spyOn(combo.closing, 'emit').and.callThrough(); + vi.spyOn(combo.opening, 'emit'); + vi.spyOn(combo.closing, 'emit'); const mockObj = {}; const mockEvent = new Event('mock'); const inputEvent: IBaseCancelableBrowserEventArgs = { @@ -311,16 +327,18 @@ describe('igxCombo', () => { }); it('should properly handleInputChange', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']); + const dropdown = { + selectItem: vi.fn().mockName("IgxComboDropDownComponent.selectItem") + }; combo.ngOnInit(); combo.data = data; - combo.dropdown = dropdown; + combo.dropdown = dropdown as any; combo.comboInput = { value: '', } as any; combo.disableFiltering = false; - const matchSpy = spyOn(combo, 'checkMatch').and.callThrough(); - spyOn(combo.searchInputUpdate, 'emit'); + const matchSpy = vi.spyOn(combo as any, 'checkMatch'); + vi.spyOn(combo.searchInputUpdate, 'emit'); combo.handleInputChange(); expect(matchSpy).toHaveBeenCalledTimes(1); @@ -355,8 +373,8 @@ describe('igxCombo', () => { combo.searchInputUpdate.subscribe((e) => { e.cancel = true; }); - const matchSpy = spyOn(combo, 'checkMatch').and.callThrough(); - spyOn(combo.searchInputUpdate, 'emit').and.callThrough(); + const matchSpy = vi.spyOn(combo as any, 'checkMatch'); + vi.spyOn(combo.searchInputUpdate, 'emit'); combo.handleInputChange('Item1'); expect(combo.searchInputUpdate.emit).toHaveBeenCalledTimes(1); @@ -364,14 +382,21 @@ describe('igxCombo', () => { }); it('should not open on click if combo is disabled', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['open', 'close', 'toggle']); - const spyObj = jasmine.createSpyObj('event', ['stopPropagation', 'preventDefault']); + const dropdown = { + open: vi.fn().mockName("IgxComboDropDownComponent.open"), + close: vi.fn().mockName("IgxComboDropDownComponent.close"), + toggle: vi.fn().mockName("IgxComboDropDownComponent.toggle") + }; + const spyObj = { + stopPropagation: vi.fn().mockName("event.stopPropagation"), + preventDefault: vi.fn().mockName("event.preventDefault") + }; combo.ngOnInit(); - combo.dropdown = dropdown; - dropdown.collapsed = true; + combo.dropdown = dropdown as any; + (dropdown as any).collapsed = true; combo.disabled = true; - combo.onClick(spyObj); + combo.onClick(spyObj as any); expect(combo.dropdown.collapsed).toBeTruthy(); }); it('should delete the selection on destroy', () => { @@ -410,12 +435,14 @@ describe('igxCombo', () => { }); it('should select items through setSelctedItem method', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']); + const dropdown = { + selectItem: vi.fn().mockName("IgxComboDropDownComponent.selectItem") + }; combo.ngOnInit(); combo.data = complexData; combo.valueKey = 'country'; - combo.dropdown = dropdown; - spyOnProperty(combo, 'totalItemCount').and.returnValue(combo.data.length); + combo.dropdown = dropdown as any; + vi.spyOn(combo as any, 'totalItemCount').mockReturnValue(combo.data.length); const selectedItems = [combo.data[0]]; const selectedValues = [combo.data[0].country]; @@ -453,11 +480,13 @@ describe('igxCombo', () => { expect(combo.value).toEqual(selectedItems); }); it('should set selectedItems correctly on selectItems method call', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']); + const dropdown = { + selectItem: vi.fn().mockName("IgxComboDropDownComponent.selectItem") + }; combo.ngOnInit(); combo.data = data; - combo.dropdown = dropdown; - spyOnProperty(combo, 'totalItemCount').and.returnValue(combo.data.length); + combo.dropdown = dropdown as any; + vi.spyOn(combo as any, 'totalItemCount').mockReturnValue(combo.data.length); combo.select([], false); expect(combo.selection).toEqual([]); @@ -481,12 +510,14 @@ describe('igxCombo', () => { expect(combo.value).toEqual([]); }); it('should fire selectionChanging event on item selection', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']); + const dropdown = { + selectItem: vi.fn().mockName("IgxComboDropDownComponent.selectItem") + }; combo.ngOnInit(); combo.data = data; - combo.dropdown = dropdown; - spyOnProperty(combo, 'totalItemCount').and.returnValue(combo.data.length); - spyOn(combo.selectionChanging, 'emit'); + combo.dropdown = dropdown as any; + vi.spyOn(combo as any, 'totalItemCount').mockReturnValue(combo.data.length); + vi.spyOn(combo.selectionChanging, 'emit'); let oldValue = []; let newValue = [combo.data[1], combo.data[5], combo.data[6]]; @@ -570,13 +601,15 @@ describe('igxCombo', () => { }); }); it('should properly emit added and removed values in change event on single value selection', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']); + const dropdown = { + selectItem: vi.fn().mockName("IgxComboDropDownComponent.selectItem") + }; combo.ngOnInit(); combo.data = complexData; combo.valueKey = 'country'; - combo.dropdown = dropdown; - spyOnProperty(combo, 'totalItemCount').and.returnValue(combo.data.length); - const selectionSpy = spyOn(combo.selectionChanging, 'emit'); + combo.dropdown = dropdown as any; + vi.spyOn(combo as any, 'totalItemCount').mockReturnValue(combo.data.length); + const selectionSpy = vi.spyOn(combo.selectionChanging, 'emit'); const expectedResults: IComboSelectionChangingEventArgs = { newValue: [combo.data[0][combo.valueKey]], oldValue: [], @@ -604,14 +637,16 @@ describe('igxCombo', () => { expect(selectionSpy).toHaveBeenCalledWith(expectedResults); }); it('should properly emit added and removed values in change event on multiple values selection', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']); + const dropdown = { + selectItem: vi.fn().mockName("IgxComboDropDownComponent.selectItem") + }; combo.ngOnInit(); combo.data = complexData; combo.valueKey = 'country'; combo.displayKey = 'city'; - combo.dropdown = dropdown; - spyOnProperty(combo, 'totalItemCount').and.returnValue(combo.data.length); - const selectionSpy = spyOn(combo.selectionChanging, 'emit'); + combo.dropdown = dropdown as any; + vi.spyOn(combo as any, 'totalItemCount').mockReturnValue(combo.data.length); + const selectionSpy = vi.spyOn(combo.selectionChanging, 'emit'); let oldSelection = []; let newSelection = [combo.data[0], combo.data[1], combo.data[2]]; @@ -659,13 +694,15 @@ describe('igxCombo', () => { expect(selectionSpy).toHaveBeenCalledWith(expectedResults); }); it('should handle select/deselect ALL items', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']); + const dropdown = { + selectItem: vi.fn().mockName("IgxComboDropDownComponent.selectItem") + }; combo.ngOnInit(); combo.data = data; - combo.dropdown = dropdown; - spyOnProperty(combo, 'totalItemCount').and.returnValue(combo.data.length); - spyOn(combo, 'selectAllItems'); - spyOn(combo, 'deselectAllItems'); + combo.dropdown = dropdown as any; + vi.spyOn(combo as any, 'totalItemCount').mockReturnValue(combo.data.length); + vi.spyOn(combo, 'selectAllItems'); + vi.spyOn(combo, 'deselectAllItems'); combo.handleSelectAll({ checked: true }); expect(combo.selectAllItems).toHaveBeenCalledTimes(1); @@ -676,12 +713,14 @@ describe('igxCombo', () => { expect(combo.deselectAllItems).toHaveBeenCalledTimes(1); }); it('should emit onSelectonChange event on select/deselect ALL items method call', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']); + const dropdown = { + selectItem: vi.fn().mockName("IgxComboDropDownComponent.selectItem") + }; combo.ngOnInit(); combo.data = data; combo.dropdown = dropdown; - spyOnProperty(combo, 'totalItemCount').and.returnValue(combo.data.length); - spyOn(combo.selectionChanging, 'emit'); + vi.spyOn(combo, 'totalItemCount').mockReturnValue(combo.data.length); + vi.spyOn(combo.selectionChanging, 'emit'); combo.selectAllItems(true); expect(combo.selection).toEqual(data); @@ -718,12 +757,14 @@ describe('igxCombo', () => { }); }); it('should properly handle selection manipulation through selectionChanging emit', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']); + const dropdown = { + selectItem: vi.fn().mockName("IgxComboDropDownComponent.selectItem") + }; combo.ngOnInit(); combo.data = data; combo.dropdown = dropdown; - spyOnProperty(combo, 'totalItemCount').and.returnValue(combo.data.length); - spyOn(combo.selectionChanging, 'emit').and.callFake((event: IComboSelectionChangingEventArgs) => event.newValue = []); + vi.spyOn(combo, 'totalItemCount').mockReturnValue(combo.data.length); + vi.spyOn(combo.selectionChanging, 'emit').mockImplementation((event: IComboSelectionChangingEventArgs) => event.newValue = []); // No items are initially selected expect(combo.selection).toEqual([]); // Select the first 5 items @@ -732,13 +773,17 @@ describe('igxCombo', () => { expect(combo.selection).toEqual([]); }); it('should not clear value when combo is disabled', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']); - const spyObj = jasmine.createSpyObj('event', ['stopPropagation']); + const dropdown = { + selectItem: vi.fn().mockName("IgxComboDropDownComponent.selectItem") + }; + const spyObj = { + stopPropagation: vi.fn().mockName("event.stopPropagation") + }; combo.ngOnInit(); combo.data = data; combo.dropdown = dropdown; combo.disabled = true; - spyOnProperty(combo, 'totalItemCount').and.returnValue(combo.data.length); + vi.spyOn(combo, 'totalItemCount').mockReturnValue(combo.data.length); const item = combo.data.slice(0, 1); combo.select(item, true); @@ -746,13 +791,23 @@ describe('igxCombo', () => { expect(combo.displayValue).toEqual(item[0]); }); it('should allow canceling and overwriting of item addition', fakeAsync(() => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']); - const mockVirtDir = jasmine.createSpyObj('virtDir', ['scrollTo']); - const mockInput = jasmine.createSpyObj('mockInput', [], { - nativeElement: jasmine.createSpyObj('mockElement', ['focus']) - }); - spyOn(combo.addition, 'emit').and.callThrough(); - const subParams: { cancel: boolean; newValue: string; modify: boolean } = { + const dropdown = { + selectItem: vi.fn().mockName("IgxComboDropDownComponent.selectItem") + }; + const mockVirtDir = { + scrollTo: vi.fn().mockName("virtDir.scrollTo") + }; + const mockInput = { + nativeElement: { + focus: vi.fn().mockName("mockElement.focus") + } + }; + vi.spyOn(combo.addition, 'emit'); + const subParams: { + cancel: boolean; + newValue: string; + modify: boolean; + } = { cancel: false, modify: false, newValue: 'mockValue' @@ -1016,7 +1071,7 @@ describe('igxCombo', () => { fixture.detectChanges(); verifyDropdownItemHeight(); })); - it('should render grouped items properly', (done) => { + it('should render grouped items properly', async () => { let dropdownContainer; let dropdownItems; let scrollIndex = 0; @@ -1041,7 +1096,7 @@ describe('igxCombo', () => { checkGroupedItemsClass(); }); } else { - done(); + ; } }; checkGroupedItemsClass(); @@ -1166,7 +1221,7 @@ describe('igxCombo', () => { expect(combo.id).toEqual("id1"); fixture.detectChanges(); - const errorSpy = spyOn(console, 'error'); + const errorSpy = vi.spyOn(console, 'error'); fixture.detectChanges(); expect(errorSpy).not.toHaveBeenCalled(); @@ -1374,7 +1429,9 @@ describe('igxCombo', () => { }); it('should bind combo data to remote data and clear selection properly', async () => { let selectedItems = [combo.data[0], combo.data[1]]; - const spyObj = jasmine.createSpyObj('event', ['stopPropagation']); + const spyObj = { + stopPropagation: vi.fn().mockName("event.stopPropagation") + }; combo.toggle(); combo.select([selectedItems[0][combo.valueKey], selectedItems[1][combo.valueKey]]); expect(combo.displayValue).toEqual(`${selectedItems[0][combo.displayKey]}, ${selectedItems[1][combo.displayKey]}`); @@ -1424,7 +1481,7 @@ describe('igxCombo', () => { expect(combo.displayValue).toEqual(`${firstItem[combo.displayKey]}, ${secondItem[combo.displayKey]}`); }); it('should fire selectionChanging event with partial data for items out of view', async () => { - const selectionSpy = spyOn(combo.selectionChanging, 'emit').and.callThrough(); + const selectionSpy = vi.spyOn(combo.selectionChanging, 'emit'); const valueKey = combo.valueKey; combo.toggle(); @@ -1545,7 +1602,7 @@ describe('igxCombo', () => { expect(dropdown.focusedItem).toBeTruthy(); expect(dropdown.focusedItem.itemIndex).toEqual(1); expect(combo.virtualizationState.startIndex).toEqual(0); - spyOn(dropdown, 'navigatePrev').and.callThrough(); + vi.spyOn(dropdown, 'navigatePrev'); dropdown.navigatePrev(); tick(); expect(dropdown.focusedItem).toBeTruthy(); @@ -1559,9 +1616,12 @@ describe('igxCombo', () => { expect(dropdown.focusedItem).toBeFalsy(); expect(combo.virtualScrollContainer).toBeDefined(); combo.allowCustomValues = true; - const mockClick = jasmine.createSpyObj('event', ['preventDefault', 'stopPropagation']); - const virtualMockUP = spyOn(dropdown, 'navigatePrev').and.callThrough(); - const virtualMockDOWN = spyOn(dropdown, 'navigateNext').and.callThrough(); + const mockClick = { + preventDefault: vi.fn().mockName("event.preventDefault"), + stopPropagation: vi.fn().mockName("event.stopPropagation") + }; + const virtualMockUP = vi.spyOn(dropdown, 'navigatePrev'); + const virtualMockDOWN = vi.spyOn(dropdown, 'navigateNext'); expect(dropdown.focusedItem).toEqual(null); expect(combo.collapsed).toBeTruthy(); combo.toggle(); @@ -1640,9 +1700,9 @@ describe('igxCombo', () => { combo.toggle(); tick(); fixture.detectChanges(); - const virtualSpyUP = spyOn(dropdown, 'navigatePrev'); - const virtualSpyDOWN = spyOn(dropdown, 'navigateNext'); - spyOn(IgxComboDropDownComponent.prototype, 'navigateItem').and.callThrough(); + const virtualSpyUP = vi.spyOn(dropdown, 'navigatePrev'); + const virtualSpyDOWN = vi.spyOn(dropdown, 'navigateNext'); + vi.spyOn(IgxComboDropDownComponent.prototype, 'navigateItem'); dropdown.navigateItem(0); fixture.detectChanges(); expect(IgxComboDropDownComponent.prototype.navigateItem).toHaveBeenCalledTimes(1); @@ -1658,16 +1718,16 @@ describe('igxCombo', () => { combo.toggle(); tick(); fixture.detectChanges(); - spyOn(combo, 'selectAllItems'); - spyOn(combo, 'toggle'); - spyOn(combo.dropdown, 'onFocus').and.callThrough(); + vi.spyOn(combo, 'selectAllItems'); + vi.spyOn(combo, 'toggle'); + vi.spyOn(combo.dropdown, 'onFocus'); combo.handleKeyUp(UIInteractions.getKeyboardEvent('keyup', 'A')); combo.handleKeyUp(UIInteractions.getKeyboardEvent('keyup', null)); expect(combo.selectAllItems).toHaveBeenCalledTimes(0); expect(combo.dropdown.onFocus).toHaveBeenCalledTimes(0); combo.handleKeyUp(UIInteractions.getKeyboardEvent('keyup', 'Enter')); expect(combo.selectAllItems).toHaveBeenCalledTimes(0); - spyOnProperty(combo, 'filteredData', 'get').and.returnValue([1]); + vi.spyOn(combo, 'filteredData', 'get').mockReturnValue([1]); combo.handleKeyUp(UIInteractions.getKeyboardEvent('keyup', 'Enter')); expect(combo.selectAllItems).toHaveBeenCalledTimes(0); combo.handleKeyUp(UIInteractions.getKeyboardEvent('keyup', 'ArrowDown')); @@ -1677,7 +1737,7 @@ describe('igxCombo', () => { expect(combo.toggle).toHaveBeenCalledTimes(1); })); it('should toggle combo dropdown on toggle button click', fakeAsync(() => { - spyOn(combo, 'toggle').and.callThrough(); + vi.spyOn(combo, 'toggle'); input.triggerEventHandler('click', UIInteractions.getMouseEvent('click')); tick(); fixture.detectChanges(); @@ -1692,8 +1752,8 @@ describe('igxCombo', () => { expect(combo.toggle).toHaveBeenCalledTimes(2); })); it('should toggle dropdown list with arrow down/up keys', fakeAsync(() => { - spyOn(combo, 'open').and.callThrough(); - spyOn(combo, 'close').and.callThrough(); + vi.spyOn(combo, 'open'); + vi.spyOn(combo, 'close'); combo.onArrowDown(UIInteractions.getKeyboardEvent('keydown', 'ArrowDown')); tick(); @@ -1862,7 +1922,7 @@ describe('igxCombo', () => { }); it('should properly return a reference to the VirtScrollContainer', () => { expect(combo.dropdown.element).toBeDefined(); - const mockScroll = spyOnProperty(combo.dropdown, 'scrollContainer', 'get').and.callThrough(); + const mockScroll = vi.spyOn(combo.dropdown, 'scrollContainer', 'get'); const mockFunc = () => mockScroll(); expect(mockFunc).toThrow(); combo.toggle(); @@ -1872,10 +1932,10 @@ describe('igxCombo', () => { }); it('should restore position of dropdown scroll after opening', async () => { const virtDir = combo.virtualScrollContainer; - spyOn(combo.dropdown, 'onToggleOpening').and.callThrough(); - spyOn(combo.dropdown, 'onToggleOpened').and.callThrough(); - spyOn(combo.dropdown, 'onToggleClosing').and.callThrough(); - spyOn(combo.dropdown, 'onToggleClosed').and.callThrough(); + vi.spyOn(combo.dropdown, 'onToggleOpening'); + vi.spyOn(combo.dropdown, 'onToggleOpened'); + vi.spyOn(combo.dropdown, 'onToggleClosing'); + vi.spyOn(combo.dropdown, 'onToggleClosed'); combo.toggle(); await wait(); fixture.detectChanges(); @@ -2070,7 +2130,7 @@ describe('igxCombo', () => { }); it('should select/deselect item on check/uncheck', () => { const dropdown = combo.dropdown; - spyOn(combo.selectionChanging, 'emit').and.callThrough(); + vi.spyOn(combo.selectionChanging, 'emit'); combo.toggle(); fixture.detectChanges(); @@ -2081,19 +2141,18 @@ describe('igxCombo', () => { expect(selectedItem_1.selected).toBeTruthy(); expect(selectedItem_1.element.nativeElement.classList.contains(CSS_CLASS_SELECTED)).toBeTruthy(); expect(combo.selectionChanging.emit).toHaveBeenCalledTimes(1); - expect(combo.selectionChanging.emit).toHaveBeenCalledWith( - { - newValue: [selectedItem_1.value[combo.valueKey]], - oldValue: [], - newSelection: [selectedItem_1.value], - oldSelection: [], - added: [selectedItem_1.value], - removed: [], - event: UIInteractions.getMouseEvent('click'), - owner: combo, - displayText: selectedItem_1.value[combo.valueKey], - cancel: false - }); + expect(combo.selectionChanging.emit).toHaveBeenCalledWith({ + newValue: [selectedItem_1.value[combo.valueKey]], + oldValue: [], + newSelection: [selectedItem_1.value], + oldSelection: [], + added: [selectedItem_1.value], + removed: [], + event: UIInteractions.getMouseEvent('click'), + owner: combo, + displayText: selectedItem_1.value[combo.valueKey], + cancel: false + }); const selectedItem_2 = dropdown.items[4]; simulateComboItemClick(4); @@ -2102,19 +2161,18 @@ describe('igxCombo', () => { expect(selectedItem_2.selected).toBeTruthy(); expect(selectedItem_2.element.nativeElement.classList.contains(CSS_CLASS_SELECTED)).toBeTruthy(); expect(combo.selectionChanging.emit).toHaveBeenCalledTimes(2); - expect(combo.selectionChanging.emit).toHaveBeenCalledWith( - { - newValue: [selectedItem_1.value[combo.valueKey], selectedItem_2.value[combo.valueKey]], - oldValue: [selectedItem_1.value[combo.valueKey]], - newSelection: [selectedItem_1.value, selectedItem_2.value], - oldSelection: [selectedItem_1.value], - added: [selectedItem_2.value], - removed: [], - event: UIInteractions.getMouseEvent('click'), - owner: combo, - displayText: selectedItem_1.value[combo.valueKey] + ', ' + selectedItem_2.value[combo.valueKey], - cancel: false - }); + expect(combo.selectionChanging.emit).toHaveBeenCalledWith({ + newValue: [selectedItem_1.value[combo.valueKey], selectedItem_2.value[combo.valueKey]], + oldValue: [selectedItem_1.value[combo.valueKey]], + newSelection: [selectedItem_1.value, selectedItem_2.value], + oldSelection: [selectedItem_1.value], + added: [selectedItem_2.value], + removed: [], + event: UIInteractions.getMouseEvent('click'), + owner: combo, + displayText: selectedItem_1.value[combo.valueKey] + ', ' + selectedItem_2.value[combo.valueKey], + cancel: false + }); // Unselecting an item const unselectedItem = dropdown.items[1]; @@ -2123,22 +2181,21 @@ describe('igxCombo', () => { expect(unselectedItem.selected).toBeFalsy(); expect(unselectedItem.element.nativeElement.classList.contains(CSS_CLASS_SELECTED)).toBeFalsy(); expect(combo.selectionChanging.emit).toHaveBeenCalledTimes(3); - expect(combo.selectionChanging.emit).toHaveBeenCalledWith( - { - newValue: [selectedItem_2.value[combo.valueKey]], - oldValue: [selectedItem_1.value[combo.valueKey], selectedItem_2.value[combo.valueKey]], - newSelection: [selectedItem_2.value], - oldSelection: [selectedItem_1.value, selectedItem_2.value], - added: [], - removed: [unselectedItem.value], - event: UIInteractions.getMouseEvent('click'), - owner: combo, - displayText: selectedItem_2.value[combo.valueKey], - cancel: false - }); + expect(combo.selectionChanging.emit).toHaveBeenCalledWith({ + newValue: [selectedItem_2.value[combo.valueKey]], + oldValue: [selectedItem_1.value[combo.valueKey], selectedItem_2.value[combo.valueKey]], + newSelection: [selectedItem_2.value], + oldSelection: [selectedItem_1.value, selectedItem_2.value], + added: [], + removed: [unselectedItem.value], + event: UIInteractions.getMouseEvent('click'), + owner: combo, + displayText: selectedItem_2.value[combo.valueKey], + cancel: false + }); }); it('should toggle combo dropdown on Enter of the focused toggle icon', fakeAsync(() => { - spyOn(combo, 'toggle').and.callThrough(); + vi.spyOn(combo, 'toggle'); const toggleBtn = fixture.debugElement.query(By.css(`.${CSS_CLASS_TOGGLEBUTTON}`)); UIInteractions.triggerEventHandlerKeyDown('Enter', toggleBtn); @@ -2169,7 +2226,7 @@ describe('igxCombo', () => { expect(combo.value.length).toEqual(0); }); it('should not be able to select group header', () => { - spyOn(combo.selectionChanging, 'emit').and.callThrough(); + vi.spyOn(combo.selectionChanging, 'emit'); combo.toggle(); fixture.detectChanges(); @@ -2243,7 +2300,7 @@ describe('igxCombo', () => { expect(combo.displayValue).toEqual('0, false, , null, NaN'); expect(combo.value).toEqual([0, false, '', null, NaN]); expect(combo.selection).toEqual([{ field: '0', value: 0 }, { field: 'false', value: false }, - { field: '', value: '' }, { field: 'null', value: null }, { field: 'NaN', value: NaN }]); + { field: '', value: '' }, { field: 'null', value: null }, { field: 'NaN', value: NaN }]); combo.open(); fixture.detectChanges(); @@ -2255,7 +2312,7 @@ describe('igxCombo', () => { expect(combo.displayValue).toEqual('0, false, , null, NaN'); expect(combo.value).toEqual([0, false, '', null, NaN]); expect(combo.selection).toEqual([{ field: '0', value: 0 }, { field: 'false', value: false }, - { field: '', value: '' }, { field: 'null', value: null }, { field: 'NaN', value: NaN }]); + { field: '', value: '' }, { field: 'null', value: null }, { field: 'NaN', value: NaN }]); }); it('should select falsy values except "undefined" with "writeValue" method', () => { combo.valueKey = 'value'; @@ -2333,7 +2390,7 @@ describe('igxCombo', () => { expect(combo.displayValue).toEqual('Mississippi '); })); it('should prevent selection when selectionChanging is cancelled', () => { - spyOn(combo.selectionChanging, 'emit').and.callFake((event: IComboSelectionChangingEventArgs) => event.cancel = true); + vi.spyOn(combo.selectionChanging, 'emit').mockImplementation((event: IComboSelectionChangingEventArgs) => event.cancel = true); combo.toggle(); fixture.detectChanges(); @@ -2353,7 +2410,7 @@ describe('igxCombo', () => { fixture.detectChanges(); combo = fixture.componentInstance.instance; - spyOn(combo.selectionChanging, 'emit').and.callFake((event: IComboSelectionChangingEventArgs) => event.cancel = true); + vi.spyOn(combo.selectionChanging, 'emit').mockImplementation((event: IComboSelectionChangingEventArgs) => event.cancel = true); combo.toggle(); fixture.detectChanges(); @@ -2382,8 +2439,7 @@ describe('igxCombo', () => { { key: 3, value: 'Three' }, ]; - spyOn(combo.selectionChanging, 'emit').and.callFake( - (event: IComboSelectionChangingEventArgs) => event.displayText = `Selected Count: ${event.newSelection.length}`); + vi.spyOn(combo.selectionChanging, 'emit').mockImplementation((event: IComboSelectionChangingEventArgs) => event.displayText = `Selected Count: ${event.newSelection.length}`); combo.select([1]); fixture.detectChanges(); @@ -2406,7 +2462,7 @@ describe('igxCombo', () => { const items = fixture.componentInstance.items; expect(combo).toBeDefined(); - const selectionSpy = spyOn(combo.selectionChanging, 'emit'); + const selectionSpy = vi.spyOn(combo.selectionChanging, 'emit'); let expectedResults: IComboSelectionChangingEventArgs = { newValue: [combo.data[1][combo.valueKey]], oldValue: [], @@ -2473,7 +2529,7 @@ describe('igxCombo', () => { expect(combo.dropdown.items[0].value).toEqual(combo.data[0]); })); it('should properly handle click events on disabled/header items', fakeAsync(() => { - spyOn(combo.dropdown, 'selectItem').and.callThrough(); + vi.spyOn(combo.dropdown, 'selectItem'); combo.toggle(); tick(); fixture.detectChanges(); @@ -2483,8 +2539,10 @@ describe('igxCombo', () => { (combo.dropdown.headers[0] as IgxComboItemComponent).clicked(null); fixture.detectChanges(); - const mockObj = jasmine.createSpyObj('nativeElement', ['focus']); - spyOnProperty(combo.dropdown, 'focusedItem', 'get').and.returnValue({ element: { nativeElement: mockObj } } as IgxDropDownItemBaseDirective); + const mockObj = { + focus: vi.fn().mockName("nativeElement.focus") + }; + vi.spyOn(combo.dropdown, 'focusedItem', 'get').mockReturnValue({ element: { nativeElement: mockObj } } as IgxDropDownItemBaseDirective); (combo.dropdown.headers[0] as IgxComboItemComponent).clicked(null); fixture.detectChanges(); expect(mockObj.focus).not.toHaveBeenCalled(); // Focus only if `allowItemFocus === true` @@ -2528,7 +2586,7 @@ describe('igxCombo', () => { combo.groupSortingDirection = SortingDirection.None; combo.toggle(); fixture.detectChanges(); - expect(combo.dropdown.headers[0].element.nativeElement.innerText).toEqual('New England') + expect(combo.dropdown.headers[0].element.nativeElement.innerText).toEqual('New England'); }); it('should sort groups with diacritics correctly', () => { combo.data = [ @@ -2572,7 +2630,7 @@ describe('igxCombo', () => { const initialData = [...combo.filteredData]; expect(combo.searchValue).toEqual(''); - const filterSpy = spyOn(IgxComboFilteringPipe.prototype, 'transform').and.callThrough(); + const filterSpy = vi.spyOn(IgxComboFilteringPipe.prototype, 'transform'); combo.searchValue = 'New '; combo.handleInputChange(); fixture.detectChanges(); @@ -2600,7 +2658,7 @@ describe('igxCombo', () => { const initialData = [...combo.filteredData]; expect(combo.searchValue).toEqual(''); - const filterSpy = spyOn(IgxComboFilteringPipe.prototype, 'transform').and.callThrough(); + const filterSpy = vi.spyOn(IgxComboFilteringPipe.prototype, 'transform'); combo.searchValue = 'New '; combo.handleInputChange(); fixture.detectChanges(); @@ -2633,7 +2691,7 @@ describe('igxCombo', () => { expect(combo.data.length).toEqual(initialData.length); combo.searchValue = 'myItem'; fixture.detectChanges(); - spyOn(combo.addition, 'emit').and.callThrough(); + vi.spyOn(combo.addition, 'emit'); combo.addItemToCollection(); fixture.detectChanges(); expect(initialData.length).toBeLessThan(combo.data.length); @@ -2685,7 +2743,7 @@ describe('igxCombo', () => { expect(combo.data.length).toEqual(initialData.length); combo.searchValue = 'myItem'; fixture.detectChanges(); - spyOn(combo.addition, 'emit').and.callThrough(); + vi.spyOn(combo.addition, 'emit'); combo.addItemToCollection(); fixture.detectChanges(); expect(initialData.length).toBeLessThan(combo.data.length); @@ -2778,7 +2836,7 @@ describe('igxCombo', () => { }); it('should fire searchInputUpdate event when typing in the search box ', () => { let timesFired = 0; - spyOn(combo.searchInputUpdate, 'emit').and.callThrough(); + vi.spyOn(combo.searchInputUpdate, 'emit'); combo.toggle(); fixture.detectChanges(); const searchInput = fixture.debugElement.query(By.css(CSS_CLASS_SEARCHINPUT)); @@ -2802,9 +2860,7 @@ describe('igxCombo', () => { fixture.detectChanges(); const searchInput = fixture.debugElement.query(By.css(CSS_CLASS_SEARCHINPUT)); - const verifyFilteredItems = (inputValue: string, - expectedDropdownItemsNumber: number, - expectedFilteredItemsNumber: number) => { + const verifyFilteredItems = (inputValue: string, expectedDropdownItemsNumber: number, expectedFilteredItemsNumber: number) => { UIInteractions.triggerInputEvent(searchInput, inputValue); fixture.detectChanges(); dropdownList = fixture.debugElement.query(By.css(`.${CSS_CLASS_CONTAINER}`)).nativeElement; @@ -2836,7 +2892,9 @@ describe('igxCombo', () => { expect(searchInput.nativeElement.textContent).toEqual(''); })); it('should not display group headers when no results are filtered for a group', () => { - const filteredItems: { [index: string]: any } = combo.data.reduce((filteredArray, item) => { + const filteredItems: { + [index: string]: any; + } = combo.data.reduce((filteredArray, item) => { if (item.field.toLowerCase().trim().includes('mi')) { (filteredArray[item['region']] = filteredArray[item['region']] || []).push(item); } @@ -3056,13 +3114,15 @@ describe('igxCombo', () => { fixture.detectChanges(); combo.filteringOptions = { caseSensitive: false, filteringKey: combo.groupKey }; combo.filterFunction = (collection: any[], searchValue: any, filteringOptions: IComboFilteringOptions): any[] => { - if (!collection) return []; - if (!searchValue) return collection; + if (!collection) + return []; + if (!searchValue) + return collection; const searchTerm = filteringOptions.caseSensitive ? searchValue.trim() : searchValue.toLowerCase().trim(); return collection.filter(i => filteringOptions.caseSensitive ? i[filteringOptions.filteringKey]?.includes(searchTerm) : - i[filteringOptions.filteringKey]?.toString().toLowerCase().includes(searchTerm)) - } + i[filteringOptions.filteringKey]?.toString().toLowerCase().includes(searchTerm)); + }; combo.open(); tick(); fixture.detectChanges(); @@ -3094,13 +3154,15 @@ describe('igxCombo', () => { fixture.detectChanges(); combo.filteringOptions = { caseSensitive: false, filteringKey: combo.groupKey }; combo.filterFunction = (collection: any[], searchValue: any, filteringOptions: IComboFilteringOptions): any[] => { - if (!collection) return []; - if (!searchValue) return collection; + if (!collection) + return []; + if (!searchValue) + return collection; const searchTerm = filteringOptions.caseSensitive ? searchValue.trim() : searchValue.toLowerCase().trim(); return collection.filter(i => filteringOptions.caseSensitive ? i[filteringOptions.filteringKey]?.includes(searchTerm) : - i[filteringOptions.filteringKey]?.toString().toLowerCase().includes(searchTerm)) - } + i[filteringOptions.filteringKey]?.toString().toLowerCase().includes(searchTerm)); + }; combo.open(); tick(); fixture.detectChanges(); @@ -3226,8 +3288,8 @@ describe('igxCombo', () => { expect(comboFormReference).toBeDefined(); expect(combo.disabled).toBeFalsy(); expect(comboFormReference.disabled).toBeFalsy(); - spyOn(combo, 'onClick'); - spyOn(combo, 'setDisabledState').and.callThrough(); + vi.spyOn(combo, 'onClick'); + vi.spyOn(combo, 'setDisabledState'); combo.comboInput.nativeElement.click(); fixture.detectChanges(); expect(combo.onClick).toHaveBeenCalledTimes(1); @@ -3281,7 +3343,7 @@ describe('igxCombo', () => { form.controls.password.setValue('TEST'); form.controls.firstName.setValue('TEST'); - spyOn(console, 'log'); + vi.spyOn(console, 'log'); fixture.detectChanges(); expect(form.status).toEqual('VALID'); fixture.debugElement.query(By.css('button')).triggerEventHandler('click', UIInteractions.simulateClickAndSelectEvent); @@ -3372,9 +3434,9 @@ describe('igxCombo', () => { tick(); expect(combo.valid).toEqual(IgxInputState.INITIAL); expect(combo.comboInput.valid).toEqual(IgxInputState.INITIAL); - expect(model.valid).toBeFalse(); - expect(model.dirty).toBeFalse(); - expect(model.touched).toBeFalse(); + expect(model.valid).toBe(false); + expect(model.dirty).toBe(false); + expect(model.touched).toBe(false); fixture.componentInstance.values = ['Missouri']; fixture.detectChanges(); @@ -3384,8 +3446,8 @@ describe('igxCombo', () => { expect(combo.selection).toEqual([{ field: 'Missouri', region: 'West North Central' }]); expect(combo.value).toEqual(['Missouri']); expect(combo.displayValue).toEqual('Missouri'); - expect(model.valid).toBeTrue(); - expect(model.touched).toBeFalse(); + expect(model.valid).toBe(true); + expect(model.touched).toBe(false); fixture.componentInstance.values = ['Missouri', 'Missouri']; fixture.detectChanges(); @@ -3394,8 +3456,8 @@ describe('igxCombo', () => { expect(combo.selection).toEqual([{ field: 'Missouri', region: 'West North Central' }]); expect(combo.value).toEqual(['Missouri']); expect(combo.displayValue).toEqual('Missouri'); - expect(model.valid).toBeTrue(); - expect(model.touched).toBeFalse(); + expect(model.valid).toBe(true); + expect(model.touched).toBe(false); fixture.componentInstance.values = null; fixture.detectChanges(); @@ -3405,17 +3467,17 @@ describe('igxCombo', () => { expect(combo.selection).toEqual([]); expect(combo.value).toEqual([]); expect(combo.displayValue).toEqual(''); - expect(model.valid).toBeFalse(); - expect(model.touched).toBeFalse(); - expect(model.dirty).toBeFalse(); + expect(model.valid).toBe(false); + expect(model.touched).toBe(false); + expect(model.dirty).toBe(false); combo.onBlur(); fixture.detectChanges(); expect(combo.valid).toEqual(IgxInputState.INVALID); expect(combo.comboInput.valid).toEqual(IgxInputState.INVALID); - expect(model.valid).toBeFalse(); - expect(model.touched).toBeTrue(); - expect(model.dirty).toBeFalse(); + expect(model.valid).toBe(false); + expect(model.touched).toBe(true); + expect(model.dirty).toBe(false); fixture.componentInstance.values = ['New Jersey']; fixture.detectChanges(); @@ -3425,12 +3487,12 @@ describe('igxCombo', () => { expect(combo.selection).toEqual([{ field: 'New Jersey', region: 'Mid-Atlan' }]); expect(combo.value).toEqual(['New Jersey']); expect(combo.displayValue).toEqual('New Jersey'); - expect(model.valid).toBeTrue(); - expect(model.touched).toBeTrue(); - expect(model.dirty).toBeFalse(); + expect(model.valid).toBe(true); + expect(model.touched).toBe(true); + expect(model.dirty).toBe(false); })); it('should have correctly bound blur handler', () => { - spyOn(combo, 'onBlur'); + vi.spyOn(combo, 'onBlur'); input.triggerEventHandler('blur', {}); expect(combo.onBlur).toHaveBeenCalled(); @@ -3451,12 +3513,12 @@ describe('igxCombo', () => { const ngModel = fixture.debugElement.query(By.directive(NgModel)).injector.get(NgModel); expect(combo.valid).toEqual(IgxInputState.INITIAL); expect(combo.comboInput.valid).toEqual(IgxInputState.INITIAL); - expect(ngModel.touched).toBeFalse(); + expect(ngModel.touched).toBe(false); combo.open(); input.triggerEventHandler('focus', {}); fixture.detectChanges(); - expect(ngModel.touched).toBeFalse(); + expect(ngModel.touched).toBe(false); combo.searchInput.nativeElement.focus(); fixture.detectChanges(); const documentClickEvent = new MouseEvent('click', { bubbles: true }); @@ -3468,7 +3530,7 @@ describe('igxCombo', () => { tick(); expect(combo.valid).toEqual(IgxInputState.INVALID); expect(combo.comboInput.valid).toEqual(IgxInputState.INVALID); - expect(ngModel.touched).toBeTrue(); + expect(ngModel.touched).toBe(true); })); }); }); @@ -3724,11 +3786,9 @@ export class IgxComboBindingTestComponent { public items = []; constructor() { - this.localService.getData().subscribe( - (data: any[]) => { - this.items = data; - } - ); + this.localService.getData().subscribe((data: any[]) => { + this.items = data; + }); } } @Component({ @@ -3763,7 +3823,8 @@ class IgxComboInContainerTestComponent { 'Prague', 'Padua', 'Palermo', - 'Palma de Mallorca']; + 'Palma de Mallorca' + ]; } @Injectable() @@ -3854,7 +3915,7 @@ export class ComboModelBindingComponent implements OnInit { public ngOnInit() { this.items = [{ text: 'One', id: 0 }, { text: 'Two', id: 1 }, { text: 'Three', id: 2 }, - { text: 'Four', id: 3 }, { text: 'Five', id: 4 }]; + { text: 'Four', id: 3 }, { text: 'Five', id: 4 }]; } } @@ -3872,7 +3933,7 @@ export class IgxComboBindingDataAfterInitComponent implements AfterViewInit { public ngAfterViewInit() { setTimeout(() => { this.items = [{ text: 'One', id: 0 }, { text: 'Two', id: 1 }, { text: 'Three', id: 2 }, - { text: 'Four', id: 3 }, { text: 'Five', id: 4 }]; + { text: 'Four', id: 3 }, { text: 'Five', id: 4 }]; this.cdr.detectChanges(); }, 1000); } diff --git a/projects/igniteui-angular/core/src/core/i18n/formatters/formatter-base.spec.ts b/projects/igniteui-angular/core/src/core/i18n/formatters/formatter-base.spec.ts index cc1685543b4..85aaf389baf 100644 --- a/projects/igniteui-angular/core/src/core/i18n/formatters/formatter-base.spec.ts +++ b/projects/igniteui-angular/core/src/core/i18n/formatters/formatter-base.spec.ts @@ -1,4 +1,5 @@ import { BaseFormatter } from './formatter-base'; +import { describe, it, expect } from 'vitest'; describe('Localization', () => { const i18nFormatter = new BaseFormatter(); @@ -35,7 +36,7 @@ describe('Localization', () => { expect(i18nFormatter.formatCurrency(12345, 'en', 'symbol', 'EUR', '1.1-3')).toEqual('€12,345.0'); expect(i18nFormatter.formatCurrency('12345', 'en', 'symbol', 'EUR', '1.1-3')).toEqual('€12,345.0'); }); - }) + }); describe('date formatting', () => { it('should format string to dateTime using Angular', () => { diff --git a/projects/igniteui-angular/core/src/core/i18n/formatters/formatter-intl.spec.ts b/projects/igniteui-angular/core/src/core/i18n/formatters/formatter-intl.spec.ts index ce0bf141f4f..8da9c244af5 100644 --- a/projects/igniteui-angular/core/src/core/i18n/formatters/formatter-intl.spec.ts +++ b/projects/igniteui-angular/core/src/core/i18n/formatters/formatter-intl.spec.ts @@ -1,4 +1,5 @@ import { IntlFormatter } from './formatter-intl'; +import { describe, it, expect } from 'vitest'; describe('Localization', () => { const i18nFormatter = new IntlFormatter(); @@ -35,7 +36,7 @@ describe('Localization', () => { expect(i18nFormatter.formatCurrency(12345, 'en', 'symbol', 'EUR', '1.1-3')).toEqual('€12,345.0'); expect(i18nFormatter.formatCurrency('12345', 'en', 'symbol', 'EUR', '1.1-3')).toEqual('€12,345.0'); }); - }) + }); describe('date formatting', () => { it('should format string to dateTime using Intl', () => { diff --git a/projects/igniteui-angular/core/src/core/i18n/resources.spec.ts b/projects/igniteui-angular/core/src/core/i18n/resources.spec.ts index 8ab20d80528..a02df82084c 100644 --- a/projects/igniteui-angular/core/src/core/i18n/resources.spec.ts +++ b/projects/igniteui-angular/core/src/core/i18n/resources.spec.ts @@ -5,6 +5,7 @@ import { changei18n, getCurrentResourceStrings as igxGetCurrentResourceStrings } import { ActionStripResourceStringsBG } from 'projects/igniteui-angular-i18n/src/i18n/BG/action-strip-resources'; import { BannerResourceStringsBG, ResourceStringsBG } from 'igniteui-i18n-resources'; import { IResourceCategories } from 'node_modules/igniteui-i18n-core/i18n-manager.interfaces'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('i18n', () => { beforeEach(() => { @@ -107,7 +108,7 @@ describe('i18n', () => { }); setCurrentI18n('en-US'); - }) + }); it('should return default strings if locale is changed using new API, but its missing resources', () => { // Components init their default locales diff --git a/projects/igniteui-angular/core/src/core/selection.spec.ts b/projects/igniteui-angular/core/src/core/selection.spec.ts index 3adf6fe4d95..fdbf7bca21a 100644 --- a/projects/igniteui-angular/core/src/core/selection.spec.ts +++ b/projects/igniteui-angular/core/src/core/selection.spec.ts @@ -1,4 +1,5 @@ -import {IgxSelectionAPIService} from './selection'; +import { IgxSelectionAPIService } from './selection'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('IgxSelectionAPIService', () => { let service; diff --git a/projects/igniteui-angular/core/src/core/styles/spec/tests.mjs b/projects/igniteui-angular/core/src/core/styles/spec/tests.mjs deleted file mode 100644 index 5fbaec9a349..00000000000 --- a/projects/igniteui-angular/core/src/core/styles/spec/tests.mjs +++ /dev/null @@ -1,8 +0,0 @@ -import * as path from 'path'; -import * as sassTrue from 'sass-true'; -import { fileURLToPath } from "url"; -import {} from 'jasmine'; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); -const file = path.join(__dirname, '_index.scss'); -sassTrue.runSass({ describe, it }, file, { loadPaths: ['node_modules'] }); diff --git a/projects/igniteui-angular/core/src/core/utils.spec.ts b/projects/igniteui-angular/core/src/core/utils.spec.ts index 2a6bb842080..57700d64b9e 100644 --- a/projects/igniteui-angular/core/src/core/utils.spec.ts +++ b/projects/igniteui-angular/core/src/core/utils.spec.ts @@ -1,5 +1,6 @@ import { SampleTestData } from 'igniteui-angular/test-utils/sample-test-data.spec'; import { cloneValue, isObject, isDate } from './utils'; +import { describe, it, expect } from 'vitest'; describe('Utils', () => { const complexObject = { @@ -108,8 +109,18 @@ describe('Utils', () => { }); it('Should create shallow copy of array', () => { - const input: { Number: any; String: any; Boolean: any; Date: any }[] = SampleTestData.differentTypesData(); - const clone: { Number: any; String: any; Boolean: any; Date: any }[] = cloneValue(input); + const input: { + Number: any; + String: any; + Boolean: any; + Date: any; + }[] = SampleTestData.differentTypesData(); + const clone: { + Number: any; + String: any; + Boolean: any; + Date: any; + }[] = cloneValue(input); expect(clone).not.toBe(input); expect(clone.length).toBe(input.length); expect(clone).toEqual(input); diff --git a/projects/igniteui-angular/core/src/data-operations/data-util.spec.ts b/projects/igniteui-angular/core/src/data-operations/data-util.spec.ts index 6069306a53e..55a6a0ee968 100644 --- a/projects/igniteui-angular/core/src/data-operations/data-util.spec.ts +++ b/projects/igniteui-angular/core/src/data-operations/data-util.spec.ts @@ -11,16 +11,12 @@ import { FilteringStrategy, FilterUtil } from './filtering-strategy'; import { IFilteringExpressionsTree, FilteringExpressionsTree } from './filtering-expressions-tree'; import { IFilteringState } from './filtering-state.interface'; import { FilteringLogic } from './filtering-expression.interface'; -import { - IgxNumberFilteringOperand, - IgxStringFilteringOperand, - IgxDateFilteringOperand, - IgxBooleanFilteringOperand -} from './filtering-condition'; +import { IgxNumberFilteringOperand, IgxStringFilteringOperand, IgxDateFilteringOperand, IgxBooleanFilteringOperand } from './filtering-condition'; import { IPagingState, PagingError } from './paging-state.interface'; import { SampleTestData } from '../../../test-utils/sample-test-data.spec'; import { Transaction, TransactionType, HierarchicalTransaction } from '../services/public_api'; import { DefaultDataCloneStrategy } from './data-clone-strategy'; +import { describe, it, expect, beforeEach } from 'vitest'; /* Test sorting */ const testSort = () => { @@ -80,8 +76,7 @@ const testSort = () => { strategy: DefaultSortingStrategy.instance() }; let res = DataUtil.sort(data, [se0]); - expect(dataGenerator.getValuesForColumn(res, 'number')) - .toEqual([3, 2, 1, 0, 4], 'expressionDefaults.ignoreCase = false'); + expect(dataGenerator.getValuesForColumn(res, 'number'), 'expressionDefaults.ignoreCase = false').toEqual([3, 2, 1, 0, 4]); se0.ignoreCase = true; res = DataUtil.sort(data, [se0]); expect(dataGenerator.getValuesForColumn(res, 'number')) @@ -195,10 +190,10 @@ const testGroupBy = () => { const result = groupRecords.data; expect(dataGenerator.getValuesForColumn(result, 'boolean')) .toEqual([undefined, undefined, false, undefined, false, - undefined, false, undefined, undefined, true, undefined, true]); + undefined, false, undefined, undefined, true, undefined, true]); expect(dataGenerator.getValuesForColumn(result, 'string')) .toEqual([undefined, undefined, 'row0, col1', undefined, 'row2, col1', - undefined, 'row4, col1', undefined, undefined, 'row1, col1', undefined, 'row3, col1']); + undefined, 'row4, col1', undefined, undefined, 'row1, col1', undefined, 'row3, col1']); const group1: IGroupByRecord = groupRecords.metadata[2]; const group2: IGroupByRecord = group1.groupParent; const group3: IGroupByRecord = groupRecords.metadata[9]; @@ -278,7 +273,7 @@ const testGroupBy = () => { state.expressions.push(expr2); // sort const sorted = DataUtil.sort(data, [expr, expr2]); - // group by + // group by DataUtil.group(sorted, state, undefined, null, groupRecords); expect(groupRecords.length).toEqual(2); expect(groupRecords[0].records.length).toEqual(3); @@ -390,7 +385,9 @@ const testFilter = () => { let res = FilterUtil.filter(data, state); expect(dataGenerator.getValuesForColumn(res, 'number')) .toEqual(dataGenerator.getValuesForColumn(data, 'number')); - (res[0] as { string: string }).string = 'ROW'; + (res[0] as { + string: string; + }).string = 'ROW'; // case-sensitive res = FilterUtil.filter(res, stateIgnoreCase); expect(dataGenerator.getValuesForColumn(res, 'number')) @@ -591,7 +588,7 @@ const testMerging = () => { }, ]; - DataUtil.mergeHierarchicalTransactions(data, transactions, 'Employees', 'ID',cloneStrategy, false); + DataUtil.mergeHierarchicalTransactions(data, transactions, 'Employees', 'ID', cloneStrategy, false); expect(data[1].Name).toBe(updateRootRow.Name); expect(data[1].Age).toBe(updateRootRow.Age); diff --git a/projects/igniteui-angular/core/src/data-operations/expressions-tree-util.spec.ts b/projects/igniteui-angular/core/src/data-operations/expressions-tree-util.spec.ts index 528c18e79d7..e17941daf4b 100644 --- a/projects/igniteui-angular/core/src/data-operations/expressions-tree-util.spec.ts +++ b/projects/igniteui-angular/core/src/data-operations/expressions-tree-util.spec.ts @@ -3,9 +3,10 @@ import { FilteringExpressionsTree, IFilteringExpressionsTree } from './filtering import { recreateTree, recreateTreeFromFields } from './expressions-tree-util'; import { IgxBooleanFilteringOperand, IgxDateFilteringOperand, IgxDateTimeFilteringOperand, IgxNumberFilteringOperand, IgxStringFilteringOperand, IgxTimeFilteringOperand } from './filtering-condition'; import type { EntityType, FieldType } from './grid-types'; +import { describe, it, expect } from 'vitest'; function serialize(value: unknown, pretty = false) { - return pretty ? JSON.stringify(value, undefined, ' ') : JSON.stringify(value) + return pretty ? JSON.stringify(value, undefined, ' ') : JSON.stringify(value); } function checkOp(op: IFilteringExpression, reconstructedOp: IFilteringExpression) { @@ -305,11 +306,11 @@ describe('Unit testing FilteringUtil', () => { it('Number search values should deserialize correctly', () => { const tree = new FilteringExpressionsTree(FilteringLogic.Or, 'myField', 'myEntity', ['*']); const entities: EntityType[] = [{ - name: 'myEntity', - fields: [ - { field: 'Id', dataType: 'number' } - ] as any, - }]; + name: 'myEntity', + fields: [ + { field: 'Id', dataType: 'number' } + ] as any, + }]; tree.filteringOperands.push({ fieldName: 'Id', @@ -328,11 +329,11 @@ describe('Unit testing FilteringUtil', () => { it('Boolean search values should deserialize correctly', () => { const tree = new FilteringExpressionsTree(FilteringLogic.Or, 'myField', 'myEntity', ['*']); const entities: EntityType[] = [{ - name: 'myEntity', - fields: [ - { field: 'Id', dataType: 'boolean' } - ] as any, - }]; + name: 'myEntity', + fields: [ + { field: 'Id', dataType: 'boolean' } + ] as any, + }]; tree.filteringOperands.push({ fieldName: 'Id', conditionName: 'false' @@ -349,11 +350,11 @@ describe('Unit testing FilteringUtil', () => { it('String search values should deserialize correctly', () => { const tree = new FilteringExpressionsTree(FilteringLogic.Or, 'myField', 'myEntity', ['*']); const entities: EntityType[] = [{ - name: 'myEntity', - fields: [ - { field: 'Id', dataType: 'string' } - ] as any, - }]; + name: 'myEntity', + fields: [ + { field: 'Id', dataType: 'string' } + ] as any, + }]; tree.filteringOperands.push({ fieldName: 'Id', conditionName: 'equals', @@ -371,11 +372,11 @@ describe('Unit testing FilteringUtil', () => { it('Date search values should deserialize correctly', () => { const tree = new FilteringExpressionsTree(FilteringLogic.Or, 'myField', 'myEntity', ['*']); const entities: EntityType[] = [{ - name: 'myEntity', - fields: [ - { field: 'Id', dataType: 'date' } - ] as any, - }]; + name: 'myEntity', + fields: [ + { field: 'Id', dataType: 'date' } + ] as any, + }]; tree.filteringOperands.push({ fieldName: 'Id', conditionName: 'equals', @@ -393,11 +394,11 @@ describe('Unit testing FilteringUtil', () => { it('DateTime search values should deserialize correctly', () => { const tree = new FilteringExpressionsTree(FilteringLogic.Or, 'myField', 'myEntity', ['*']); const entities: EntityType[] = [{ - name: 'myEntity', - fields: [ - { field: 'Id', dataType: 'dateTime' } - ] as any, - }]; + name: 'myEntity', + fields: [ + { field: 'Id', dataType: 'dateTime' } + ] as any, + }]; const currDate = new Date(); tree.filteringOperands.push({ fieldName: 'Id', @@ -416,11 +417,11 @@ describe('Unit testing FilteringUtil', () => { it('Time search values should deserialize correctly', () => { const tree = new FilteringExpressionsTree(FilteringLogic.Or, 'myField', 'myEntity', ['*']); const entities: EntityType[] = [{ - name: 'myEntity', - fields: [ - { field: 'Id', dataType: 'time' } - ] as any, - }]; + name: 'myEntity', + fields: [ + { field: 'Id', dataType: 'time' } + ] as any, + }]; tree.filteringOperands.push({ fieldName: 'Id', conditionName: 'at', diff --git a/projects/igniteui-angular/core/src/data-operations/filtering-condition.spec.ts b/projects/igniteui-angular/core/src/data-operations/filtering-condition.spec.ts index a8f8d0ade0e..f86bb0950a0 100644 --- a/projects/igniteui-angular/core/src/data-operations/filtering-condition.spec.ts +++ b/projects/igniteui-angular/core/src/data-operations/filtering-condition.spec.ts @@ -1,8 +1,5 @@ -import { IgxStringFilteringOperand, - IgxNumberFilteringOperand, - IgxDateFilteringOperand, - IgxBooleanFilteringOperand, - IgxFilteringOperand} from './filtering-condition'; +import { IgxStringFilteringOperand, IgxNumberFilteringOperand, IgxDateFilteringOperand, IgxBooleanFilteringOperand, IgxFilteringOperand } from './filtering-condition'; +import { describe, it, expect } from 'vitest'; describe('Unit testing FilteringCondition', () => { it('tests string conditions', () => { @@ -61,14 +58,14 @@ describe('Unit testing FilteringCondition', () => { expect(!fn.condition('greaterThan').logic(1, 2) && fn.condition('greaterThan').logic(2, 1)) .toBeTruthy('greaterThan'); expect(!fn.condition('greaterThanOrEqualTo').logic(1, 2) && !fn.condition('greaterThanOrEqualTo').logic(1, 2) && - fn.condition('greaterThanOrEqualTo').logic(1, 1)) + fn.condition('greaterThanOrEqualTo').logic(1, 1)) .toBeTruthy('greaterThanOrEqualTo'); expect(fn.condition('lessThan').logic(1, 2) && !fn.condition('lessThan').logic(2, 2) && - !fn.condition('lessThan').logic(3, 2)) + !fn.condition('lessThan').logic(3, 2)) .toBeTruthy('lessThan'); expect(fn.condition('lessThanOrEqualTo').logic(1, 2) && - fn.condition('lessThanOrEqualTo').logic(1, 1) && - !fn.condition('lessThanOrEqualTo').logic(3, 2)) + fn.condition('lessThanOrEqualTo').logic(1, 1) && + !fn.condition('lessThanOrEqualTo').logic(3, 2)) .toBeTruthy('lessThanOrEqualTo'); expect(fn.condition('notEmpty').logic(1)) .toBeTruthy('notEmpty'); @@ -85,11 +82,13 @@ describe('Unit testing FilteringCondition', () => { const cnow = new Date(); const yesterday = ((d) => new Date(d.setDate(d.getDate() - 1)))(new Date()); const lastMonth = ((d) => { - d.setDate(1); return new Date(d.setMonth(d.getMonth() - 1)); -})(new Date()); + d.setDate(1); + return new Date(d.setMonth(d.getMonth() - 1)); + })(new Date()); const nextMonth = ((d) => { - d.setDate(1); return new Date(d.setMonth(d.getMonth() + 1)); -})(new Date()); + d.setDate(1); + return new Date(d.setMonth(d.getMonth() + 1)); + })(new Date()); const lastYear = ((d) => new Date(d.setFullYear(d.getFullYear() - 1)))(new Date()); const nextYear = ((d) => new Date(d.setFullYear(d.getFullYear() + 1)))(new Date()); diff --git a/projects/igniteui-angular/core/src/data-operations/filtering-strategy.spec.ts b/projects/igniteui-angular/core/src/data-operations/filtering-strategy.spec.ts index 962656c5f57..8e07e6ef9ea 100644 --- a/projects/igniteui-angular/core/src/data-operations/filtering-strategy.spec.ts +++ b/projects/igniteui-angular/core/src/data-operations/filtering-strategy.spec.ts @@ -3,6 +3,7 @@ import { FilteringStrategy } from './filtering-strategy'; import { FilteringExpressionsTree } from './filtering-expressions-tree'; import { FilteringLogic } from './filtering-expression.interface'; import { IgxNumberFilteringOperand, IgxStringFilteringOperand, IgxBooleanFilteringOperand } from './filtering-condition'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Unit testing FilteringStrategy', () => { @@ -14,7 +15,7 @@ describe('Unit testing FilteringStrategy', () => { data = dataGenerator.data; fs = new FilteringStrategy(); }); - it ('tests `filter`', () => { + it('tests `filter`', () => { const expressionTree = new FilteringExpressionsTree(FilteringLogic.And); expressionTree.filteringOperands = [ { @@ -26,9 +27,9 @@ describe('Unit testing FilteringStrategy', () => { ]; const res = fs.filter(data, expressionTree, null, null); expect(dataGenerator.getValuesForColumn(res, 'number')) - .toEqual([2, 3, 4]); + .toEqual([2, 3, 4]); }); - it ('tests `matchRecordByExpressions`', () => { + it('tests `matchRecordByExpressions`', () => { const rec = data[0]; const expressionTree = new FilteringExpressionsTree(FilteringLogic.Or); expressionTree.filteringOperands = [ @@ -49,7 +50,7 @@ describe('Unit testing FilteringStrategy', () => { const res = fs.matchRecord(rec, expressionTree); expect(res).toBeTruthy(); }); - it ('tests `findMatchByExpression` for working with filtering operands with missing condition', () => { + it('tests `findMatchByExpression` for working with filtering operands with missing condition', () => { const rec = data[0]; const expressionTree = JSON.parse('{"filteringOperands":[{"fieldName":"Missing","condition":{"name":"notEmpty","isUnary":true,"iconName":"filter_not_empty"},"conditionName":"notEmpty","ignoreCase":true,"searchVal":null,"searchTree":null}],"operator":0,"returnFields":[],"type":1}'); @@ -58,7 +59,7 @@ describe('Unit testing FilteringStrategy', () => { expect(res).toBeFalsy(); }); - it ('no error when condition is missing in the filtering expressions tree', () => { + it('no error when condition is missing in the filtering expressions tree', () => { const rec = data[0]; const expressionTree = new FilteringExpressionsTree(FilteringLogic.Or); expressionTree.filteringOperands = [ @@ -73,7 +74,7 @@ describe('Unit testing FilteringStrategy', () => { expect(res).toBeFalsy(); }); - it ('tests `findMatch`', () => { + it('tests `findMatch`', () => { const rec = data[0]; const res = fs.findMatchByExpression(rec, { condition: IgxBooleanFilteringOperand.instance().condition('false'), @@ -82,8 +83,10 @@ describe('Unit testing FilteringStrategy', () => { }); expect(res).toBeTruthy(); }); - it ('tests default settings', () => { - (data[0] as { string: string }).string = 'ROW'; + it('tests default settings', () => { + (data[0] as { + string: string; + }).string = 'ROW'; const filterstr = new FilteringStrategy(); const expressionTree = new FilteringExpressionsTree(FilteringLogic.And); expressionTree.filteringOperands = [ @@ -96,6 +99,6 @@ describe('Unit testing FilteringStrategy', () => { ]; const res = filterstr.filter(data, expressionTree, null, null); expect(dataGenerator.getValuesForColumn(res, 'number')) - .toEqual([0]); + .toEqual([0]); }); }); diff --git a/projects/igniteui-angular/core/src/data-operations/groupby-strategy.spec.ts b/projects/igniteui-angular/core/src/data-operations/groupby-strategy.spec.ts index d2683e40e29..e8afd283555 100644 --- a/projects/igniteui-angular/core/src/data-operations/groupby-strategy.spec.ts +++ b/projects/igniteui-angular/core/src/data-operations/groupby-strategy.spec.ts @@ -2,6 +2,7 @@ import { IgxGrouping } from './grid-sorting-strategy'; import { IGroupByRecord } from './groupby-record.interface'; import { DefaultSortingStrategy, SortingDirection } from './sorting-strategy'; import { DataGenerator } from './test-util/data-generator'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Unit testing GroupingStrategy', () => { let dataGenerator: DataGenerator; @@ -14,11 +15,11 @@ describe('Unit testing GroupingStrategy', () => { it('should group by a field', () => { const expr = [{ - dir: SortingDirection.Asc, - fieldName: 'boolean', - ignoreCase: false, - strategy: DefaultSortingStrategy.instance() - }]; + dir: SortingDirection.Asc, + fieldName: 'boolean', + ignoreCase: false, + strategy: DefaultSortingStrategy.instance() + }]; const result = grouping.sort(data, expr); const groupResult = grouping.groupBy(result, { expressions: expr, @@ -26,7 +27,7 @@ describe('Unit testing GroupingStrategy', () => { defaultExpanded: true }); expect(dataGenerator.getValuesForColumn(groupResult.data, 'boolean')) - .toEqual([undefined, false, false, false, undefined, true, true]); + .toEqual([undefined, false, false, false, undefined, true, true]); const group1: IGroupByRecord = groupResult.metadata[1]; const group2: IGroupByRecord = groupResult.metadata[5]; expect(groupResult.metadata[2]).toEqual(group1); diff --git a/projects/igniteui-angular/core/src/data-operations/sorting-strategy.spec.ts b/projects/igniteui-angular/core/src/data-operations/sorting-strategy.spec.ts index f4c1948e49f..4117af4d874 100644 --- a/projects/igniteui-angular/core/src/data-operations/sorting-strategy.spec.ts +++ b/projects/igniteui-angular/core/src/data-operations/sorting-strategy.spec.ts @@ -1,6 +1,7 @@ import { DataGenerator } from './test-util/data-generator'; import { DefaultSortingStrategy, SortingDirection } from './sorting-strategy'; import { IgxSorting } from './grid-sorting-strategy'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Unit testing SortingStrategy', () => { let dataGenerator: DataGenerator; @@ -22,7 +23,8 @@ describe('Unit testing SortingStrategy', () => { fieldName: 'number', ignoreCase: false, strategy: DefaultSortingStrategy.instance() - }]); + } + ]); expect(dataGenerator.getValuesForColumn(res, 'number')) .toEqual([4, 2, 0, 3, 1]); }); @@ -38,18 +40,19 @@ describe('Unit testing SortingStrategy', () => { .toBeTruthy('compare 0, 1'); expect(strategy.compareValues(0, 0) === 0 && strategy.compareValues(true, true) === 0 && - strategy.compareValues('test', 'test') === 0 - ) + strategy.compareValues('test', 'test') === 0) .toBeTruthy('Comare equal variables'); }); it('tests default settings', () => { - (data[4] as { string: string }).string = 'ROW'; + (data[4] as { + string: string; + }).string = 'ROW'; const res = sorting.sort(data, [{ - dir: SortingDirection.Asc, - fieldName: 'string', - ignoreCase: true, - strategy: DefaultSortingStrategy.instance() - }]); + dir: SortingDirection.Asc, + fieldName: 'string', + ignoreCase: true, + strategy: DefaultSortingStrategy.instance() + }]); expect(dataGenerator.getValuesForColumn(res, 'number')) .toEqual([4, 0, 1, 2, 3]); }); @@ -57,11 +60,11 @@ describe('Unit testing SortingStrategy', () => { it('should not sort when sorting direction is None', () => { const unsortedData = [{ number: 3 }, { number: 1 }, { number: 4 }, { number: 0 }, { number: 2 }]; const res = sorting.sort(unsortedData, [{ - dir: SortingDirection.None, - fieldName: 'number', - ignoreCase: false, - strategy: DefaultSortingStrategy.instance() - }]); + dir: SortingDirection.None, + fieldName: 'number', + ignoreCase: false, + strategy: DefaultSortingStrategy.instance() + }]); expect(res.map(d => d.number)) .toEqual([3, 1, 4, 0, 2]); }); diff --git a/projects/igniteui-angular/core/src/date-common/util/date-time.util.spec.ts b/projects/igniteui-angular/core/src/date-common/util/date-time.util.spec.ts index 3c8344ce741..1792f4bb41d 100644 --- a/projects/igniteui-angular/core/src/date-common/util/date-time.util.spec.ts +++ b/projects/igniteui-angular/core/src/date-common/util/date-time.util.spec.ts @@ -4,6 +4,7 @@ import { registerLocaleData } from '@angular/common'; import localeBg from "@angular/common/locales/bg"; import { BaseFormatter } from '../../core/i18n/formatters/formatter-base'; import { DatePart, DatePartInfo } from '../date-parts'; +import { describe, it, expect, vi } from 'vitest'; const reduceToDictionary = (parts: DatePartInfo[]) => parts.reduce((obj, x) => { obj[x.type] = x; @@ -37,7 +38,7 @@ describe(`DateTimeUtil Unit tests`, () => { expect(JSON.stringify(result)).toEqual(JSON.stringify(expected)); result = DateTimeUtil.parseDateTimeFormat('dd/MM/yyyy HH:mm:ss:SS tt', angularFormatter); - expected[expected.length - 1] = { start: 24, end: 26, type: DatePart.AmPm, format: 'tt' } + expected[expected.length - 1] = { start: 24, end: 26, type: DatePart.AmPm, format: 'tt' }; expect(JSON.stringify(result)).toEqual(JSON.stringify(expected)); }); @@ -45,58 +46,58 @@ describe(`DateTimeUtil Unit tests`, () => { let result = DateTimeUtil.parseDateTimeFormat('MM/dd/yyyy', angularFormatter); let resDict = reduceToDictionary(result); expect(result.length).toEqual(5); - expect(resDict[DatePart.Month]).toEqual(jasmine.objectContaining({ start: 0, end: 2 })); - expect(resDict[DatePart.Date]).toEqual(jasmine.objectContaining({ start: 3, end: 5 })); - expect(resDict[DatePart.Year]).toEqual(jasmine.objectContaining({ start: 6, end: 10 })); + expect(resDict[DatePart.Month]).toEqual(expect.objectContaining({ start: 0, end: 2 })); + expect(resDict[DatePart.Date]).toEqual(expect.objectContaining({ start: 3, end: 5 })); + expect(resDict[DatePart.Year]).toEqual(expect.objectContaining({ start: 6, end: 10 })); // M/d/yy should be 00/00/00 result = DateTimeUtil.parseDateTimeFormat('M/d/yy', angularFormatter); resDict = reduceToDictionary(result); expect(result.length).toEqual(5); - expect(resDict[DatePart.Month]).toEqual(jasmine.objectContaining({ start: 0, end: 2 })); - expect(resDict[DatePart.Date]).toEqual(jasmine.objectContaining({ start: 3, end: 5 })); - expect(resDict[DatePart.Year]).toEqual(jasmine.objectContaining({ start: 6, end: 8 })); + expect(resDict[DatePart.Month]).toEqual(expect.objectContaining({ start: 0, end: 2 })); + expect(resDict[DatePart.Date]).toEqual(expect.objectContaining({ start: 3, end: 5 })); + expect(resDict[DatePart.Year]).toEqual(expect.objectContaining({ start: 6, end: 8 })); // d/M/y should be 00/00/0000 result = DateTimeUtil.parseDateTimeFormat('d/M/y', angularFormatter); resDict = reduceToDictionary(result); expect(result.length).toEqual(5); - expect(resDict[DatePart.Date]).toEqual(jasmine.objectContaining({ start: 0, end: 2 })); - expect(resDict[DatePart.Month]).toEqual(jasmine.objectContaining({ start: 3, end: 5 })); - expect(resDict[DatePart.Year]).toEqual(jasmine.objectContaining({ start: 6, end: 10 })); + expect(resDict[DatePart.Date]).toEqual(expect.objectContaining({ start: 0, end: 2 })); + expect(resDict[DatePart.Month]).toEqual(expect.objectContaining({ start: 3, end: 5 })); + expect(resDict[DatePart.Year]).toEqual(expect.objectContaining({ start: 6, end: 10 })); // d/M/yyy should be 00/00/0000 result = DateTimeUtil.parseDateTimeFormat('d/M/yyy', angularFormatter); resDict = reduceToDictionary(result); expect(result.length).toEqual(5); - expect(resDict[DatePart.Date]).toEqual(jasmine.objectContaining({ start: 0, end: 2 })); - expect(resDict[DatePart.Month]).toEqual(jasmine.objectContaining({ start: 3, end: 5 })); - expect(resDict[DatePart.Year]).toEqual(jasmine.objectContaining({ start: 6, end: 10 })); + expect(resDict[DatePart.Date]).toEqual(expect.objectContaining({ start: 0, end: 2 })); + expect(resDict[DatePart.Month]).toEqual(expect.objectContaining({ start: 3, end: 5 })); + expect(resDict[DatePart.Year]).toEqual(expect.objectContaining({ start: 6, end: 10 })); // d/M/yyyy should 00/00/0000 result = DateTimeUtil.parseDateTimeFormat('d/M/yyyy', angularFormatter); resDict = reduceToDictionary(result); expect(result.length).toEqual(5); - expect(resDict[DatePart.Date]).toEqual(jasmine.objectContaining({ start: 0, end: 2 })); - expect(resDict[DatePart.Month]).toEqual(jasmine.objectContaining({ start: 3, end: 5 })); - expect(resDict[DatePart.Year]).toEqual(jasmine.objectContaining({ start: 6, end: 10 })); + expect(resDict[DatePart.Date]).toEqual(expect.objectContaining({ start: 0, end: 2 })); + expect(resDict[DatePart.Month]).toEqual(expect.objectContaining({ start: 3, end: 5 })); + expect(resDict[DatePart.Year]).toEqual(expect.objectContaining({ start: 6, end: 10 })); // H:m:s should be 00:00:00 result = DateTimeUtil.parseDateTimeFormat('H:m:s', angularFormatter); resDict = reduceToDictionary(result); expect(result.length).toEqual(5); - expect(resDict[DatePart.Hours]).toEqual(jasmine.objectContaining({ start: 0, end: 2 })); - expect(resDict[DatePart.Minutes]).toEqual(jasmine.objectContaining({ start: 3, end: 5 })); - expect(resDict[DatePart.Seconds]).toEqual(jasmine.objectContaining({ start: 6, end: 8 })); + expect(resDict[DatePart.Hours]).toEqual(expect.objectContaining({ start: 0, end: 2 })); + expect(resDict[DatePart.Minutes]).toEqual(expect.objectContaining({ start: 3, end: 5 })); + expect(resDict[DatePart.Seconds]).toEqual(expect.objectContaining({ start: 6, end: 8 })); result = DateTimeUtil.parseDateTimeFormat('dd.MM.yyyy г.', angularFormatter); resDict = reduceToDictionary(result); expect(result.length).toEqual(6); - expect(resDict[DatePart.Date]).toEqual(jasmine.objectContaining({ start: 0, end: 2 })); - expect(resDict[DatePart.Month]).toEqual(jasmine.objectContaining({ start: 3, end: 5 })); - expect(resDict[DatePart.Year]).toEqual(jasmine.objectContaining({ start: 6, end: 10 })); + expect(resDict[DatePart.Date]).toEqual(expect.objectContaining({ start: 0, end: 2 })); + expect(resDict[DatePart.Month]).toEqual(expect.objectContaining({ start: 3, end: 5 })); + expect(resDict[DatePart.Year]).toEqual(expect.objectContaining({ start: 6, end: 10 })); // TODO // result = DateTimeUtil.parseDateTimeFormat('dd.MM.yyyyг'); @@ -146,7 +147,7 @@ describe(`DateTimeUtil Unit tests`, () => { verifyTime(result, 12, 0, 0); result = DateTimeUtil.parseValueFromMask('12:00:00 AM', parts); verifyTime(result, 0, 0, 0); - } + }; const inputFormat = 'h:m:s'; let parts = DateTimeUtil.parseDateTimeFormat(`${inputFormat} tt`, angularFormatter); @@ -217,7 +218,7 @@ describe(`DateTimeUtil Unit tests`, () => { }); it('should properly build input formats based on locale', () => { - spyOn(DateTimeUtil, 'getDefaultInputFormat').and.callThrough(); + vi.spyOn(DateTimeUtil, 'getDefaultInputFormat'); let result = DateTimeUtil.getDefaultInputFormat('en-US', angularFormatter); expect(result).toEqual('MM/dd/yyyy'); @@ -263,17 +264,17 @@ describe(`DateTimeUtil Unit tests`, () => { }); it('should correctly distinguish date from time characters', () => { - expect(DateTimeUtil.isDateOrTimeChar('d')).toBeTrue(); - expect(DateTimeUtil.isDateOrTimeChar('M')).toBeTrue(); - expect(DateTimeUtil.isDateOrTimeChar('y')).toBeTrue(); - expect(DateTimeUtil.isDateOrTimeChar('H')).toBeTrue(); - expect(DateTimeUtil.isDateOrTimeChar('h')).toBeTrue(); - expect(DateTimeUtil.isDateOrTimeChar('m')).toBeTrue(); - expect(DateTimeUtil.isDateOrTimeChar('s')).toBeTrue(); - expect(DateTimeUtil.isDateOrTimeChar('S')).toBeTrue(); - expect(DateTimeUtil.isDateOrTimeChar(':')).toBeFalse(); - expect(DateTimeUtil.isDateOrTimeChar('/')).toBeFalse(); - expect(DateTimeUtil.isDateOrTimeChar('.')).toBeFalse(); + expect(DateTimeUtil.isDateOrTimeChar('d')).toBe(true); + expect(DateTimeUtil.isDateOrTimeChar('M')).toBe(true); + expect(DateTimeUtil.isDateOrTimeChar('y')).toBe(true); + expect(DateTimeUtil.isDateOrTimeChar('H')).toBe(true); + expect(DateTimeUtil.isDateOrTimeChar('h')).toBe(true); + expect(DateTimeUtil.isDateOrTimeChar('m')).toBe(true); + expect(DateTimeUtil.isDateOrTimeChar('s')).toBe(true); + expect(DateTimeUtil.isDateOrTimeChar('S')).toBe(true); + expect(DateTimeUtil.isDateOrTimeChar(':')).toBe(false); + expect(DateTimeUtil.isDateOrTimeChar('/')).toBe(false); + expect(DateTimeUtil.isDateOrTimeChar('.')).toBe(false); }); it('should spin date portions correctly', () => { @@ -500,72 +501,72 @@ describe(`DateTimeUtil Unit tests`, () => { // base let minValue = new Date(2010, 3, 2); let maxValue = new Date(2010, 3, 7); - expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2), minValue)).toBeFalse(); - expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 3), minValue)).toBeFalse(); - expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 1), minValue)).toBeTrue(); + expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2), minValue)).toBe(false); + expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 3), minValue)).toBe(false); + expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 1), minValue)).toBe(true); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 7), maxValue)).toBeFalse(); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 6), maxValue)).toBeFalse(); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 8), maxValue)).toBeTrue(); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 7), maxValue)).toBe(false); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 6), maxValue)).toBe(false); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 8), maxValue)).toBe(true); // time variations minValue = new Date(2010, 3, 2, 11, 10, 10); maxValue = new Date(2010, 3, 2, 15, 15, 15); - expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 11, 10, 11), minValue)).toBeFalse(); - expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 11, 10, 10), minValue)).toBeFalse(); - expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 11, 10, 9), minValue)).toBeTrue(); + expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 11, 10, 11), minValue)).toBe(false); + expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 11, 10, 10), minValue)).toBe(false); + expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 11, 10, 9), minValue)).toBe(true); - expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 11, 11, 10), minValue)).toBeFalse(); - expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 11, 10, 10), minValue)).toBeFalse(); - expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 11, 9, 10), minValue)).toBeTrue(); + expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 11, 11, 10), minValue)).toBe(false); + expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 11, 10, 10), minValue)).toBe(false); + expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 11, 9, 10), minValue)).toBe(true); - expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 12, 10, 10), minValue)).toBeFalse(); - expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 11, 10, 10), minValue)).toBeFalse(); - expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 10, 10, 10), minValue)).toBeTrue(); + expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 12, 10, 10), minValue)).toBe(false); + expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 11, 10, 10), minValue)).toBe(false); + expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 10, 10, 10), minValue)).toBe(true); - expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 3, 11, 10, 10), minValue)).toBeFalse(); - expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 11, 10, 10), minValue)).toBeFalse(); - expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 1, 11, 10, 10), minValue)).toBeTrue(); + expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 3, 11, 10, 10), minValue)).toBe(false); + expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 11, 10, 10), minValue)).toBe(false); + expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 1, 11, 10, 10), minValue)).toBe(true); - expect(DateTimeUtil.lessThanMinValue(new Date(2010, 4, 2, 11, 10, 10), minValue)).toBeFalse(); - expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 11, 10, 10), minValue)).toBeFalse(); - expect(DateTimeUtil.lessThanMinValue(new Date(2010, 2, 2, 11, 10, 10), minValue)).toBeTrue(); + expect(DateTimeUtil.lessThanMinValue(new Date(2010, 4, 2, 11, 10, 10), minValue)).toBe(false); + expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 11, 10, 10), minValue)).toBe(false); + expect(DateTimeUtil.lessThanMinValue(new Date(2010, 2, 2, 11, 10, 10), minValue)).toBe(true); - expect(DateTimeUtil.lessThanMinValue(new Date(2011, 3, 2, 11, 10, 10), minValue)).toBeFalse(); - expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 11, 10, 10), minValue)).toBeFalse(); - expect(DateTimeUtil.lessThanMinValue(new Date(2009, 3, 2, 11, 10, 10), minValue)).toBeTrue(); + expect(DateTimeUtil.lessThanMinValue(new Date(2011, 3, 2, 11, 10, 10), minValue)).toBe(false); + expect(DateTimeUtil.lessThanMinValue(new Date(2010, 3, 2, 11, 10, 10), minValue)).toBe(false); + expect(DateTimeUtil.lessThanMinValue(new Date(2009, 3, 2, 11, 10, 10), minValue)).toBe(true); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 15, 15, 16), maxValue)).toBeTrue(); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 15, 15, 15), maxValue)).toBeFalse(); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 15, 15, 14), maxValue)).toBeFalse(); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 15, 15, 16), maxValue)).toBe(true); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 15, 15, 15), maxValue)).toBe(false); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 15, 15, 14), maxValue)).toBe(false); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 15, 16, 15), maxValue)).toBeTrue(); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 15, 15, 15), maxValue)).toBeFalse(); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 15, 14, 15), maxValue)).toBeFalse(); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 15, 16, 15), maxValue)).toBe(true); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 15, 15, 15), maxValue)).toBe(false); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 15, 14, 15), maxValue)).toBe(false); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 16, 15, 15), maxValue)).toBeTrue(); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 15, 15, 15), maxValue)).toBeFalse(); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 14, 15, 15), maxValue)).toBeFalse(); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 16, 15, 15), maxValue)).toBe(true); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 15, 15, 15), maxValue)).toBe(false); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 14, 15, 15), maxValue)).toBe(false); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 3, 15, 15, 15), maxValue)).toBeTrue(); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 15, 15, 15), maxValue)).toBeFalse(); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 1, 15, 15, 15), maxValue)).toBeFalse(); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 3, 15, 15, 15), maxValue)).toBe(true); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 15, 15, 15), maxValue)).toBe(false); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 1, 15, 15, 15), maxValue)).toBe(false); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 4, 2, 15, 15, 15), maxValue)).toBeTrue(); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 15, 15, 15), maxValue)).toBeFalse(); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 2, 2, 15, 15, 15), maxValue)).toBeFalse(); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 4, 2, 15, 15, 15), maxValue)).toBe(true); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 15, 15, 15), maxValue)).toBe(false); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 2, 2, 15, 15, 15), maxValue)).toBe(false); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2011, 3, 2, 15, 15, 15), maxValue)).toBeTrue(); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 15, 15, 15), maxValue)).toBeFalse(); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2009, 3, 2, 15, 15, 15), maxValue)).toBeFalse(); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2011, 3, 2, 15, 15, 15), maxValue)).toBe(true); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2010, 3, 2, 15, 15, 15), maxValue)).toBe(false); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2009, 3, 2, 15, 15, 15), maxValue)).toBe(false); // date excluded - expect(DateTimeUtil.lessThanMinValue(new Date(2030, 3, 2, 11, 10, 9), minValue, true, false)).toBeTrue(); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2000, 3, 2, 15, 15, 16), minValue, true, false)).toBeTrue(); + expect(DateTimeUtil.lessThanMinValue(new Date(2030, 3, 2, 11, 10, 9), minValue, true, false)).toBe(true); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2000, 3, 2, 15, 15, 16), minValue, true, false)).toBe(true); // time excluded - expect(DateTimeUtil.lessThanMinValue(new Date(2009, 3, 2, 11, 10, 10), minValue, false, true)).toBeTrue(); - expect(DateTimeUtil.greaterThanMaxValue(new Date(2011, 3, 2, 15, 15, 15), minValue, true, false)).toBeTrue(); + expect(DateTimeUtil.lessThanMinValue(new Date(2009, 3, 2, 11, 10, 10), minValue, false, true)).toBe(true); + expect(DateTimeUtil.greaterThanMaxValue(new Date(2011, 3, 2, 15, 15, 15), minValue, true, false)).toBe(true); }); it('should return ValidationErrors for minValue and maxValue', () => { @@ -585,17 +586,13 @@ describe(`DateTimeUtil Unit tests`, () => { // ignore date portion expect(DateTimeUtil.validateMinMax(new Date(2000, 0, 1, 10, 10, 10), minValue, maxValue, true, false)).toEqual({}); - expect(DateTimeUtil.validateMinMax( - new Date(2020, 10, 10, 9, 10, 10), minValue, maxValue, true, false)).toEqual({ minValue: true }); - expect(DateTimeUtil.validateMinMax( - new Date(2000, 0, 1, 16, 0, 0), minValue, maxValue, true, false)).toEqual({ maxValue: true }); + expect(DateTimeUtil.validateMinMax(new Date(2020, 10, 10, 9, 10, 10), minValue, maxValue, true, false)).toEqual({ minValue: true }); + expect(DateTimeUtil.validateMinMax(new Date(2000, 0, 1, 16, 0, 0), minValue, maxValue, true, false)).toEqual({ maxValue: true }); // ignore time portion expect(DateTimeUtil.validateMinMax(new Date(2010, 3, 2, 9, 0, 0), minValue, maxValue, false, true)).toEqual({}); - expect(DateTimeUtil.validateMinMax( - new Date(2009, 3, 2, 11, 11, 11), minValue, maxValue, false, true)).toEqual({ minValue: true }); - expect(DateTimeUtil.validateMinMax( - new Date(2020, 3, 2, 0, 0, 0), minValue, maxValue, false, true)).toEqual({ maxValue: true }); + expect(DateTimeUtil.validateMinMax(new Date(2009, 3, 2, 11, 11, 11), minValue, maxValue, false, true)).toEqual({ minValue: true }); + expect(DateTimeUtil.validateMinMax(new Date(2020, 3, 2, 0, 0, 0), minValue, maxValue, false, true)).toEqual({ maxValue: true }); }); it('should parse dates correctly with parseIsoDate', () => { @@ -646,16 +643,16 @@ describe(`DateTimeUtil Unit tests`, () => { }); it('isValidDate should properly determine if a date is valid or not', () => { - expect(DateTimeUtil.isValidDate(new Date())).toBeTrue(); - expect(DateTimeUtil.isValidDate(new Date(NaN))).toBeFalse(); - expect(DateTimeUtil.isValidDate(new Date().getTime())).toBeFalse(); - expect(DateTimeUtil.isValidDate('')).toBeFalse(); - expect(DateTimeUtil.isValidDate({})).toBeFalse(); - expect(DateTimeUtil.isValidDate([])).toBeFalse(); - expect(DateTimeUtil.isValidDate(null)).toBeFalse(); - expect(DateTimeUtil.isValidDate(undefined)).toBeFalse(); - expect(DateTimeUtil.isValidDate(false)).toBeFalse(); - expect(DateTimeUtil.isValidDate(true)).toBeFalse(); + expect(DateTimeUtil.isValidDate(new Date())).toBe(true); + expect(DateTimeUtil.isValidDate(new Date(NaN))).toBe(false); + expect(DateTimeUtil.isValidDate(new Date().getTime())).toBe(false); + expect(DateTimeUtil.isValidDate('')).toBe(false); + expect(DateTimeUtil.isValidDate({})).toBe(false); + expect(DateTimeUtil.isValidDate([])).toBe(false); + expect(DateTimeUtil.isValidDate(null)).toBe(false); + expect(DateTimeUtil.isValidDate(undefined)).toBe(false); + expect(DateTimeUtil.isValidDate(false)).toBe(false); + expect(DateTimeUtil.isValidDate(true)).toBe(false); }); it('should correctly identify formats that would resolve to only numeric parts (and period) for the date/time parts', () => { @@ -669,14 +666,14 @@ describe(`DateTimeUtil Unit tests`, () => { 'dd/MM/yyyy test hh:mm' ]; numericFormats.forEach(format => { - expect(DateTimeUtil.isFormatNumeric(locale, format, angularFormatter)).withContext(`Format: ${format}`).toBeTrue(); + expect(DateTimeUtil.isFormatNumeric(locale, format, angularFormatter), `Format: ${format}`).toBe(true); }); const nonNumericFormats = ['MMM', 'MMMM', 'MMMMM', 'medium', 'long', 'full', 'mediumDate', 'longDate', 'fullDate', 'longTime', 'fullTime', 'dd-MMM-yyyy', 'E', 'EE']; nonNumericFormats.forEach(format => { - expect(DateTimeUtil.isFormatNumeric(locale, format, angularFormatter)).withContext(`Format: ${format}`).toBeFalse(); + expect(DateTimeUtil.isFormatNumeric(locale, format, angularFormatter), `Format: ${format}`).toBe(false); }); }); diff --git a/projects/igniteui-angular/core/src/date-common/util/helpers.spec.ts b/projects/igniteui-angular/core/src/date-common/util/helpers.spec.ts index b0a2f20b35b..5cfbd4d2b15 100644 --- a/projects/igniteui-angular/core/src/date-common/util/helpers.spec.ts +++ b/projects/igniteui-angular/core/src/date-common/util/helpers.spec.ts @@ -1,18 +1,7 @@ import { DateRangeType } from "../../core/dates/dateRange"; -import { - areSameMonth, - getNextActiveDate, - getPreviousActiveDate, - getClosestActiveDate, - isNextMonth, - isPreviousMonth, - calendarRange, - isDateInRanges, - generateMonth, - getYearRange, - formatToParts, -} from "./helpers"; +import { areSameMonth, getNextActiveDate, getPreviousActiveDate, getClosestActiveDate, isNextMonth, isPreviousMonth, calendarRange, isDateInRanges, generateMonth, getYearRange, formatToParts, } from "./helpers"; import { CalendarDay } from "./model"; +import { describe, it, expect } from 'vitest'; describe("Calendar Helpers", () => { const date = new Date(2020, 0, 1); @@ -47,19 +36,13 @@ describe("Calendar Helpers", () => { }); it("should get the next date for a given range", () => { - const nextDate = getNextActiveDate( - CalendarDay.from(date), - disabledDates, - ); + const nextDate = getNextActiveDate(CalendarDay.from(date), disabledDates); expect(nextDate.native).toEqual(new Date(2020, 0, 15)); }); it("should get the previous date for a given range", () => { - const nextDate = getPreviousActiveDate( - CalendarDay.from(date), - disabledDates, - ); + const nextDate = getPreviousActiveDate(CalendarDay.from(date), disabledDates); expect(nextDate.native).toEqual(new Date(2019, 11, 31)); }); @@ -68,19 +51,11 @@ describe("Calendar Helpers", () => { let target = CalendarDay.from(date); // Offset 1 day in the future - let nextDate = getClosestActiveDate( - CalendarDay.from(date), - 1, - disabledDates, - ); + let nextDate = getClosestActiveDate(CalendarDay.from(date), 1, disabledDates); expect(nextDate.native).toEqual(new Date(2020, 0, 15)); // Offset 1 day in the past - nextDate = getClosestActiveDate( - CalendarDay.from(date), - -1, - disabledDates, - ); + nextDate = getClosestActiveDate(CalendarDay.from(date), -1, disabledDates); expect(nextDate.native).toEqual(new Date(2019, 11, 31)); // Set the starting point to December 25th, 2019 @@ -109,14 +84,12 @@ describe("Calendar Helpers", () => { expect(range.length).toBe(7); range.forEach((day) => { - expect( - isDateInRanges(day, [ - { - type: DateRangeType.Between, - dateRange: [start.native, end.native], - }, - ]), - ).toBe(true); + expect(isDateInRanges(day, [ + { + type: DateRangeType.Between, + dateRange: [start.native, end.native], + }, + ])).toBe(true); }); }); @@ -128,17 +101,15 @@ describe("Calendar Helpers", () => { expect(range.length).toBe(42); range.forEach((day) => { - expect( - isDateInRanges(day, [ - { - type: DateRangeType.Between, - dateRange: [ - new Date(2019, 11, 30), - new Date(2020, 1, 9), - ], - }, - ]), - ).toBe(true); + expect(isDateInRanges(day, [ + { + type: DateRangeType.Between, + dateRange: [ + new Date(2019, 11, 30), + new Date(2020, 1, 9), + ], + }, + ])).toBe(true); }); }); @@ -153,67 +124,46 @@ describe("Calendar Helpers", () => { expect(isDateInRanges(date, disabledDates)).toBe(true); // Date is after range - expect( - isDateInRanges(date, [ - { - type: DateRangeType.After, - dateRange: [new Date(2020, 0, 2)], - }, - ]), - ).toBe(false); + expect(isDateInRanges(date, [ + { + type: DateRangeType.After, + dateRange: [new Date(2020, 0, 2)], + }, + ])).toBe(false); // Date is before range - expect( - isDateInRanges(date, [ - { - type: DateRangeType.Before, - dateRange: [new Date(2020, 0, 2)], - }, - ]), - ).toBe(true); + expect(isDateInRanges(date, [ + { + type: DateRangeType.Before, + dateRange: [new Date(2020, 0, 2)], + }, + ])).toBe(true); // Date is in a specific range - expect( - isDateInRanges(date, [ - { - type: DateRangeType.Specific, - dateRange: [new Date(2019, 11, 31), new Date(2020, 0, 2)], - }, - ]), - ).toBe(false); + expect(isDateInRanges(date, [ + { + type: DateRangeType.Specific, + dateRange: [new Date(2019, 11, 31), new Date(2020, 0, 2)], + }, + ])).toBe(false); // Date is a weekday - expect( - isDateInRanges(date, [ - { - type: DateRangeType.Weekdays, - }, - ]), - ).toBe(true); + expect(isDateInRanges(date, [ + { + type: DateRangeType.Weekdays, + }, + ])).toBe(true); // Date is not a weekend - expect( - isDateInRanges(date, [ - { - type: DateRangeType.Weekends, - }, - ]), - ).toBe(false); + expect(isDateInRanges(date, [ + { + type: DateRangeType.Weekends, + }, + ])).toBe(false); }); it("should get formatted parts by a given locale for a date", () => { - const { - date: day, - full, - day: dayObject, - month: monthObject, - year: yearObject, - } = formatToParts( - date, - "en", - { day: "numeric", month: "long", year: "numeric" }, - ["day", "month", "year"], - ); + const { date: day, full, day: dayObject, month: monthObject, year: yearObject, } = formatToParts(date, "en", { day: "numeric", month: "long", year: "numeric" }, ["day", "month", "year"]); expect(day).toEqual(date); diff --git a/projects/igniteui-angular/core/src/date-common/util/model.spec.ts b/projects/igniteui-angular/core/src/date-common/util/model.spec.ts index 53c4d69403e..4feec525fe8 100644 --- a/projects/igniteui-angular/core/src/date-common/util/model.spec.ts +++ b/projects/igniteui-angular/core/src/date-common/util/model.spec.ts @@ -1,6 +1,7 @@ import { DateRangeType } from '../../core/dates/dateRange'; import { calendarRange, isDateInRanges } from "./helpers"; import { CalendarDay } from "./model"; +import { describe, it, expect } from 'vitest'; export function first(arr: T[]) { return arr.at(0) as T; @@ -29,26 +30,26 @@ describe("Calendar Day Model", () => { // 2024/01/01 is a Monday expect(firstOfJan.day).toEqual(1); - expect(firstOfJan.weekend).toBeFalse(); + expect(firstOfJan.weekend).toBe(false); }); it("comparators", () => { const today = CalendarDay.today; - expect(today.greaterThan(firstOfJan)).toBeTrue(); - expect(firstOfJan.lessThan(today)).toBeTrue(); + expect(today.greaterThan(firstOfJan)).toBe(true); + expect(firstOfJan.lessThan(today)).toBe(true); expect(today.equalTo(new Date(Date.now()))); }); describe("Deltas", () => { it("day", () => { - expect(firstOfJan.add("day", 0).equalTo(firstOfJan)).toBeTrue(); - expect(firstOfJan.add("day", 1).greaterThan(firstOfJan)).toBeTrue(); - expect(firstOfJan.add("day", -1).lessThan(firstOfJan)).toBeTrue(); + expect(firstOfJan.add("day", 0).equalTo(firstOfJan)).toBe(true); + expect(firstOfJan.add("day", 1).greaterThan(firstOfJan)).toBe(true); + expect(firstOfJan.add("day", -1).lessThan(firstOfJan)).toBe(true); }); it("quarters", () => { - expect(firstOfJan.add("quarter", 0).equalTo(firstOfJan)).toBeTrue(); + expect(firstOfJan.add("quarter", 0).equalTo(firstOfJan)).toBe(true); const nextQ = firstOfJan.add("quarter", 1); expect(nextQ.month).toEqual(3); const prevQ = firstOfJan.add("quarter", -1); @@ -119,13 +120,13 @@ describe("Calendar Day Model", () => { const testDate = new CalendarDay({ year: 2024, month: 2, date: 15 }); // March 15, 2024 (Friday) // Test different week start days - const mondayStart = testDate.getWeekNumber(1); // ISO 8601 - const tuesdayStart = testDate.getWeekNumber(2); // Simple counting - const wednesdayStart = testDate.getWeekNumber(3); // Simple counting - const thursdayStart = testDate.getWeekNumber(4); // Simple counting - const fridayStart = testDate.getWeekNumber(5); // Simple counting - const saturdayStart = testDate.getWeekNumber(6); // Simple counting - const sundayStart = testDate.getWeekNumber(0); // Simple counting + const mondayStart = testDate.getWeekNumber(1); // ISO 8601 + const tuesdayStart = testDate.getWeekNumber(2); // Simple counting + const wednesdayStart = testDate.getWeekNumber(3); // Simple counting + const thursdayStart = testDate.getWeekNumber(4); // Simple counting + const fridayStart = testDate.getWeekNumber(5); // Simple counting + const saturdayStart = testDate.getWeekNumber(6); // Simple counting + const sundayStart = testDate.getWeekNumber(0); // Simple counting // All should be valid week numbers (positive integers) expect(mondayStart).toBeGreaterThan(0); @@ -226,9 +227,7 @@ describe("Calendar Day Model", () => { }); it("generating date ranges (end > start)", () => { - const weekFuture = Array.from( - calendarRange({ start, end: endFuture }), - ); + const weekFuture = Array.from(calendarRange({ start, end: endFuture })); expect(weekFuture.length).toEqual(end); @@ -263,57 +262,45 @@ describe("Calendar Day Model", () => { ]; it("After", () => { - expect( - isDateInRanges(start, [ - { type: DateRangeType.After, dateRange: [dayBefore] }, - ]), - ).toBeTrue(); + expect(isDateInRanges(start, [ + { type: DateRangeType.After, dateRange: [dayBefore] }, + ])).toBe(true); }); it("Before", () => { - expect( - isDateInRanges(start, [ - { type: DateRangeType.Before, dateRange: [dayAfter] }, - ]), - ).toBeTrue(); + expect(isDateInRanges(start, [ + { type: DateRangeType.Before, dateRange: [dayAfter] }, + ])).toBe(true); }); it("Between", () => { - expect( - isDateInRanges(start, [ - { - type: DateRangeType.Between, - dateRange: [begin, end], - }, - ]), - ).toBeTrue(); + expect(isDateInRanges(start, [ + { + type: DateRangeType.Between, + dateRange: [begin, end], + }, + ])).toBe(true); }); it("Specific", () => { - expect( - isDateInRanges(start, [ - { - type: DateRangeType.Specific, - dateRange: [], - }, - ]), - ).toBeFalse(); + expect(isDateInRanges(start, [ + { + type: DateRangeType.Specific, + dateRange: [], + }, + ])).toBe(false); }); it("Weekday", () => { - expect( - isDateInRanges(start, [{ type: DateRangeType.Weekdays }]), - ).toBeTrue(); + expect(isDateInRanges(start, [{ type: DateRangeType.Weekdays }])).toBe(true); }); it("Weekends", () => { - expect( - isDateInRanges(start, [ - { - type: DateRangeType.Weekends, - }, - ]), - ).toBeFalse(); + expect(isDateInRanges(start, [ + { + type: DateRangeType.Weekends, + }, + ])).toBe(false); }); }); }); diff --git a/projects/igniteui-angular/core/src/services/direction/directionality.spec.ts b/projects/igniteui-angular/core/src/services/direction/directionality.spec.ts index ad29ace4c56..5f6c2b61425 100644 --- a/projects/igniteui-angular/core/src/services/direction/directionality.spec.ts +++ b/projects/igniteui-angular/core/src/services/direction/directionality.spec.ts @@ -1,27 +1,30 @@ import { TestBed, inject, waitForAsync } from '@angular/core/testing'; import { Component, DOCUMENT, inject as inject_1 } from '@angular/core'; import { IgxDirectionality, DIR_DOCUMENT } from './directionality'; +import { describe, it, expect, beforeEach } from 'vitest'; interface FakeDoc { - body: { dir?: string }; - documentElement: { dir?: string }; + body: { + dir?: string; + }; + documentElement: { + dir?: string; + }; } describe('IgxDirectionality', () => { describe('DI', () => { - beforeEach(waitForAsync(() => - TestBed.configureTestingModule({ - imports: [InjectsIgxDirectionalityComponent] - }).compileComponents() - )); + beforeEach(waitForAsync(() => TestBed.configureTestingModule({ + imports: [InjectsIgxDirectionalityComponent] + }).compileComponents())); it('should inject the document through the injectionToken properly', () => { const injectionToken = TestBed.inject(DIR_DOCUMENT); const document = TestBed.inject(DOCUMENT); expect(injectionToken).toEqual(document); - expect(injectionToken).toEqual(jasmine.any(Document)); - expect(document).toBeTruthy(jasmine.any(Document)); + expect(injectionToken).toEqual(expect.any(Document)); + expect(document).toBeTruthy(expect.any(Document)); }); it('should read dir from html if not specified on the body', inject([DOCUMENT], () => { @@ -30,7 +33,7 @@ describe('IgxDirectionality', () => { expect(component.dir.document).not.toBeNull(); expect(component.dir.document).not.toBeUndefined(); - expect(component.dir.document).toEqual(jasmine.any(Document)); + expect(component.dir.document).toEqual(expect.any(Document)); })); }); diff --git a/projects/igniteui-angular/core/src/services/overlay/overlay.spec.ts b/projects/igniteui-angular/core/src/services/overlay/overlay.spec.ts index 2dd45ea03e2..b284be225a7 100644 --- a/projects/igniteui-angular/core/src/services/overlay/overlay.spec.ts +++ b/projects/igniteui-angular/core/src/services/overlay/overlay.spec.ts @@ -1,3 +1,4 @@ +import type { Mock } from "vitest"; import { Component, ComponentRef, ElementRef, HostBinding, Injector, ViewChild, ViewContainerRef, ViewEncapsulation, inject } from '@angular/core'; import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; @@ -16,23 +17,14 @@ import { AbsoluteScrollStrategy } from './scroll/absolute-scroll-strategy'; import { BlockScrollStrategy } from './scroll/block-scroll-strategy'; import { CloseScrollStrategy } from './scroll/close-scroll-strategy'; import { NoOpScrollStrategy } from './scroll/NoOpScrollStrategy'; -import { - HorizontalAlignment, - IgxOverlayOutletDirective, - OffsetMode, - OverlayCancelableEventArgs, - OverlayEventArgs, - OverlaySettings, - Point, - PositionSettings, - VerticalAlignment -} from './utilities'; +import { HorizontalAlignment, IgxOverlayOutletDirective, OffsetMode, OverlayCancelableEventArgs, OverlayEventArgs, OverlaySettings, Point, PositionSettings, VerticalAlignment } from './utilities'; import { scaleInVerTop, scaleOutVerTop } from 'igniteui-angular/animations'; import { IgxCalendarContainerComponent } from 'igniteui-angular/date-picker'; import { IgxAvatarComponent } from 'igniteui-angular/avatar'; import { IgxCalendarComponent } from 'igniteui-angular/calendar'; import { IgxToggleDirective } from 'igniteui-angular/directives'; import { PlatformUtil } from 'igniteui-angular'; +import { describe, it, expect, beforeEach, afterEach, afterAll, vi } from 'vitest'; const CLASS_OVERLAY_CONTENT = 'igx-overlay__content'; const CLASS_OVERLAY_CONTENT_MODAL = 'igx-overlay__content--modal'; @@ -50,10 +42,10 @@ const css = (element) => { const ret = []; element.matches = element.matches || - element.webkitMatchesSelector || - element.mozMatchesSelector || - element.msMatchesSelector || - element.oMatchesSelector; + element.webkitMatchesSelector || + element.mozMatchesSelector || + element.msMatchesSelector || + element.oMatchesSelector; for (const key in sheets) { if (sheets.hasOwnProperty(key)) { const sheet = sheets[key]; @@ -273,9 +265,9 @@ describe('igxOverlay', () => { }); it('Should clear listener for escape key when overlay settings have outlet specified', () => { - const addEventSpy = spyOn(document, 'addEventListener').and.callThrough(); - const removeEventSpy = spyOn(document, 'removeEventListener').and.callThrough(); - const hideSpy = spyOn(overlay, 'hide').and.callThrough(); + const addEventSpy = vi.spyOn(document, 'addEventListener'); + const removeEventSpy = vi.spyOn(document, 'removeEventListener'); + const hideSpy = vi.spyOn(overlay, 'hide'); const mockOverlaySettings: OverlaySettings = { modal: false, @@ -289,10 +281,9 @@ describe('igxOverlay', () => { overlay.show(id); // expect escape listener to be added to document - expect(addEventSpy).toHaveBeenCalledWith('keydown', jasmine.any(Function), undefined); + expect(addEventSpy).toHaveBeenCalledWith('keydown', expect.any(Function), undefined); - const listener = addEventSpy.calls.all() - .find(call => call.args[0] === 'keydown')?.args[1] as EventListener; + const listener = vi.mocked(addEventSpy).mock.calls.find(call => call.args[0] === 'keydown')?.args[1] as EventListener; expect(listener).toBeDefined(); @@ -338,7 +329,7 @@ describe('igxOverlay', () => { const overlayDiv = (fixture.nativeElement as HTMLElement) .parentElement.getElementsByClassName(CLASS_OVERLAY_MAIN)[0] as HTMLElement; expect(overlayDiv).toBeDefined(); - expect(overlayDiv).toHaveClass(CLASS_OVERLAY_MAIN); + expect(overlayDiv.classList.contains(CLASS_OVERLAY_MAIN)).toBe(true); fixture.componentInstance.overlay.detachAll(); })); @@ -397,12 +388,12 @@ describe('igxOverlay', () => { const wrapperElement = overlayElement.children[0]; expect(wrapperElement).toBeDefined(); - expect(wrapperElement).toHaveClass(CLASS_OVERLAY_WRAPPER_MODAL); + expect(wrapperElement.classList.contains(CLASS_OVERLAY_WRAPPER_MODAL)).toBe(true); expect(wrapperElement.children[0].localName).toEqual('div'); const contentElement = wrapperElement.children[0]; expect(contentElement).toBeDefined(); - expect(contentElement).toHaveClass(CLASS_OVERLAY_CONTENT_MODAL); + expect(contentElement.classList.contains(CLASS_OVERLAY_CONTENT_MODAL)).toBe(true); fixture.componentInstance.overlay.detachAll(); })); @@ -495,13 +486,13 @@ describe('igxOverlay', () => { const fixture = TestBed.createComponent(SimpleRefComponent); fixture.detectChanges(); const overlayInstance = fixture.componentInstance.overlay; - spyOn(overlayInstance.closed, 'emit'); - spyOn(overlayInstance.closing, 'emit'); - spyOn(overlayInstance.opened, 'emit'); - spyOn(overlayInstance.contentAppending, 'emit'); - spyOn(overlayInstance.contentAppended, 'emit'); - spyOn(overlayInstance.opening, 'emit'); - spyOn(overlayInstance.animationStarting, 'emit'); + vi.spyOn(overlayInstance.closed, 'emit'); + vi.spyOn(overlayInstance.closing, 'emit'); + vi.spyOn(overlayInstance.opened, 'emit'); + vi.spyOn(overlayInstance.contentAppending, 'emit'); + vi.spyOn(overlayInstance.contentAppended, 'emit'); + vi.spyOn(overlayInstance.opening, 'emit'); + vi.spyOn(overlayInstance.animationStarting, 'emit'); const firstCallId = overlayInstance.attach(SimpleDynamicComponent); overlayInstance.show(firstCallId); @@ -509,28 +500,28 @@ describe('igxOverlay', () => { expect(overlayInstance.opening.emit).toHaveBeenCalledTimes(1); expect(overlayInstance.opening.emit) - .toHaveBeenCalledWith({ id: firstCallId, componentRef: jasmine.any(ComponentRef) as any, cancel: false }); - const args: OverlayEventArgs = (overlayInstance.opening.emit as jasmine.Spy).calls.mostRecent().args[0]; - expect(args.componentRef.instance).toEqual(jasmine.any(SimpleDynamicComponent)); + .toHaveBeenCalledWith({ id: firstCallId, componentRef: expect.any(ComponentRef) as any, cancel: false }); + const args: OverlayEventArgs = vi.mocked((overlayInstance.opening.emit as Mock)).mock.lastCall[0]; + expect(args.componentRef.instance).toEqual(expect.any(SimpleDynamicComponent)); expect(overlayInstance.contentAppending.emit).toHaveBeenCalledTimes(1); expect(overlayInstance.contentAppended.emit).toHaveBeenCalledTimes(1); expect(overlayInstance.animationStarting.emit).toHaveBeenCalledTimes(1); tick(); expect(overlayInstance.opened.emit).toHaveBeenCalledTimes(1); - expect(overlayInstance.opened.emit).toHaveBeenCalledWith({ id: firstCallId, componentRef: jasmine.any(ComponentRef) as any }); + expect(overlayInstance.opened.emit).toHaveBeenCalledWith({ id: firstCallId, componentRef: expect.any(ComponentRef) as any }); overlayInstance.hide(firstCallId); tick(); expect(overlayInstance.closing.emit).toHaveBeenCalledTimes(1); expect(overlayInstance.closing.emit) - .toHaveBeenCalledWith({ id: firstCallId, componentRef: jasmine.any(ComponentRef) as any, cancel: false, event: undefined }); + .toHaveBeenCalledWith({ id: firstCallId, componentRef: expect.any(ComponentRef) as any, cancel: false, event: undefined }); expect(overlayInstance.animationStarting.emit).toHaveBeenCalledTimes(2); tick(); expect(overlayInstance.closed.emit).toHaveBeenCalledTimes(1); expect(overlayInstance.closed.emit). - toHaveBeenCalledWith({ id: firstCallId, componentRef: jasmine.any(ComponentRef) as any, event: undefined }); + toHaveBeenCalledWith({ id: firstCallId, componentRef: expect.any(ComponentRef) as any, event: undefined }); const secondCallId = overlayInstance.attach(fixture.componentInstance.item); overlayInstance.show(secondCallId); @@ -572,8 +563,8 @@ describe('igxOverlay', () => { closeOnEscape: false }; - spyOn(overlayInstance.contentAppending, 'emit'); - spyOn(overlayInstance.contentAppended, 'emit'); + vi.spyOn(overlayInstance.contentAppending, 'emit'); + vi.spyOn(overlayInstance.contentAppended, 'emit'); const firstCallId = overlayInstance.attach(SimpleDynamicComponent); overlayInstance.show(firstCallId); @@ -583,9 +574,9 @@ describe('igxOverlay', () => { expect(overlayInstance.contentAppended.emit).toHaveBeenCalledTimes(1); expect(overlayInstance.contentAppending.emit).toHaveBeenCalledWith({ - id: firstCallId, elementRef: jasmine.any(Object), - componentRef: jasmine.any(ComponentRef) as any, settings: os - }) + id: firstCallId, elementRef: expect.any(Object), + componentRef: expect.any(ComponentRef) as any, settings: os + }); })); it('Should properly be able to override OverlaySettings using contentAppending event args', fakeAsync(() => { @@ -607,13 +598,13 @@ describe('igxOverlay', () => { }); overlayInstance.contentAppended.pipe(first()).subscribe((e: OverlayEventArgs) => { const overlay = overlayInstance.getOverlayById(e.id); - expect(overlay.settings.closeOnEscape).toBeTrue(); + expect(overlay.settings.closeOnEscape).toBe(true); expect(overlay.settings.modal).toBeFalsy(); expect(overlay.settings.closeOnOutsideClick).toBeFalsy(); }); - spyOn(overlayInstance.contentAppended, 'emit').and.callThrough(); - spyOn(overlayInstance.contentAppending, 'emit').and.callThrough(); + vi.spyOn(overlayInstance.contentAppended, 'emit'); + vi.spyOn(overlayInstance.contentAppending, 'emit'); const firstCallId = overlayInstance.attach(SimpleDynamicComponent); overlayInstance.show(firstCallId); @@ -658,13 +649,13 @@ describe('igxOverlay', () => { const height = 200; const bottom = 200; const mockElement = document.createElement('div'); - spyOn(mockElement, 'getBoundingClientRect').and.callFake(() => ({ + vi.spyOn(mockElement, 'getBoundingClientRect').mockImplementation(() => ({ left, top, width, height, right, bottom } as DOMRect)); const mockItem = document.createElement('div'); mockElement.append(mockItem); - spyOn(mockItem, 'getBoundingClientRect').and.callFake(() => new DOMRect(top, left, width, height)); + vi.spyOn(mockItem, 'getBoundingClientRect').mockImplementation(() => new DOMRect(top, left, width, height)); const mockPositioningSettings1: PositionSettings = { horizontalDirection: HorizontalAlignment.Right, @@ -709,8 +700,8 @@ describe('igxOverlay', () => { }); it('Should properly call position method - AutoPosition.', () => { - spyOn(BaseFitPositionStrategy.prototype, 'position'); - spyOn(ConnectedPositioningStrategy.prototype, 'setStyle'); + vi.spyOn(BaseFitPositionStrategy.prototype, 'position'); + vi.spyOn(ConnectedPositioningStrategy.prototype, 'setStyle'); const mockDiv = document.createElement('div'); const autoStrat1 = new AutoPositionStrategy(); autoStrat1.position(mockDiv, null, document, false); @@ -727,8 +718,8 @@ describe('igxOverlay', () => { }); it('Should properly call position method - ElasticPosition.', () => { - spyOn(BaseFitPositionStrategy.prototype, 'position'); - spyOn(ConnectedPositioningStrategy.prototype, 'setStyle'); + vi.spyOn(BaseFitPositionStrategy.prototype, 'position'); + vi.spyOn(ConnectedPositioningStrategy.prototype, 'setStyle'); const mockDiv = document.createElement('div'); const autoStrat1 = new ElasticPositionStrategy(); @@ -925,34 +916,34 @@ describe('igxOverlay', () => { it('#2475 - An error is thrown for IgxOverlay when showing a component' + 'instance that is not attached to the DOM', fakeAsync(() => { - const fixture = TestBed.createComponent(SimpleRefComponent); - fixture.detectChanges(); - const overlay = fixture.componentInstance.overlay; + const fixture = TestBed.createComponent(SimpleRefComponent); + fixture.detectChanges(); + const overlay = fixture.componentInstance.overlay; - // remove SimpleRefComponent HTML element from the DOM tree - fixture.elementRef.nativeElement.parentElement.removeChild(fixture.elementRef.nativeElement); - overlay.show(overlay.attach(fixture.elementRef)); - tick(DEBOUNCE_TIME); + // remove SimpleRefComponent HTML element from the DOM tree + fixture.elementRef.nativeElement.parentElement.removeChild(fixture.elementRef.nativeElement); + overlay.show(overlay.attach(fixture.elementRef)); + tick(DEBOUNCE_TIME); - const componentElement = fixture.nativeElement as HTMLElement; - expect(componentElement).toBeDefined(); + const componentElement = fixture.nativeElement as HTMLElement; + expect(componentElement).toBeDefined(); - const contentElement = componentElement.parentElement; - expect(contentElement).toBeDefined(); - expect(contentElement).toHaveClass(CLASS_OVERLAY_CONTENT_MODAL); - expect(contentElement).toHaveClass(CLASS_OVERLAY_CONTENT_RELATIVE); + const contentElement = componentElement.parentElement; + expect(contentElement).toBeDefined(); + expect(contentElement.classList.contains(CLASS_OVERLAY_CONTENT_MODAL)).toBe(true); + expect(contentElement.classList.contains(CLASS_OVERLAY_CONTENT_RELATIVE)).toBe(true); - const wrapperElement = contentElement.parentElement; - expect(wrapperElement).toBeDefined(); - expect(wrapperElement).toHaveClass(CLASS_OVERLAY_WRAPPER_MODAL); - expect(wrapperElement).toHaveClass(CLASS_OVERLAY_WRAPPER_FLEX); + const wrapperElement = contentElement.parentElement; + expect(wrapperElement).toBeDefined(); + expect(wrapperElement.classList.contains(CLASS_OVERLAY_WRAPPER_MODAL)).toBe(true); + expect(wrapperElement.classList.contains(CLASS_OVERLAY_WRAPPER_FLEX)).toBe(true); - const overlayElement = wrapperElement.parentElement; - expect(overlayElement).toBeDefined(); - expect(overlayElement).toHaveClass(CLASS_OVERLAY_MAIN); + const overlayElement = wrapperElement.parentElement; + expect(overlayElement).toBeDefined(); + expect(overlayElement.classList.contains(CLASS_OVERLAY_MAIN)).toBe(true); - overlay.detachAll(); - })); + overlay.detachAll(); + })); it('#2486 - filtering dropdown is not correctly positioned', fakeAsync(() => { const fixture = TestBed.createComponent(WidthTestOverlayComponent); @@ -986,10 +977,10 @@ describe('igxOverlay', () => { e.cancel = true; }); - spyOn(overlayInstance.closed, 'emit').and.callThrough(); - spyOn(overlayInstance.closing, 'emit').and.callThrough(); - spyOn(overlayInstance.opened, 'emit').and.callThrough(); - spyOn(overlayInstance.opening, 'emit').and.callThrough(); + vi.spyOn(overlayInstance.closed, 'emit'); + vi.spyOn(overlayInstance.closing, 'emit'); + vi.spyOn(overlayInstance.opened, 'emit'); + vi.spyOn(overlayInstance.opening, 'emit'); const firstCallId = overlayInstance.attach(SimpleDynamicComponent); overlayInstance.show(firstCallId); @@ -1120,7 +1111,7 @@ describe('igxOverlay', () => { location: { nativeElement: mockNativeElement }, destroy: () => { } }; - spyOn(viewContainerRef, 'createComponent').and.returnValue(mockComponent as any); + vi.spyOn(viewContainerRef, 'createComponent').mockReturnValue(mockComponent as any); const id = overlay.attach(SimpleDynamicComponent, viewContainerRef); expect(viewContainerRef.createComponent).toHaveBeenCalledWith(SimpleDynamicComponent as any); expect(overlay.getOverlayById(id).componentRef as any).toBe(mockComponent); @@ -1341,7 +1332,7 @@ describe('igxOverlay', () => { const overlayInstance = fixture.componentInstance.overlay; const id = overlayInstance.attach(SimpleDynamicComponent); const info = overlayInstance.getOverlayById(id); - const initialPositionSpy = spyOn(info.settings.positionStrategy, 'position').and.callThrough(); + const initialPositionSpy = vi.spyOn(info.settings.positionStrategy, 'position'); overlayInstance.show(id); tick(); @@ -1358,7 +1349,7 @@ describe('igxOverlay', () => { closeOnOutsideClick: false, closeOnEscape: true }; - const lastPositionSpy = spyOn(os.positionStrategy, 'position').and.callThrough(); + const lastPositionSpy = vi.spyOn(os.positionStrategy, 'position'); overlayInstance.show(id, os); tick(); @@ -1395,10 +1386,10 @@ describe('igxOverlay', () => { closeOnOutsideClick: false }; const overlay = fixture.componentInstance.overlay; - spyOn(scrollStrat, 'initialize').and.callThrough(); - spyOn(scrollStrat, 'attach').and.callThrough(); - spyOn(scrollStrat, 'detach').and.callThrough(); - const scrollSpy = spyOn(scrollStrat, 'onScroll').and.callThrough(); + vi.spyOn(scrollStrat, 'initialize'); + vi.spyOn(scrollStrat, 'attach'); + vi.spyOn(scrollStrat, 'detach'); + const scrollSpy = vi.spyOn(scrollStrat, 'onScroll'); const overlayId = overlay.attach(SimpleDynamicComponent, overlaySettings); overlay.show(overlayId); tick(); @@ -1436,10 +1427,10 @@ describe('igxOverlay', () => { closeOnOutsideClick: false }; const overlay = fixture.componentInstance.overlay; - spyOn(scrollStrat, 'initialize').and.callThrough(); - spyOn(scrollStrat, 'attach').and.callThrough(); - spyOn(scrollStrat, 'detach').and.callThrough(); - const scrollSpy = spyOn(scrollStrat, 'onScroll').and.callThrough(); + vi.spyOn(scrollStrat, 'initialize'); + vi.spyOn(scrollStrat, 'attach'); + vi.spyOn(scrollStrat, 'detach'); + const scrollSpy = vi.spyOn(scrollStrat, 'onScroll'); const id = overlay.attach(SimpleDynamicComponent, overlaySettings); overlay.show(id); tick(); @@ -1476,8 +1467,8 @@ describe('igxOverlay', () => { closeOnOutsideClick: false }; const overlay = fixture.componentInstance.overlay; - const scrollSpy = spyOn(scrollStrat, 'onScroll').and.callThrough(); - spyOn(overlay, 'reposition'); + const scrollSpy = vi.spyOn(scrollStrat, 'onScroll'); + vi.spyOn(overlay, 'reposition'); const id = overlay.attach(SimpleDynamicComponent, overlaySettings); overlay.show(id); @@ -1518,10 +1509,10 @@ describe('igxOverlay', () => { closeOnOutsideClick: false }; const overlay = fixture.componentInstance.overlay; - spyOn(scrollStrat, 'initialize').and.callThrough(); - spyOn(scrollStrat, 'attach').and.callThrough(); - spyOn(scrollStrat, 'detach').and.callThrough(); - const scrollSpy = spyOn(scrollStrat, 'onScroll').and.callThrough(); + vi.spyOn(scrollStrat, 'initialize'); + vi.spyOn(scrollStrat, 'attach'); + vi.spyOn(scrollStrat, 'detach'); + const scrollSpy = vi.spyOn(scrollStrat, 'onScroll'); const id = overlay.attach(SimpleDynamicComponent, overlaySettings); overlay.show(id); @@ -1576,7 +1567,7 @@ describe('igxOverlay', () => { const overlayElement = (fixture.nativeElement as HTMLElement) .parentElement.getElementsByClassName(CLASS_OVERLAY_MAIN)[0] as HTMLElement; const wrapperElement = overlayElement.children[0]; - expect(wrapperElement).toHaveClass(CLASS_OVERLAY_WRAPPER); + expect(wrapperElement.classList.contains(CLASS_OVERLAY_WRAPPER)).toBe(true); overlay.detachAll(); })); @@ -1731,26 +1722,24 @@ describe('igxOverlay', () => { // 1.1.1 Global Css it('Should apply the css class on igx-overlay component div wrapper.' + - 'Test defaults: When no positionStrategy is passed use GlobalPositionStrategy with default PositionSettings and css class.', - fakeAsync(() => { - const fixture = TestBed.createComponent(EmptyPageComponent); - fixture.detectChanges(); - const overlay = fixture.componentInstance.overlay; + 'Test defaults: When no positionStrategy is passed use GlobalPositionStrategy with default PositionSettings and css class.', fakeAsync(() => { + const fixture = TestBed.createComponent(EmptyPageComponent); + fixture.detectChanges(); + const overlay = fixture.componentInstance.overlay; - overlay.show(overlay.attach(SimpleDynamicComponent)); - tick(DEBOUNCE_TIME); - fixture.detectChanges(); + overlay.show(overlay.attach(SimpleDynamicComponent)); + tick(DEBOUNCE_TIME); + fixture.detectChanges(); - // overlay container IS NOT a child of the debugElement (attached to body, not app-root) - const wrapperElement = (fixture.nativeElement as HTMLElement) - .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER_MODAL)[0] as HTMLElement; + // overlay container IS NOT a child of the debugElement (attached to body, not app-root) + const wrapperElement = (fixture.nativeElement as HTMLElement) + .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER_MODAL)[0] as HTMLElement; - expect(wrapperElement).toBeTruthy(); - expect(wrapperElement.localName).toEqual('div'); + expect(wrapperElement).toBeTruthy(); + expect(wrapperElement.localName).toEqual('div'); - overlay.detachAll(); - }) - ); + overlay.detachAll(); + })); it('Should apply css class on igx-overlay component inner div wrapper.', fakeAsync(() => { const fixture = TestBed.createComponent(EmptyPageComponent); @@ -1800,7 +1789,7 @@ describe('igxOverlay', () => { const wrapperElement = (fixture.nativeElement as HTMLElement) .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER)[0] as HTMLElement; expect(wrapperElement).toBeDefined(); - expect(wrapperElement).toHaveClass(CLASS_OVERLAY_WRAPPER); + expect(wrapperElement.classList.contains(CLASS_OVERLAY_WRAPPER)).toBe(true); overlay.detachAll(); })); @@ -1876,119 +1865,116 @@ describe('igxOverlay', () => { }); // adding more than one component to show in igx-overlay: - it('Should render the component exactly on top of the previous one when adding a new instance with default settings.', - fakeAsync(() => { - const fixture = TestBed.createComponent(TopLeftOffsetComponent); - const overlay = fixture.componentInstance.overlay; - const overlaySettings: OverlaySettings = { - positionStrategy: new ConnectedPositioningStrategy() - }; - overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); - overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); - tick(DEBOUNCE_TIME); - fixture.detectChanges(); - - const wrapperElements = (fixture.nativeElement as HTMLElement) - .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER_MODAL) as HTMLCollectionOf; - const wrapperElement1 = wrapperElements[0]; - const wrapperElement2 = wrapperElements[1]; - const componentElement1 = wrapperElement1.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; - const componentElement2 = wrapperElement2.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; - const componentRect1 = componentElement1.getBoundingClientRect(); - const componentRect2 = componentElement2.getBoundingClientRect(); - expect(componentRect1.left).toEqual(0); - expect(componentRect1.left).toEqual(componentRect2.left); - expect(componentRect1.top).toEqual(0); - expect(componentRect1.top).toEqual(componentRect2.top); - expect(componentRect1.width).toEqual(componentRect2.width); - expect(componentRect1.height).toEqual(componentRect2.height); - - overlay.detachAll(); - })); - - it('Should render the component exactly on top of the previous one when adding a new instance with the same options.', - fakeAsync(() => { - const fixture = TestBed.createComponent(TopLeftOffsetComponent); - const x = 200; - const y = 300; - - const overlay = fixture.componentInstance.overlay; - const positionSettings: PositionSettings = { - horizontalDirection: HorizontalAlignment.Left, - verticalDirection: VerticalAlignment.Top, - horizontalStartPoint: HorizontalAlignment.Left, - verticalStartPoint: VerticalAlignment.Bottom, - }; - const overlaySettings: OverlaySettings = { - target: new Point(x, y), - positionStrategy: new ConnectedPositioningStrategy(positionSettings) - }; - overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); - overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); - tick(DEBOUNCE_TIME); - fixture.detectChanges(); - - const wrapperElements = (fixture.nativeElement as HTMLElement) - .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER_MODAL) as HTMLCollectionOf; - const wrapperElement1 = wrapperElements[0]; - const wrapperElement2 = wrapperElements[1]; - const componentElement1 = wrapperElement1.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; - const componentElement2 = wrapperElement2.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; - const componentRect1 = componentElement1.getBoundingClientRect(); - const componentRect2 = componentElement2.getBoundingClientRect(); - expect(componentRect1.left).toEqual(x - componentRect1.width); - expect(componentRect1.left).toEqual(componentRect2.left); - expect(componentRect1.top).toEqual(y - componentRect1.height); - expect(componentRect1.top).toEqual(componentRect2.top); - expect(componentRect1.width).toEqual(componentRect2.width); - expect(componentRect1.height).toEqual(componentRect2.height); - - overlay.detachAll(); - })); - - it(`Should change the state of the component to closed when reaching threshold and closing scroll strategy is used.`, - fakeAsync(() => { - const fixture = TestBed.createComponent(EmptyPageComponent); - - // add one div far away to the right and to the bottom in order scrollbars to appear on page - addScrollDivToElement(fixture.nativeElement); - - const scrollStrat = new CloseScrollStrategy(); - fixture.detectChanges(); - const overlaySettings: OverlaySettings = { - scrollStrategy: scrollStrat, - modal: false, - closeOnOutsideClick: false - }; - const overlay = fixture.componentInstance.overlay; - overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); - tick(); - - let wrapperElement = (fixture.nativeElement as HTMLElement) - .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER)[0] as HTMLElement; - expect(wrapperElement.style.visibility).toEqual(''); - expect(document.documentElement.scrollTop).toEqual(0); - - document.documentElement.scrollTop += 9; - document.documentElement.dispatchEvent(new Event('scroll')); - tick(); - - expect(document.documentElement.scrollTop).toEqual(9); - wrapperElement = (fixture.nativeElement as HTMLElement) - .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER)[0] as HTMLElement; - expect(wrapperElement.style.visibility).toEqual(''); - - document.documentElement.scrollTop += 25; - document.documentElement.dispatchEvent(new Event('scroll')); - tick(); - - expect(document.documentElement.scrollTop).toEqual(34); - wrapperElement = (fixture.nativeElement as HTMLElement) - .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER)[0] as HTMLElement; - expect(wrapperElement.style.visibility).toEqual('hidden'); - - overlay.detachAll() - })); + it('Should render the component exactly on top of the previous one when adding a new instance with default settings.', fakeAsync(() => { + const fixture = TestBed.createComponent(TopLeftOffsetComponent); + const overlay = fixture.componentInstance.overlay; + const overlaySettings: OverlaySettings = { + positionStrategy: new ConnectedPositioningStrategy() + }; + overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); + overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); + tick(DEBOUNCE_TIME); + fixture.detectChanges(); + + const wrapperElements = (fixture.nativeElement as HTMLElement) + .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER_MODAL) as HTMLCollectionOf; + const wrapperElement1 = wrapperElements[0]; + const wrapperElement2 = wrapperElements[1]; + const componentElement1 = wrapperElement1.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; + const componentElement2 = wrapperElement2.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; + const componentRect1 = componentElement1.getBoundingClientRect(); + const componentRect2 = componentElement2.getBoundingClientRect(); + expect(componentRect1.left).toEqual(0); + expect(componentRect1.left).toEqual(componentRect2.left); + expect(componentRect1.top).toEqual(0); + expect(componentRect1.top).toEqual(componentRect2.top); + expect(componentRect1.width).toEqual(componentRect2.width); + expect(componentRect1.height).toEqual(componentRect2.height); + + overlay.detachAll(); + })); + + it('Should render the component exactly on top of the previous one when adding a new instance with the same options.', fakeAsync(() => { + const fixture = TestBed.createComponent(TopLeftOffsetComponent); + const x = 200; + const y = 300; + + const overlay = fixture.componentInstance.overlay; + const positionSettings: PositionSettings = { + horizontalDirection: HorizontalAlignment.Left, + verticalDirection: VerticalAlignment.Top, + horizontalStartPoint: HorizontalAlignment.Left, + verticalStartPoint: VerticalAlignment.Bottom, + }; + const overlaySettings: OverlaySettings = { + target: new Point(x, y), + positionStrategy: new ConnectedPositioningStrategy(positionSettings) + }; + overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); + overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); + tick(DEBOUNCE_TIME); + fixture.detectChanges(); + + const wrapperElements = (fixture.nativeElement as HTMLElement) + .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER_MODAL) as HTMLCollectionOf; + const wrapperElement1 = wrapperElements[0]; + const wrapperElement2 = wrapperElements[1]; + const componentElement1 = wrapperElement1.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; + const componentElement2 = wrapperElement2.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; + const componentRect1 = componentElement1.getBoundingClientRect(); + const componentRect2 = componentElement2.getBoundingClientRect(); + expect(componentRect1.left).toEqual(x - componentRect1.width); + expect(componentRect1.left).toEqual(componentRect2.left); + expect(componentRect1.top).toEqual(y - componentRect1.height); + expect(componentRect1.top).toEqual(componentRect2.top); + expect(componentRect1.width).toEqual(componentRect2.width); + expect(componentRect1.height).toEqual(componentRect2.height); + + overlay.detachAll(); + })); + + it(`Should change the state of the component to closed when reaching threshold and closing scroll strategy is used.`, fakeAsync(() => { + const fixture = TestBed.createComponent(EmptyPageComponent); + + // add one div far away to the right and to the bottom in order scrollbars to appear on page + addScrollDivToElement(fixture.nativeElement); + + const scrollStrat = new CloseScrollStrategy(); + fixture.detectChanges(); + const overlaySettings: OverlaySettings = { + scrollStrategy: scrollStrat, + modal: false, + closeOnOutsideClick: false + }; + const overlay = fixture.componentInstance.overlay; + overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); + tick(); + + let wrapperElement = (fixture.nativeElement as HTMLElement) + .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER)[0] as HTMLElement; + expect(wrapperElement.style.visibility).toEqual(''); + expect(document.documentElement.scrollTop).toEqual(0); + + document.documentElement.scrollTop += 9; + document.documentElement.dispatchEvent(new Event('scroll')); + tick(); + + expect(document.documentElement.scrollTop).toEqual(9); + wrapperElement = (fixture.nativeElement as HTMLElement) + .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER)[0] as HTMLElement; + expect(wrapperElement.style.visibility).toEqual(''); + + document.documentElement.scrollTop += 25; + document.documentElement.dispatchEvent(new Event('scroll')); + tick(); + + expect(document.documentElement.scrollTop).toEqual(34); + wrapperElement = (fixture.nativeElement as HTMLElement) + .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER)[0] as HTMLElement; + expect(wrapperElement.style.visibility).toEqual('hidden'); + + overlay.detachAll(); + })); it('Should scroll component with the scrolling container when absolute scroll strategy is used.', fakeAsync(() => { const fixture = TestBed.createComponent(EmptyPageComponent); @@ -2076,7 +2062,7 @@ describe('igxOverlay', () => { fixture.detectChanges(); // for a Point(300,300); - const expectedTopForPoint: number[] = [240, 270, 300]; // top/middle/bottom/ + const expectedTopForPoint: number[] = [240, 270, 300]; // top/middle/bottom/ const expectedLeftForPoint: number[] = [240, 270, 300]; // left/center/right/ const size = { width: 60, height: 60 }; @@ -2126,7 +2112,7 @@ describe('igxOverlay', () => { fixture.detectChanges(); // for a Point(300,300); - const expectedTopForPoint: Array = [240, 270, 300]; // top/middle/bottom/ + const expectedTopForPoint: Array = [240, 270, 300]; // top/middle/bottom/ const expectedLeftForPoint: Array = [240, 270, 300]; // left/center/right/ const size = { width: 60, height: 60 }; @@ -2202,7 +2188,7 @@ describe('igxOverlay', () => { const wrapperElement = (fixture.nativeElement as HTMLElement) .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER)[0] as HTMLElement; expect(wrapperElement).toBeDefined(); - expect(wrapperElement).toHaveClass(CLASS_OVERLAY_WRAPPER); + expect(wrapperElement.classList.contains(CLASS_OVERLAY_WRAPPER)).toBe(true); overlay.detachAll(); })); @@ -2499,96 +2485,95 @@ describe('igxOverlay', () => { // When adding more than one component to show in igx-overlay: it('When the options used to fit the component in the window - adding a new instance of the component with the ' + ' same options will render it on top of the previous one.', fakeAsync(() => { - const fixture = TestBed.createComponent(EmptyPageComponent); - fixture.detectChanges(); - - const overlay = fixture.componentInstance.overlay; - const button = fixture.componentInstance.buttonElement.nativeElement; - const positionSettings: PositionSettings = { - horizontalDirection: HorizontalAlignment.Right, - verticalDirection: VerticalAlignment.Bottom, - horizontalStartPoint: HorizontalAlignment.Center, - verticalStartPoint: VerticalAlignment.Bottom - }; - const overlaySettings: OverlaySettings = { - target: button, - positionStrategy: new AutoPositionStrategy(positionSettings), - scrollStrategy: new NoOpScrollStrategy(), - modal: false, - closeOnOutsideClick: false - }; - overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); - overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); - fixture.detectChanges(); - tick(); - - const wrapperElements = (fixture.nativeElement as HTMLElement) - .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER) as HTMLCollectionOf; - const wrapperElement1 = wrapperElements[0]; - const wrapperElement2 = wrapperElements[1]; - const componentElement1 = wrapperElement1.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; - const componentElement2 = wrapperElement2.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; - const componentRect1 = componentElement1.getBoundingClientRect(); - const componentRect2 = componentElement2.getBoundingClientRect(); - const buttonRect = button.getBoundingClientRect(); - expect(componentRect1.left.toFixed(1)).toEqual((buttonRect.left + buttonRect.width / 2).toFixed(1)); - expect(componentRect1.left.toFixed(1)).toEqual(componentRect2.left.toFixed(1)); - expect(componentRect1.top.toFixed(1)).toEqual((buttonRect.top + buttonRect.height).toFixed(1)); - expect(componentRect1.top.toFixed(1)).toEqual(componentRect2.top.toFixed(1)); - expect(componentRect1.width.toFixed(1)).toEqual(componentRect2.width.toFixed(1)); - expect(componentRect1.height.toFixed(1)).toEqual(componentRect2.height.toFixed(1)); - - overlay.detachAll(); - })); + const fixture = TestBed.createComponent(EmptyPageComponent); + fixture.detectChanges(); + + const overlay = fixture.componentInstance.overlay; + const button = fixture.componentInstance.buttonElement.nativeElement; + const positionSettings: PositionSettings = { + horizontalDirection: HorizontalAlignment.Right, + verticalDirection: VerticalAlignment.Bottom, + horizontalStartPoint: HorizontalAlignment.Center, + verticalStartPoint: VerticalAlignment.Bottom + }; + const overlaySettings: OverlaySettings = { + target: button, + positionStrategy: new AutoPositionStrategy(positionSettings), + scrollStrategy: new NoOpScrollStrategy(), + modal: false, + closeOnOutsideClick: false + }; + overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); + overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); + fixture.detectChanges(); + tick(); + + const wrapperElements = (fixture.nativeElement as HTMLElement) + .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER) as HTMLCollectionOf; + const wrapperElement1 = wrapperElements[0]; + const wrapperElement2 = wrapperElements[1]; + const componentElement1 = wrapperElement1.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; + const componentElement2 = wrapperElement2.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; + const componentRect1 = componentElement1.getBoundingClientRect(); + const componentRect2 = componentElement2.getBoundingClientRect(); + const buttonRect = button.getBoundingClientRect(); + expect(componentRect1.left.toFixed(1)).toEqual((buttonRect.left + buttonRect.width / 2).toFixed(1)); + expect(componentRect1.left.toFixed(1)).toEqual(componentRect2.left.toFixed(1)); + expect(componentRect1.top.toFixed(1)).toEqual((buttonRect.top + buttonRect.height).toFixed(1)); + expect(componentRect1.top.toFixed(1)).toEqual(componentRect2.top.toFixed(1)); + expect(componentRect1.width.toFixed(1)).toEqual(componentRect2.width.toFixed(1)); + expect(componentRect1.height.toFixed(1)).toEqual(componentRect2.height.toFixed(1)); + + overlay.detachAll(); + })); // When adding more than one component to show in igx-overlay and the options used will not fit the component in the // window, so AutoPosition is used. - it('When adding a new instance of the component with the same options, will render it on top of the previous one.', - fakeAsync(() => { - const fixture = TestBed.createComponent(EmptyPageComponent); - fixture.detectChanges(); - - const overlay = fixture.componentInstance.overlay; - const button = fixture.componentInstance.buttonElement.nativeElement; - const positionSettings: PositionSettings = { - horizontalDirection: HorizontalAlignment.Left, - verticalDirection: VerticalAlignment.Top, - horizontalStartPoint: HorizontalAlignment.Left, - verticalStartPoint: VerticalAlignment.Top - }; - const overlaySettings: OverlaySettings = { - target: button, - positionStrategy: new AutoPositionStrategy(positionSettings), - scrollStrategy: new NoOpScrollStrategy(), - modal: false, - closeOnOutsideClick: false - }; - overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); - fixture.detectChanges(); - tick(); - overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); - fixture.detectChanges(); - tick(); - const buttonRect = button.getBoundingClientRect(); - - const wrapperElements = (fixture.nativeElement as HTMLElement) - .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER) as HTMLCollectionOf; - const wrapperElement1 = wrapperElements[0]; - const wrapperElement2 = wrapperElements[1]; - const componentElement1 = wrapperElement1.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; - const componentElement2 = wrapperElement2.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; - const componentRect1 = componentElement1.getBoundingClientRect(); - const componentRect2 = componentElement2.getBoundingClientRect(); - - // Will be positioned on the right of the button - expect(Math.round(componentRect1.left)).toEqual(Math.round(buttonRect.right)); - expect(Math.round(componentRect1.left)).toEqual(Math.round(componentRect2.left)); // Are on the same spot - expect(Math.round(componentRect1.top)).toEqual(Math.round(componentRect2.top)); // Will have the same top - expect(Math.round(componentRect1.width)).toEqual(Math.round(componentRect2.width)); // Will have the same width - expect(Math.round(componentRect1.height)).toEqual(Math.round(componentRect2.height)); // Will have the same height - - overlay.detachAll(); - })); + it('When adding a new instance of the component with the same options, will render it on top of the previous one.', fakeAsync(() => { + const fixture = TestBed.createComponent(EmptyPageComponent); + fixture.detectChanges(); + + const overlay = fixture.componentInstance.overlay; + const button = fixture.componentInstance.buttonElement.nativeElement; + const positionSettings: PositionSettings = { + horizontalDirection: HorizontalAlignment.Left, + verticalDirection: VerticalAlignment.Top, + horizontalStartPoint: HorizontalAlignment.Left, + verticalStartPoint: VerticalAlignment.Top + }; + const overlaySettings: OverlaySettings = { + target: button, + positionStrategy: new AutoPositionStrategy(positionSettings), + scrollStrategy: new NoOpScrollStrategy(), + modal: false, + closeOnOutsideClick: false + }; + overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); + fixture.detectChanges(); + tick(); + overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); + fixture.detectChanges(); + tick(); + const buttonRect = button.getBoundingClientRect(); + + const wrapperElements = (fixture.nativeElement as HTMLElement) + .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER) as HTMLCollectionOf; + const wrapperElement1 = wrapperElements[0]; + const wrapperElement2 = wrapperElements[1]; + const componentElement1 = wrapperElement1.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; + const componentElement2 = wrapperElement2.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; + const componentRect1 = componentElement1.getBoundingClientRect(); + const componentRect2 = componentElement2.getBoundingClientRect(); + + // Will be positioned on the right of the button + expect(Math.round(componentRect1.left)).toEqual(Math.round(buttonRect.right)); + expect(Math.round(componentRect1.left)).toEqual(Math.round(componentRect2.left)); // Are on the same spot + expect(Math.round(componentRect1.top)).toEqual(Math.round(componentRect2.top)); // Will have the same top + expect(Math.round(componentRect1.width)).toEqual(Math.round(componentRect2.width)); // Will have the same width + expect(Math.round(componentRect1.height)).toEqual(Math.round(componentRect2.height)); // Will have the same height + + overlay.detachAll(); + })); it(`Should persist the component's open state when scrolling, when scrolling and noOP scroll strategy is used (expanded DropDown remains expanded).`, fakeAsync(() => { @@ -2603,12 +2588,12 @@ describe('igxOverlay', () => { positionStrategy: new GlobalPositionStrategy() }; - spyOn(scrollStrategy, 'initialize').and.callThrough(); - spyOn(scrollStrategy, 'attach').and.callThrough(); - spyOn(scrollStrategy, 'detach').and.callThrough(); - spyOn(overlay, 'hide').and.callThrough(); + vi.spyOn(scrollStrategy, 'initialize'); + vi.spyOn(scrollStrategy, 'attach'); + vi.spyOn(scrollStrategy, 'detach'); + vi.spyOn(overlay, 'hide'); - const scrollSpy = spyOn(scrollStrategy, 'onScroll').and.callThrough(); + const scrollSpy = vi.spyOn(scrollStrategy, 'onScroll'); const overlayId = overlay.attach(SimpleDynamicComponent, overlaySettings); overlay.show(overlayId); @@ -2640,12 +2625,12 @@ describe('igxOverlay', () => { scrollStrategy }; - spyOn(scrollStrategy, 'initialize').and.callThrough(); - spyOn(scrollStrategy, 'attach').and.callThrough(); - spyOn(scrollStrategy, 'detach').and.callThrough(); - spyOn(overlay, 'hide').and.callThrough(); + vi.spyOn(scrollStrategy, 'initialize'); + vi.spyOn(scrollStrategy, 'attach'); + vi.spyOn(scrollStrategy, 'detach'); + vi.spyOn(overlay, 'hide'); - const scrollSpy = spyOn(scrollStrategy, 'onScroll').and.callThrough(); + const scrollSpy = vi.spyOn(scrollStrategy, 'onScroll'); overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); tick(); @@ -2688,7 +2673,7 @@ describe('igxOverlay', () => { const wrapperElement = (fixture.nativeElement as HTMLElement) .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER)[0] as HTMLElement; expect(wrapperElement).toBeDefined(); - expect(wrapperElement).toHaveClass(CLASS_OVERLAY_WRAPPER); + expect(wrapperElement.classList.contains(CLASS_OVERLAY_WRAPPER)).toBe(true); overlay.detachAll(); })); @@ -2999,97 +2984,96 @@ describe('igxOverlay', () => { // When adding more than one component to show in igx-overlay: it('When the options used to fit the component in the window - adding a new instance of the component with the ' + ' same options will render it on top of the previous one.', fakeAsync(() => { - const fixture = TestBed.createComponent(EmptyPageComponent); - fixture.detectChanges(); - - const overlay = fixture.componentInstance.overlay; - const button = fixture.componentInstance.buttonElement.nativeElement; - const positionSettings: PositionSettings = { - horizontalDirection: HorizontalAlignment.Right, - verticalDirection: VerticalAlignment.Bottom, - horizontalStartPoint: HorizontalAlignment.Center, - verticalStartPoint: VerticalAlignment.Bottom - }; - const overlaySettings: OverlaySettings = { - target: button, - positionStrategy: new ElasticPositionStrategy(positionSettings), - scrollStrategy: new NoOpScrollStrategy(), - modal: false, - closeOnOutsideClick: false - }; - overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); - overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); - fixture.detectChanges(); - tick(); - - const buttonRect = button.getBoundingClientRect(); - const wrapperElements = (fixture.nativeElement as HTMLElement) - .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER) as HTMLCollectionOf; - const wrapperElement1 = wrapperElements[0]; - const wrapperElement2 = wrapperElements[1]; - const componentElement1 = wrapperElement1.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; - const componentElement2 = wrapperElement2.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; - const componentRect1 = componentElement1.getBoundingClientRect(); - const componentRect2 = componentElement2.getBoundingClientRect(); - expect(componentRect1.left.toFixed(1)).toEqual((buttonRect.left + buttonRect.width / 2).toFixed(1)); - expect(componentRect1.left.toFixed(1)).toEqual(componentRect2.left.toFixed(1)); - expect(componentRect1.top.toFixed(1)).toEqual((buttonRect.top + buttonRect.height).toFixed(1)); - expect(componentRect1.top.toFixed(1)).toEqual(componentRect2.top.toFixed(1)); - expect(componentRect1.width.toFixed(1)).toEqual(componentRect2.width.toFixed(1)); - expect(componentRect1.height.toFixed(1)).toEqual(componentRect2.height.toFixed(1)); - - overlay.detachAll(); - })); + const fixture = TestBed.createComponent(EmptyPageComponent); + fixture.detectChanges(); + + const overlay = fixture.componentInstance.overlay; + const button = fixture.componentInstance.buttonElement.nativeElement; + const positionSettings: PositionSettings = { + horizontalDirection: HorizontalAlignment.Right, + verticalDirection: VerticalAlignment.Bottom, + horizontalStartPoint: HorizontalAlignment.Center, + verticalStartPoint: VerticalAlignment.Bottom + }; + const overlaySettings: OverlaySettings = { + target: button, + positionStrategy: new ElasticPositionStrategy(positionSettings), + scrollStrategy: new NoOpScrollStrategy(), + modal: false, + closeOnOutsideClick: false + }; + overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); + overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); + fixture.detectChanges(); + tick(); + + const buttonRect = button.getBoundingClientRect(); + const wrapperElements = (fixture.nativeElement as HTMLElement) + .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER) as HTMLCollectionOf; + const wrapperElement1 = wrapperElements[0]; + const wrapperElement2 = wrapperElements[1]; + const componentElement1 = wrapperElement1.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; + const componentElement2 = wrapperElement2.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; + const componentRect1 = componentElement1.getBoundingClientRect(); + const componentRect2 = componentElement2.getBoundingClientRect(); + expect(componentRect1.left.toFixed(1)).toEqual((buttonRect.left + buttonRect.width / 2).toFixed(1)); + expect(componentRect1.left.toFixed(1)).toEqual(componentRect2.left.toFixed(1)); + expect(componentRect1.top.toFixed(1)).toEqual((buttonRect.top + buttonRect.height).toFixed(1)); + expect(componentRect1.top.toFixed(1)).toEqual(componentRect2.top.toFixed(1)); + expect(componentRect1.width.toFixed(1)).toEqual(componentRect2.width.toFixed(1)); + expect(componentRect1.height.toFixed(1)).toEqual(componentRect2.height.toFixed(1)); + + overlay.detachAll(); + })); // When adding more than one component to show in igx-overlay and the options used will not fit the component in the // window, so element is resized. - it('When adding a new instance of the component with the same options, will render it on top of the previous one.', - fakeAsync(() => { - const fixture = TestBed.createComponent(EmptyPageComponent); - fixture.detectChanges(); - - const overlay = fixture.componentInstance.overlay; - const button = fixture.componentInstance.buttonElement.nativeElement; - const positionSettings: PositionSettings = { - horizontalDirection: HorizontalAlignment.Left, - verticalDirection: VerticalAlignment.Top, - horizontalStartPoint: HorizontalAlignment.Left, - verticalStartPoint: VerticalAlignment.Top, - minSize: { width: 80, height: 80 } - }; - const overlaySettings: OverlaySettings = { - target: button, - positionStrategy: new ElasticPositionStrategy(positionSettings), - scrollStrategy: new NoOpScrollStrategy(), - modal: false, - closeOnOutsideClick: false - }; - overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); - fixture.detectChanges(); - tick(); - - overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); - fixture.detectChanges(); - tick(); - - const buttonRect = button.getBoundingClientRect(); - - const wrapperElements = (fixture.nativeElement as HTMLElement) - .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER) as HTMLCollectionOf; - const wrapperElement1 = wrapperElements[0]; - const wrapperElement2 = wrapperElements[1]; - const componentElement1 = wrapperElement1.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; - const componentElement2 = wrapperElement2.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; - const componentRect1 = componentElement1.getBoundingClientRect(); - const componentRect2 = componentElement2.getBoundingClientRect(); - expect(componentRect1.left).toEqual(buttonRect.left - positionSettings.minSize.width); - expect(componentRect1.left).toEqual(componentRect2.left); - expect(componentRect1.top).toEqual(componentRect2.top); - expect(componentRect1.width).toEqual(componentRect2.width); - expect(componentRect1.height).toEqual(componentRect2.height); - - overlay.detachAll(); - })); + it('When adding a new instance of the component with the same options, will render it on top of the previous one.', fakeAsync(() => { + const fixture = TestBed.createComponent(EmptyPageComponent); + fixture.detectChanges(); + + const overlay = fixture.componentInstance.overlay; + const button = fixture.componentInstance.buttonElement.nativeElement; + const positionSettings: PositionSettings = { + horizontalDirection: HorizontalAlignment.Left, + verticalDirection: VerticalAlignment.Top, + horizontalStartPoint: HorizontalAlignment.Left, + verticalStartPoint: VerticalAlignment.Top, + minSize: { width: 80, height: 80 } + }; + const overlaySettings: OverlaySettings = { + target: button, + positionStrategy: new ElasticPositionStrategy(positionSettings), + scrollStrategy: new NoOpScrollStrategy(), + modal: false, + closeOnOutsideClick: false + }; + overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); + fixture.detectChanges(); + tick(); + + overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); + fixture.detectChanges(); + tick(); + + const buttonRect = button.getBoundingClientRect(); + + const wrapperElements = (fixture.nativeElement as HTMLElement) + .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER) as HTMLCollectionOf; + const wrapperElement1 = wrapperElements[0]; + const wrapperElement2 = wrapperElements[1]; + const componentElement1 = wrapperElement1.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; + const componentElement2 = wrapperElement2.getElementsByTagName('test-simple-dynamic-component')[0] as HTMLElement; + const componentRect1 = componentElement1.getBoundingClientRect(); + const componentRect2 = componentElement2.getBoundingClientRect(); + expect(componentRect1.left).toEqual(buttonRect.left - positionSettings.minSize.width); + expect(componentRect1.left).toEqual(componentRect2.left); + expect(componentRect1.top).toEqual(componentRect2.top); + expect(componentRect1.width).toEqual(componentRect2.width); + expect(componentRect1.height).toEqual(componentRect2.height); + + overlay.detachAll(); + })); it(`Should persist the component's open state when scrolling, when scrolling and noOP scroll strategy is used (expanded DropDown remains expanded).`, fakeAsync(() => { @@ -3104,12 +3088,12 @@ describe('igxOverlay', () => { positionStrategy: new ElasticPositionStrategy() }; - spyOn(scrollStrategy, 'initialize').and.callThrough(); - spyOn(scrollStrategy, 'attach').and.callThrough(); - spyOn(scrollStrategy, 'detach').and.callThrough(); - spyOn(overlay, 'hide').and.callThrough(); + vi.spyOn(scrollStrategy, 'initialize'); + vi.spyOn(scrollStrategy, 'attach'); + vi.spyOn(scrollStrategy, 'detach'); + vi.spyOn(overlay, 'hide'); - const scrollSpy = spyOn(scrollStrategy, 'onScroll').and.callThrough(); + const scrollSpy = vi.spyOn(scrollStrategy, 'onScroll'); const overlayId = overlay.attach(SimpleDynamicComponent, overlaySettings); overlay.show(overlayId); @@ -3141,12 +3125,12 @@ describe('igxOverlay', () => { scrollStrategy }; - spyOn(scrollStrategy, 'initialize').and.callThrough(); - spyOn(scrollStrategy, 'attach').and.callThrough(); - spyOn(scrollStrategy, 'detach').and.callThrough(); - spyOn(overlay, 'hide').and.callThrough(); + vi.spyOn(scrollStrategy, 'initialize'); + vi.spyOn(scrollStrategy, 'attach'); + vi.spyOn(scrollStrategy, 'detach'); + vi.spyOn(overlay, 'hide'); - const scrollSpy = spyOn(scrollStrategy, 'onScroll').and.callThrough(); + const scrollSpy = vi.spyOn(scrollStrategy, 'onScroll'); overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); tick(); @@ -3222,11 +3206,9 @@ describe('igxOverlay', () => { expect(wrapperElement).toBeDefined(); const styles = css(wrapperElement); - expect(styles.findIndex( - (e) => e.includes('--background-color: var(--igx-overlay-background-color, hsl(from var(--ig-gray-500) h s l/0.54));'))) + expect(styles.findIndex((e) => e.includes('--background-color: var(--igx-overlay-background-color, hsl(from var(--ig-gray-500) h s l/0.54));'))) .toBeGreaterThan(-1); - expect(styles.findIndex( - (e) => e.includes('background: var(--background-color);'))) + expect(styles.findIndex((e) => e.includes('background: var(--background-color);'))) .toBeGreaterThan(-1); fixture.componentInstance.overlay.detachAll(); @@ -3284,10 +3266,10 @@ describe('igxOverlay', () => { button.addEventListener('click', _handler); - spyOn(button, 'click').and.callThrough(); - spyOn(button, 'onclick').and.callThrough(); - spyOn(overlay, 'show').and.callThrough(); - spyOn(overlay, 'hide').and.callThrough(); + vi.spyOn(button, 'click'); + vi.spyOn(button, 'onclick'); + vi.spyOn(overlay, 'show'); + vi.spyOn(overlay, 'hide'); overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); tick(); @@ -3506,27 +3488,26 @@ describe('igxOverlay', () => { })); // 4. Css - it('Should use component initial container\'s properties when is with 100% width and show in overlay element', - fakeAsync(() => { - const fixture = TestBed.createComponent(WidthTestOverlayComponent); - fixture.detectChanges(); - expect(fixture.componentInstance.customComponent).toBeDefined(); - expect(fixture.componentInstance.customComponent.nativeElement.style.width).toEqual('100%'); - expect(fixture.componentInstance.customComponent.nativeElement.getBoundingClientRect().width).toEqual(420); - expect(fixture.componentInstance.customComponent.nativeElement.style.height).toEqual('100%'); - expect(fixture.componentInstance.customComponent.nativeElement.getBoundingClientRect().height).toEqual(280); - fixture.componentInstance.buttonElement.nativeElement.click(); - tick(); - const componentElement = (fixture.nativeElement as HTMLElement) - .parentElement.getElementsByClassName('customList')[0] as HTMLElement; - expect(componentElement).toBeDefined(); - expect(componentElement.style.width).toEqual('100%'); - expect(componentElement.getBoundingClientRect().width).toEqual(420); - // content element has no height, so the shown element will calculate its own height by itself - // expect(overlayChild.style.height).toEqual('100%'); - // expect(overlayChild.getBoundingClientRect().height).toEqual(280); - fixture.componentInstance.overlay.detachAll(); - })); + it('Should use component initial container\'s properties when is with 100% width and show in overlay element', fakeAsync(() => { + const fixture = TestBed.createComponent(WidthTestOverlayComponent); + fixture.detectChanges(); + expect(fixture.componentInstance.customComponent).toBeDefined(); + expect(fixture.componentInstance.customComponent.nativeElement.style.width).toEqual('100%'); + expect(fixture.componentInstance.customComponent.nativeElement.getBoundingClientRect().width).toEqual(420); + expect(fixture.componentInstance.customComponent.nativeElement.style.height).toEqual('100%'); + expect(fixture.componentInstance.customComponent.nativeElement.getBoundingClientRect().height).toEqual(280); + fixture.componentInstance.buttonElement.nativeElement.click(); + tick(); + const componentElement = (fixture.nativeElement as HTMLElement) + .parentElement.getElementsByClassName('customList')[0] as HTMLElement; + expect(componentElement).toBeDefined(); + expect(componentElement.style.width).toEqual('100%'); + expect(componentElement.getBoundingClientRect().width).toEqual(420); + // content element has no height, so the shown element will calculate its own height by itself + // expect(overlayChild.style.height).toEqual('100%'); + // expect(overlayChild.getBoundingClientRect().height).toEqual(280); + fixture.componentInstance.overlay.detachAll(); + })); }); describe('Integration tests - Scroll Strategies: ', () => { @@ -3554,8 +3535,7 @@ describe('igxOverlay', () => { fixture.detectChanges(); const dummy = document.createElement('div'); - dummy.setAttribute('style', - 'width:60px; height:60px; color:green; position: absolute; top: 3000px; left: 3000px;'); + dummy.setAttribute('style', 'width:60px; height:60px; color:green; position: absolute; top: 3000px; left: 3000px;'); document.body.appendChild(dummy); const target = fixture.componentInstance.buttonElement.nativeElement; @@ -4027,134 +4007,131 @@ describe('igxOverlay', () => { })); it(`Should not close the shown component when none scroll strategy is passed. - (example: expanded DropDown stays expanded during a scrolling attempt.)`, - fakeAsync(async () => { - TestBed.overrideComponent(EmptyPageComponent, { - set: { - styles: [`button { + (example: expanded DropDown stays expanded during a scrolling attempt.)`, fakeAsync(async () => { + TestBed.overrideComponent(EmptyPageComponent, { + set: { + styles: [`button { position: absolute; top: 120%; left: 120%; } `] - } - }); - await TestBed.compileComponents(); - const fixture = TestBed.createComponent(EmptyPageComponent); - fixture.detectChanges(); - - const overlaySettings: OverlaySettings = { - modal: false, - }; - const overlay = fixture.componentInstance.overlay; - - overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); - tick(); - const componentElement = (fixture.debugElement.nativeElement as HTMLElement) - .parentElement.getElementsByTagName('test-simple-dynamic-component')[0]; - const componentRect = componentElement.getBoundingClientRect(); - - document.documentElement.scrollTop = 40; - document.documentElement.scrollLeft = 30; - document.documentElement.dispatchEvent(new Event('scroll')); - tick(); - - expect(componentRect).toEqual(componentElement.getBoundingClientRect()); - expect(document.documentElement.scrollTop).toEqual(40); - expect(document.documentElement.scrollLeft).toEqual(30); - expect(document.getElementsByClassName(CLASS_OVERLAY_WRAPPER).length).toEqual(1); - - overlay.detachAll(); - })); + } + }); + await TestBed.compileComponents(); + const fixture = TestBed.createComponent(EmptyPageComponent); + fixture.detectChanges(); + + const overlaySettings: OverlaySettings = { + modal: false, + }; + const overlay = fixture.componentInstance.overlay; + + overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); + tick(); + const componentElement = (fixture.debugElement.nativeElement as HTMLElement) + .parentElement.getElementsByTagName('test-simple-dynamic-component')[0]; + const componentRect = componentElement.getBoundingClientRect(); + + document.documentElement.scrollTop = 40; + document.documentElement.scrollLeft = 30; + document.documentElement.dispatchEvent(new Event('scroll')); + tick(); + + expect(componentRect).toEqual(componentElement.getBoundingClientRect()); + expect(document.documentElement.scrollTop).toEqual(40); + expect(document.documentElement.scrollLeft).toEqual(30); + expect(document.getElementsByClassName(CLASS_OVERLAY_WRAPPER).length).toEqual(1); + + overlay.detachAll(); + })); // 2.2 Scroll Strategy - Closing. (Uses a tolerance and closes an expanded component upon scrolling if the tolerance is exceeded.) // (example: DropDown or Dialog component collapse/closes after scrolling 10px.) - it('Should scroll until the set threshold is exceeded, and closing scroll strategy is used.', - fakeAsync(async () => { - TestBed.overrideComponent(EmptyPageComponent, { - set: { - styles: [ - 'button { position: absolute; top: 100%; left: 90%; }' - ] - } - }); - await TestBed.compileComponents(); - const fixture = TestBed.createComponent(EmptyPageComponent); - fixture.detectChanges(); - - const scrollTolerance = 10; - const scrollStrategy = new CloseScrollStrategy(); - const overlay = fixture.componentInstance.overlay; - const overlaySettings: OverlaySettings = { - positionStrategy: new GlobalPositionStrategy(), - scrollStrategy, - modal: false, - }; - - overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); - tick(); - - document.documentElement.scrollTop = scrollTolerance; - document.documentElement.dispatchEvent(new Event('scroll')); - tick(); - - let wrapperElement = (fixture.nativeElement as HTMLElement) - .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER)[0] as HTMLElement; - expect(wrapperElement).toBeDefined(); - expect(wrapperElement.style.visibility).toEqual(''); - expect(document.documentElement.scrollTop).toEqual(scrollTolerance); - - document.documentElement.scrollTop += scrollTolerance * 2; - document.documentElement.dispatchEvent(new Event('scroll')); - tick(); - - wrapperElement = (fixture.nativeElement as HTMLElement) - .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER)[0] as HTMLElement; - expect(wrapperElement).toBeDefined(); - expect(wrapperElement.style.visibility).toEqual('hidden'); - - overlay.detachAll() - })); + it('Should scroll until the set threshold is exceeded, and closing scroll strategy is used.', fakeAsync(async () => { + TestBed.overrideComponent(EmptyPageComponent, { + set: { + styles: [ + 'button { position: absolute; top: 100%; left: 90%; }' + ] + } + }); + await TestBed.compileComponents(); + const fixture = TestBed.createComponent(EmptyPageComponent); + fixture.detectChanges(); + + const scrollTolerance = 10; + const scrollStrategy = new CloseScrollStrategy(); + const overlay = fixture.componentInstance.overlay; + const overlaySettings: OverlaySettings = { + positionStrategy: new GlobalPositionStrategy(), + scrollStrategy, + modal: false, + }; + + overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); + tick(); + + document.documentElement.scrollTop = scrollTolerance; + document.documentElement.dispatchEvent(new Event('scroll')); + tick(); + + let wrapperElement = (fixture.nativeElement as HTMLElement) + .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER)[0] as HTMLElement; + expect(wrapperElement).toBeDefined(); + expect(wrapperElement.style.visibility).toEqual(''); + expect(document.documentElement.scrollTop).toEqual(scrollTolerance); + + document.documentElement.scrollTop += scrollTolerance * 2; + document.documentElement.dispatchEvent(new Event('scroll')); + tick(); + + wrapperElement = (fixture.nativeElement as HTMLElement) + .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER)[0] as HTMLElement; + expect(wrapperElement).toBeDefined(); + expect(wrapperElement.style.visibility).toEqual('hidden'); + + overlay.detachAll(); + })); it(`Should not change the shown component shown state until it exceeds the scrolling tolerance set, - and closing scroll strategy is used.`, - fakeAsync(async () => { - TestBed.overrideComponent(EmptyPageComponent, { - set: { - styles: [ - 'button { position: absolute; top: 200%; left: 90%; }' - ] - } - }); - await TestBed.compileComponents(); - const fixture = TestBed.createComponent(EmptyPageComponent); - fixture.detectChanges(); - - const scrollTolerance = 10; - const scrollStrategy = new CloseScrollStrategy(); - const overlay = fixture.componentInstance.overlay; - const overlaySettings: OverlaySettings = { - positionStrategy: new GlobalPositionStrategy(), - scrollStrategy, - closeOnOutsideClick: false, - modal: false, - }; - - overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); - tick(); - expect(document.documentElement.scrollTop).toEqual(0); - - document.documentElement.scrollTop += scrollTolerance; - document.documentElement.dispatchEvent(new Event('scroll')); - tick(); - expect(document.documentElement.scrollTop).toEqual(scrollTolerance); - const wrapperElement = (fixture.nativeElement as HTMLElement) - .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER)[0] as HTMLElement; - expect(wrapperElement).toBeDefined(); - expect(wrapperElement.style.visibility).toEqual(''); - fixture.destroy(); - - overlay.detachAll(); - })); + and closing scroll strategy is used.`, fakeAsync(async () => { + TestBed.overrideComponent(EmptyPageComponent, { + set: { + styles: [ + 'button { position: absolute; top: 200%; left: 90%; }' + ] + } + }); + await TestBed.compileComponents(); + const fixture = TestBed.createComponent(EmptyPageComponent); + fixture.detectChanges(); + + const scrollTolerance = 10; + const scrollStrategy = new CloseScrollStrategy(); + const overlay = fixture.componentInstance.overlay; + const overlaySettings: OverlaySettings = { + positionStrategy: new GlobalPositionStrategy(), + scrollStrategy, + closeOnOutsideClick: false, + modal: false, + }; + + overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); + tick(); + expect(document.documentElement.scrollTop).toEqual(0); + + document.documentElement.scrollTop += scrollTolerance; + document.documentElement.dispatchEvent(new Event('scroll')); + tick(); + expect(document.documentElement.scrollTop).toEqual(scrollTolerance); + const wrapperElement = (fixture.nativeElement as HTMLElement) + .parentElement.getElementsByClassName(CLASS_OVERLAY_WRAPPER)[0] as HTMLElement; + expect(wrapperElement).toBeDefined(); + expect(wrapperElement.style.visibility).toEqual(''); + fixture.destroy(); + + overlay.detachAll(); + })); it(`Should close the shown component shown when it exceeds the scrolling threshold set, and closing scroll strategy is used. (an expanded DropDown, Menu, DatePicker, etc.collapses).`, fakeAsync(async () => { @@ -4204,45 +4181,44 @@ describe('igxOverlay', () => { })); // 2.3 Scroll Strategy - NoOp. - it('Should retain the component static and only the background scrolls, when scrolling and noOP scroll strategy is used.', - fakeAsync(async () => { - TestBed.overrideComponent(EmptyPageComponent, { - set: { - styles: [ - 'button { position: absolute; top: 200%; left: 90%; }' - ] - } - }); - await TestBed.compileComponents(); - const fixture = TestBed.createComponent(EmptyPageComponent); - fixture.detectChanges(); - - const scrollTolerance = 10; - const scrollStrategy = new NoOpScrollStrategy(); - const overlay = fixture.componentInstance.overlay; - const overlaySettings: OverlaySettings = { - modal: false, - scrollStrategy, - positionStrategy: new GlobalPositionStrategy() - }; - - overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); - tick(); - expect(document.getElementsByClassName(CLASS_OVERLAY_WRAPPER).length).toEqual(1); - - const componentElement = (fixture.debugElement.nativeElement as HTMLElement) - .parentElement.getElementsByTagName('test-simple-dynamic-component')[0]; - const componentRect = componentElement.getBoundingClientRect(); - - document.documentElement.scrollTop += scrollTolerance; - document.documentElement.dispatchEvent(new Event('scroll')); - tick(); - expect(document.documentElement.scrollTop).toEqual(scrollTolerance); - expect(document.getElementsByClassName(CLASS_OVERLAY_WRAPPER).length).toEqual(1); - expect(componentElement.getBoundingClientRect()).toEqual(componentRect); - - overlay.detachAll(); - })); + it('Should retain the component static and only the background scrolls, when scrolling and noOP scroll strategy is used.', fakeAsync(async () => { + TestBed.overrideComponent(EmptyPageComponent, { + set: { + styles: [ + 'button { position: absolute; top: 200%; left: 90%; }' + ] + } + }); + await TestBed.compileComponents(); + const fixture = TestBed.createComponent(EmptyPageComponent); + fixture.detectChanges(); + + const scrollTolerance = 10; + const scrollStrategy = new NoOpScrollStrategy(); + const overlay = fixture.componentInstance.overlay; + const overlaySettings: OverlaySettings = { + modal: false, + scrollStrategy, + positionStrategy: new GlobalPositionStrategy() + }; + + overlay.show(overlay.attach(SimpleDynamicComponent, overlaySettings)); + tick(); + expect(document.getElementsByClassName(CLASS_OVERLAY_WRAPPER).length).toEqual(1); + + const componentElement = (fixture.debugElement.nativeElement as HTMLElement) + .parentElement.getElementsByTagName('test-simple-dynamic-component')[0]; + const componentRect = componentElement.getBoundingClientRect(); + + document.documentElement.scrollTop += scrollTolerance; + document.documentElement.dispatchEvent(new Event('scroll')); + tick(); + expect(document.documentElement.scrollTop).toEqual(scrollTolerance); + expect(document.getElementsByClassName(CLASS_OVERLAY_WRAPPER).length).toEqual(1); + expect(componentElement.getBoundingClientRect()).toEqual(componentRect); + + overlay.detachAll(); + })); // 2.4. Scroll Strategy - Absolute. it('Should scroll everything except component when scrolling and absolute scroll strategy is used.', fakeAsync(async () => { @@ -4306,8 +4282,8 @@ describe('igxOverlay', () => { positionStrategy: new GlobalPositionStrategy() }; - spyOn(overlay, 'show').and.callThrough(); - spyOn(overlay.closing, 'emit'); + vi.spyOn(overlay, 'show'); + vi.spyOn(overlay.closing, 'emit'); const firstCallId = overlay.attach(SimpleDynamicComponent, overlaySettings); overlay.show(firstCallId); @@ -4320,9 +4296,9 @@ describe('igxOverlay', () => { expect(overlay.closing.emit).toHaveBeenCalledTimes(1); expect(overlay.closing.emit).toHaveBeenCalledWith({ id: firstCallId, - componentRef: jasmine.any(ComponentRef) as any, + componentRef: expect.any(ComponentRef) as any, cancel: false, - event: jasmine.any(Event) as any + event: expect.any(Event) as any }); overlay.detachAll(); @@ -4341,9 +4317,9 @@ describe('igxOverlay', () => { excludeFromOutsideClick: [divElement] }; - spyOn(overlay, 'show').and.callThrough(); - spyOn(overlay.closing, 'emit'); - spyOn(overlay.closed, 'emit'); + vi.spyOn(overlay, 'show'); + vi.spyOn(overlay.closing, 'emit'); + vi.spyOn(overlay.closed, 'emit'); let callId = overlay.attach(SimpleDynamicComponent, overlaySettings); overlay.show(callId); @@ -4362,11 +4338,11 @@ describe('igxOverlay', () => { expect(overlay.closed.emit).toHaveBeenCalledTimes(1); expect(overlay.closing.emit) .toHaveBeenCalledWith({ - id: callId, - componentRef: jasmine.any(ComponentRef) as any, - cancel: false, - event: undefined - }); + id: callId, + componentRef: expect.any(ComponentRef) as any, + cancel: false, + event: undefined + }); overlay.detachAll(); overlaySettings.excludeFromOutsideClick = []; @@ -4383,11 +4359,11 @@ describe('igxOverlay', () => { expect(overlay.closed.emit).toHaveBeenCalledTimes(2); expect(overlay.closing.emit) .toHaveBeenCalledWith({ - id: callId, - componentRef: jasmine.any(ComponentRef) as any, - cancel: false, - event: jasmine.any(Event) as any - }); + id: callId, + componentRef: expect.any(ComponentRef) as any, + cancel: false, + event: expect.any(Event) as any + }); overlay.detachAll(); })); @@ -4558,8 +4534,10 @@ export class EmptyPageComponent { public viewContainerRef = inject(ViewContainerRef); public injector = inject(Injector); - @ViewChild('button', { static: true }) public buttonElement: ElementRef; - @ViewChild('div', { static: true }) public divElement: ElementRef; + @ViewChild('button', { static: true }) + public buttonElement: ElementRef; + @ViewChild('div', { static: true }) + public divElement: ElementRef; public click() { this.overlay.show(this.overlay.attach(SimpleDynamicComponent)); @@ -4577,8 +4555,10 @@ export class EmptyPageComponent { export class EmptyPageInShadowDomComponent { public overlay = inject(IgxOverlayService); - @ViewChild('button', { static: true }) public buttonElement: ElementRef; - @ViewChild('outlet', { static: true }) public outletElement: ElementRef; + @ViewChild('button', { static: true }) + public buttonElement: ElementRef; + @ViewChild('outlet', { static: true }) + public outletElement: ElementRef; } @Component({ @@ -4598,7 +4578,8 @@ export class EmptyPageInShadowDomComponent { export class DownRightButtonComponent { public overlay = inject(IgxOverlayService); - @ViewChild('button', { static: true }) public buttonElement: ElementRef; + @ViewChild('button', { static: true }) + public buttonElement: ElementRef; public positionStrategy: IPositionStrategy; @@ -4639,7 +4620,8 @@ export class TopLeftOffsetComponent { public overlay = inject(IgxOverlayService); - @ViewChild('button', { static: true }) public buttonElement: ElementRef; + @ViewChild('button', { static: true }) + public buttonElement: ElementRef; public click() { this.overlay.show(this.overlay.attach(SimpleDynamicComponent)); @@ -4697,8 +4679,10 @@ export class WidthTestOverlayComponent { public elementRef = inject(ElementRef); - @ViewChild('button', { static: true }) public buttonElement: ElementRef; - @ViewChild('myCustomComponent', { static: true }) public customComponent: ElementRef; + @ViewChild('button', { static: true }) + public buttonElement: ElementRef; + @ViewChild('myCustomComponent', { static: true }) + public customComponent: ElementRef; public overlaySettings: OverlaySettings = {}; public click(_event: any) { @@ -4766,7 +4750,8 @@ export class ScrollableComponent { export class FlexContainerComponent { public overlay = inject(IgxOverlayService); - @ViewChild('button', { static: true }) public buttonElement: ElementRef; + @ViewChild('button', { static: true }) + public buttonElement: ElementRef; public overlaySettings: OverlaySettings = {}; public click() { diff --git a/projects/igniteui-angular/core/src/services/transaction/igx-transaction.spec.ts b/projects/igniteui-angular/core/src/services/transaction/igx-transaction.spec.ts index 1b2ac16f921..bdf19bc3680 100644 --- a/projects/igniteui-angular/core/src/services/transaction/igx-transaction.spec.ts +++ b/projects/igniteui-angular/core/src/services/transaction/igx-transaction.spec.ts @@ -2,6 +2,7 @@ import { IgxTransactionService } from './igx-transaction'; import { Transaction, TransactionType, HierarchicalTransaction } from './transaction'; import { SampleTestData } from '../../../../test-utils/sample-test-data.spec'; import { IgxHierarchicalTransactionService } from './igx-hierarchical-transaction'; +import { describe, it, expect, vi } from 'vitest'; describe('IgxTransaction', () => { describe('IgxTransaction UNIT tests', () => { @@ -158,7 +159,7 @@ describe('IgxTransaction', () => { it('Should add ADD type transaction - all feasible paths, and correctly fires onStateUpdate', () => { const trans = new IgxTransactionService(); - spyOn(trans.onStateUpdate, 'emit').and.callThrough(); + vi.spyOn(trans.onStateUpdate, 'emit'); expect(trans).toBeDefined(); // ADD @@ -663,7 +664,7 @@ describe('IgxTransaction', () => { it('Should add pending transaction and push it to transaction log, and correctly fires onStateUpdate', () => { const trans = new IgxTransactionService(); - spyOn(trans.onStateUpdate, 'emit').and.callThrough(); + vi.spyOn(trans.onStateUpdate, 'emit'); expect(trans).toBeDefined(); const recordRef = { key: 'Key1', value1: 1, value2: 2, value3: 3 }; @@ -691,18 +692,17 @@ describe('IgxTransaction', () => { expect(trans.getState('Key1')).toBeTruthy(); expect(trans.getAggregatedValue('Key1', true)).toEqual({ key: 'Key1', value1: 10, value2: 2, value3: 30 }); - expect(trans.getTransactionLog() as any).toEqual( - [ - { - id: 'Key1', - newValue: { key: 'Key1', value1: 10 }, - type: 'update' - }, { - id: 'Key1', - newValue: { key: 'Key1', value3: 30 }, - type: 'update' - } - ]); + expect(trans.getTransactionLog() as any).toEqual([ + { + id: 'Key1', + newValue: { key: 'Key1', value1: 10 }, + type: 'update' + }, { + id: 'Key1', + newValue: { key: 'Key1', value3: 30 }, + type: 'update' + } + ]); expect(trans.getState(updateTransaction.id)).toEqual({ value: { value1: 10, value3: 30 }, recordRef, @@ -713,7 +713,7 @@ describe('IgxTransaction', () => { it('Should not add pending transaction and push it to transaction log, and correctly fires onStateUpdate', () => { const trans = new IgxTransactionService(); - spyOn(trans.onStateUpdate, 'emit').and.callThrough(); + vi.spyOn(trans.onStateUpdate, 'emit'); expect(trans).toBeDefined(); const recordRef = { key: 'Key1', value1: 1, value2: 2, value3: 3 }; @@ -935,7 +935,7 @@ describe('IgxTransaction', () => { }; transaction.add(deleteTransaction, data[0].Employees[2].Employees[0]); - updateTransaction.newValue = { Name: 'New Name'}; + updateTransaction.newValue = { Name: 'New Name' }; transaction.add(updateTransaction, data[0].Employees[0]); expect(data.find(i => i.ID === 999)).toBeUndefined(); @@ -1034,7 +1034,7 @@ describe('IgxTransaction', () => { it('Should emit onStateUpdate once when commiting a hierarchical transaction', () => { const data = SampleTestData.employeeTreeData(); const transaction = new IgxHierarchicalTransactionService(); - spyOn(transaction.onStateUpdate, 'emit').and.callThrough(); + vi.spyOn(transaction.onStateUpdate, 'emit'); expect(transaction).toBeDefined(); const updateTransaction: HierarchicalTransaction = { diff --git a/projects/igniteui-angular/date-picker/src/date-picker/calendar-container/calendar-container.component.spec.ts b/projects/igniteui-angular/date-picker/src/date-picker/calendar-container/calendar-container.component.spec.ts index 7b20f510581..537dca67166 100644 --- a/projects/igniteui-angular/date-picker/src/date-picker/calendar-container/calendar-container.component.spec.ts +++ b/projects/igniteui-angular/date-picker/src/date-picker/calendar-container/calendar-container.component.spec.ts @@ -6,6 +6,7 @@ import { IgxCalendarComponent } from '../../../../calendar/src/public_api'; import { IgxButtonDirective } from '../../../../directives/src/directives/button/button.directive'; import { IgxPickerActionsDirective } from '../../../../core/src/date-common/picker-icons.common'; import { IgxCalendarContainerComponent } from './calendar-container.component'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('Calendar Container', () => { @@ -31,12 +32,12 @@ describe('Calendar Container', () => { }); it('should render default actions', () => { - spyOn(container.calendarClose, 'emit'); - spyOn(container.todaySelection, 'emit'); + vi.spyOn(container.calendarClose, 'emit'); + vi.spyOn(container.todaySelection, 'emit'); container.closeButtonLabel = 'cancel'; fixture.detectChanges(); let buttons = fixture.debugElement.queryAll(By.directive(IgxButtonDirective)); - expect(buttons).toHaveSize(1); + expect(buttons).toHaveLength(1); expect(buttons[0].nativeElement.innerText).toEqual('cancel'); buttons[0].triggerEventHandler('click', {}); expect(container.calendarClose.emit).toHaveBeenCalledTimes(1); @@ -44,20 +45,20 @@ describe('Calendar Container', () => { container.todayButtonLabel = 'ok'; fixture.detectChanges(); buttons = fixture.debugElement.queryAll(By.directive(IgxButtonDirective)); - expect(buttons).toHaveSize(2); + expect(buttons).toHaveLength(2); expect(buttons[1].nativeElement.innerText).toEqual('ok'); buttons[1].triggerEventHandler('click', {}); expect(container.todaySelection.emit).toHaveBeenCalledTimes(1); }); it('should render default toggle and clear icons', () => { - spyOn(fixture.componentInstance, 'doWork'); + vi.spyOn(fixture.componentInstance, 'doWork'); container.pickerActions = fixture.componentInstance.actions; fixture.detectChanges(); const calendar = fixture.debugElement.query(By.directive(IgxCalendarComponent)).componentInstance; const buttons = fixture.debugElement.queryAll(By.directive(IgxButtonDirective)); - expect(buttons).toHaveSize(1); + expect(buttons).toHaveLength(1); expect(buttons[0].nativeElement.innerText).toEqual('action'); buttons[0].triggerEventHandler('click', {}); expect(fixture.componentInstance.doWork).toHaveBeenCalledWith(calendar); @@ -75,7 +76,9 @@ describe('Calendar Container', () => { imports: [IgxCalendarContainerComponent, IgxPickerActionsDirective, IgxButtonDirective] }) export class IgxDatePickerTestComponent { - @ViewChild(IgxCalendarContainerComponent) public container: IgxCalendarContainerComponent; - @ViewChild(IgxPickerActionsDirective) public actions: IgxPickerActionsDirective; - public doWork = (_calendar: any) => {}; + @ViewChild(IgxCalendarContainerComponent) + public container: IgxCalendarContainerComponent; + @ViewChild(IgxPickerActionsDirective) + public actions: IgxPickerActionsDirective; + public doWork = (_calendar: any) => { }; } diff --git a/projects/igniteui-angular/date-picker/src/date-picker/date-picker.component.spec.ts b/projects/igniteui-angular/date-picker/src/date-picker/date-picker.component.spec.ts index 7e1d88dfaa4..06bafaaedf1 100644 --- a/projects/igniteui-angular/date-picker/src/date-picker/date-picker.component.spec.ts +++ b/projects/igniteui-angular/date-picker/src/date-picker/date-picker.component.spec.ts @@ -2,20 +2,11 @@ import { ComponentFixture, fakeAsync, flush, TestBed, tick, waitForAsync } from import { UntypedFormControl, UntypedFormGroup, FormsModule, NgForm, ReactiveFormsModule, Validators } from '@angular/forms'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { UIInteractions } from '../../../test-utils/ui-interactions.spec'; -import { - IgxHintDirective, IgxInputGroupComponent, IgxInputState, IgxLabelDirective, IgxPrefixDirective, IgxSuffixDirective -} from '../../../input-group/src/public_api'; +import { IgxHintDirective, IgxInputGroupComponent, IgxInputState, IgxLabelDirective, IgxPrefixDirective, IgxSuffixDirective } from '../../../input-group/src/public_api'; import { IFormattingViews, IgxCalendarComponent, IgxCalendarHeaderTemplateDirective, IgxCalendarHeaderTitleTemplateDirective } from '../../../calendar/src/public_api'; import { IgxCalendarContainerComponent } from './calendar-container/calendar-container.component'; import { IgxDatePickerComponent } from './date-picker.component'; -import { - IgxOverlayOutletDirective, - IgxOverlayService, - OverlayCancelableEventArgs, OverlayClosingEventArgs, OverlayEventArgs, OverlaySettings, - WEEKDAYS, - BaseFormatter, - I18N_FORMATTER -} from 'igniteui-angular/core'; +import { IgxOverlayOutletDirective, IgxOverlayService, OverlayCancelableEventArgs, OverlayClosingEventArgs, OverlayEventArgs, OverlaySettings, WEEKDAYS, BaseFormatter, I18N_FORMATTER } from 'igniteui-angular/core'; import { ChangeDetectorRef, Component, DebugElement, ElementRef, EventEmitter, Injector, QueryList, Renderer2, ViewChild } from '@angular/core'; import { By } from '@angular/platform-browser'; import { PickerCalendarOrientation, PickerHeaderOrientation, PickerInteractionMode } from '../../../core/src/date-common/types'; @@ -27,6 +18,7 @@ import { registerLocaleData } from "@angular/common"; import localeES from "@angular/common/locales/es"; import localeBg from "@angular/common/locales/bg"; import { IgxDateTimeEditorDirective } from '../../../directives/src/directives/date-time-editor/date-time-editor.directive'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; const CSS_CLASS_DATE_PICKER = 'igx-date-picker'; @@ -65,10 +57,10 @@ describe('IgxDatePicker', () => { it('Should render default toggle and clear icons', () => { const inputGroup = fixture.debugElement.query(By.directive(IgxInputGroupComponent)); const prefix = inputGroup.queryAll(By.directive(IgxPrefixDirective)); - expect(prefix).toHaveSize(1); + expect(prefix).toHaveLength(1); expect(prefix[0].nativeElement.innerText).toEqual(DATE_PICKER_TOGGLE_ICON); const suffix = inputGroup.queryAll(By.directive(IgxSuffixDirective)); - expect(suffix).toHaveSize(1); + expect(suffix).toHaveLength(1); expect(suffix[0].nativeElement.innerText).toEqual(DATE_PICKER_CLEAR_ICON); }); @@ -80,9 +72,9 @@ describe('IgxDatePicker', () => { tick(); fixture.detectChanges(); - expect(datePicker['_calendar'].hasHeader).toBeFalse(); + expect(datePicker['_calendar'].hasHeader).toBe(false); const calendarHeader = fixture.debugElement.query(By.css(CSS_CLASS_CALENDAR_HEADER)); - expect(calendarHeader).toBeFalsy('Calendar header should not be present'); + expect(calendarHeader, 'Calendar header should not be present').toBeFalsy(); })); it('should set calendar orientation property', fakeAsync(() => { @@ -93,7 +85,7 @@ describe('IgxDatePicker', () => { fixture.detectChanges(); expect(datePicker['_calendar'].orientation).toEqual(PickerCalendarOrientation.Horizontal.toString()); - expect(datePicker['_calendar'].wrapper.nativeElement).not.toHaveClass(CSS_CLASS_CALENDAR_WRAPPER_VERTICAL); + expect(datePicker['_calendar'].wrapper.nativeElement.classList.contains(CSS_CLASS_CALENDAR_WRAPPER_VERTICAL)).toBe(false); datePicker.close(); tick(); fixture.detectChanges(); @@ -104,7 +96,7 @@ describe('IgxDatePicker', () => { fixture.detectChanges(); expect(datePicker['_calendar'].orientation).toEqual(PickerCalendarOrientation.Vertical.toString()); - expect(datePicker['_calendar'].wrapper.nativeElement).toHaveClass(CSS_CLASS_CALENDAR_WRAPPER_VERTICAL); + expect(datePicker['_calendar'].wrapper.nativeElement.classList.contains(CSS_CLASS_CALENDAR_WRAPPER_VERTICAL)).toBe(true); })); it('should initialize activeDate with current date, when not set', fakeAsync(() => { @@ -195,10 +187,10 @@ describe('IgxDatePicker', () => { })); it('should be able to cancel opening/closing', fakeAsync(() => { - spyOn(datePicker.opening, 'emit').and.callThrough(); - spyOn(datePicker.opened, 'emit').and.callThrough(); - spyOn(datePicker.closing, 'emit').and.callThrough(); - spyOn(datePicker.closed, 'emit').and.callThrough(); + vi.spyOn(datePicker.opening, 'emit'); + vi.spyOn(datePicker.opened, 'emit'); + vi.spyOn(datePicker.closing, 'emit'); + vi.spyOn(datePicker.closed, 'emit'); const openingSub = datePicker.opening.subscribe((event) => event.cancel = true); @@ -244,12 +236,12 @@ describe('IgxDatePicker', () => { })); it('should toggle the calendar with ALT + DOWN/UP ARROW key', fakeAsync(() => { - spyOn(datePicker.opening, 'emit').and.callThrough(); - spyOn(datePicker.opened, 'emit').and.callThrough(); - spyOn(datePicker.closing, 'emit').and.callThrough(); - spyOn(datePicker.closed, 'emit').and.callThrough(); + vi.spyOn(datePicker.opening, 'emit'); + vi.spyOn(datePicker.opened, 'emit'); + vi.spyOn(datePicker.closing, 'emit'); + vi.spyOn(datePicker.closed, 'emit'); expect(datePicker.collapsed).toBeTruthy(); - expect(datePicker.isFocused).toBeFalse(); + expect(datePicker.isFocused).toBe(false); const picker = fixture.debugElement.query(By.css(CSS_CLASS_DATE_PICKER)); UIInteractions.triggerEventHandlerKeyDown('ArrowDown', picker, true); @@ -262,10 +254,8 @@ describe('IgxDatePicker', () => { expect(datePicker.opened.emit).toHaveBeenCalledTimes(1); const calendarWrapper = fixture.debugElement.query(By.css('.igx-calendar__wrapper')).nativeElement; - expect(calendarWrapper.contains(document.activeElement)) - .withContext('focus should move to calendar for KB nav') - .toBeTrue(); - expect(datePicker.isFocused).toBeTrue(); + expect(calendarWrapper.contains(document.activeElement), 'focus should move to calendar for KB nav').toBe(true); + expect(datePicker.isFocused).toBe(true); UIInteractions.triggerKeyDownEvtUponElem('ArrowUp', calendarWrapper, true, true); tick(350); @@ -273,15 +263,13 @@ describe('IgxDatePicker', () => { expect(datePicker.collapsed).toBeTruthy(); expect(datePicker.closing.emit).toHaveBeenCalledTimes(1); expect(datePicker.closed.emit).toHaveBeenCalledTimes(1); - expect(inputGroup.nativeElement.contains(document.activeElement)) - .withContext('focus should return to the picker input') - .toBeTrue(); - expect(datePicker.isFocused).toBeTrue(); + expect(inputGroup.nativeElement.contains(document.activeElement), 'focus should return to the picker input').toBe(true); + expect(datePicker.isFocused).toBe(true); })); it('should open the calendar with SPACE key', fakeAsync(() => { - spyOn(datePicker.opening, 'emit').and.callThrough(); - spyOn(datePicker.opened, 'emit').and.callThrough(); + vi.spyOn(datePicker.opening, 'emit'); + vi.spyOn(datePicker.opened, 'emit'); expect(datePicker.collapsed).toBeTruthy(); const picker = fixture.debugElement.query(By.css(CSS_CLASS_DATE_PICKER)); @@ -300,8 +288,8 @@ describe('IgxDatePicker', () => { it('should close the calendar with ESC', fakeAsync(() => { datePicker.mode = 'dropdown'; - spyOn(datePicker.closing, 'emit').and.callThrough(); - spyOn(datePicker.closed, 'emit').and.callThrough(); + vi.spyOn(datePicker.closing, 'emit'); + vi.spyOn(datePicker.closed, 'emit'); expect(datePicker.collapsed).toBeTruthy(); datePicker.open(); @@ -310,10 +298,8 @@ describe('IgxDatePicker', () => { expect(datePicker.collapsed).toBeFalsy(); const calendarWrapper = fixture.debugElement.query(By.css('.igx-calendar__wrapper')).nativeElement; - expect(calendarWrapper.contains(document.activeElement)) - .withContext('focus should move to calendar for KB nav') - .toBeTrue(); - expect(datePicker.isFocused).toBeTrue(); + expect(calendarWrapper.contains(document.activeElement), 'focus should move to calendar for KB nav').toBe(true); + expect(datePicker.isFocused).toBe(true); UIInteractions.triggerKeyDownEvtUponElem('Escape', calendarWrapper, true); @@ -323,10 +309,8 @@ describe('IgxDatePicker', () => { expect(datePicker.collapsed).toBeTruthy(); expect(datePicker.closing.emit).toHaveBeenCalledTimes(1); expect(datePicker.closed.emit).toHaveBeenCalledTimes(1); - expect(inputGroup.nativeElement.contains(document.activeElement)) - .withContext('focus should return to the picker input') - .toBeTrue(); - expect(datePicker.isFocused).toBeTrue(); + expect(inputGroup.nativeElement.contains(document.activeElement), 'focus should return to the picker input').toBe(true); + expect(datePicker.isFocused).toBe(true); })); it('should update the calendar selection on typing', fakeAsync(() => { @@ -383,9 +367,7 @@ describe('IgxDatePicker', () => { }); describe('NgControl integration', () => { - let fixture: ComponentFixture; + let fixture: ComponentFixture; let datePicker: IgxDatePickerComponent; beforeEach(fakeAsync(() => { @@ -509,7 +491,7 @@ describe('IgxDatePicker', () => { fixture.detectChanges(); expect(datePicker.locale).toEqual(locale); - expect(datePicker.weekStart).toEqual(WEEKDAYS.SUNDAY) + expect(datePicker.weekStart).toEqual(WEEKDAYS.SUNDAY); datePicker.locale = 'frrr'; @@ -578,18 +560,18 @@ describe('IgxDatePicker', () => { const inputGroup = fixture.debugElement.query(By.directive(IgxInputGroupComponent)); const label = inputGroup.queryAll(By.directive(IgxLabelDirective)); - expect(label).toHaveSize(1); + expect(label).toHaveLength(1); expect(label[0].nativeElement.innerText).toEqual('Label'); const hint = inputGroup.queryAll(By.directive(IgxHintDirective)); - expect(hint).toHaveSize(1); + expect(hint).toHaveLength(1); expect(hint[0].nativeElement.innerText).toEqual('Hint'); const prefix = inputGroup.queryAll(By.directive(IgxPrefixDirective)); - expect(prefix).toHaveSize(2); + expect(prefix).toHaveLength(2); expect(prefix[0].nativeElement.innerText).toEqual(DATE_PICKER_TOGGLE_ICON); expect(prefix[1].nativeElement.innerText).toEqual('Prefix'); const suffix = inputGroup.queryAll(By.directive(IgxSuffixDirective)); - expect(suffix).toHaveSize(2); + expect(suffix).toHaveLength(2); expect(suffix[0].nativeElement.innerText).toEqual(DATE_PICKER_CLEAR_ICON); expect(suffix[1].nativeElement.innerText).toEqual('Suffix'); }); @@ -602,11 +584,11 @@ describe('IgxDatePicker', () => { const inputGroup = fixture.debugElement.query(By.directive(IgxInputGroupComponent)); const prefix = inputGroup.queryAll(By.directive(IgxPrefixDirective)); - expect(prefix).toHaveSize(2); + expect(prefix).toHaveLength(2); expect(prefix[0].nativeElement.innerText).toEqual('CustomToggle'); expect(prefix[1].nativeElement.innerText).toEqual('Prefix'); const suffix = inputGroup.queryAll(By.directive(IgxSuffixDirective)); - expect(suffix).toHaveSize(2); + expect(suffix).toHaveLength(2); expect(suffix[0].nativeElement.innerText).toEqual('CustomClear'); expect(suffix[1].nativeElement.innerText).toEqual('Suffix'); }); @@ -617,8 +599,8 @@ describe('IgxDatePicker', () => { fixture.componentInstance.showCustomClear = true; fixture.componentInstance.showCustomToggle = true; fixture.detectChanges(); - spyOn(datePicker, 'open'); - spyOn(datePicker, 'clear'); + vi.spyOn(datePicker, 'open'); + vi.spyOn(datePicker, 'clear'); const inputGroup = fixture.debugElement.query(By.directive(IgxInputGroupComponent)); const toggleElem = inputGroup.query(By.directive(IgxPickerToggleComponent)); @@ -626,9 +608,11 @@ describe('IgxDatePicker', () => { let toggle = fixture.componentInstance.customToggle; let clear = fixture.componentInstance.customClear; - expect(toggle.clicked.observers).toHaveSize(1); - expect(clear.clicked.observers).toHaveSize(1); - const event = jasmine.createSpyObj('event', ['stopPropagation']); + expect(toggle.clicked.observers).toHaveLength(1); + expect(clear.clicked.observers).toHaveLength(1); + const event = { + stopPropagation: vi.fn().mockName("event.stopPropagation") + }; toggleElem.triggerEventHandler('click', event); expect(datePicker.open).toHaveBeenCalledTimes(1); clearElem.triggerEventHandler('click', event); @@ -637,12 +621,12 @@ describe('IgxDatePicker', () => { // hide fixture.componentInstance.showCustomToggle = false; fixture.detectChanges(); - expect(toggle.clicked.observers).toHaveSize(0); - expect(clear.clicked.observers).toHaveSize(1); + expect(toggle.clicked.observers).toHaveLength(0); + expect(clear.clicked.observers).toHaveLength(1); fixture.componentInstance.showCustomClear = false; fixture.detectChanges(); - expect(toggle.clicked.observers).toHaveSize(0); - expect(clear.clicked.observers).toHaveSize(0); + expect(toggle.clicked.observers).toHaveLength(0); + expect(clear.clicked.observers).toHaveLength(0); // show again fixture.componentInstance.showCustomClear = true; @@ -650,12 +634,12 @@ describe('IgxDatePicker', () => { fixture.detectChanges(); toggle = fixture.componentInstance.customToggle; clear = fixture.componentInstance.customClear; - expect(toggle.clicked.observers).toHaveSize(1); - expect(clear.clicked.observers).toHaveSize(1); + expect(toggle.clicked.observers).toHaveLength(1); + expect(clear.clicked.observers).toHaveLength(1); datePicker.ngOnDestroy(); - expect(toggle.clicked.observers).toHaveSize(0); - expect(clear.clicked.observers).toHaveSize(0); + expect(toggle.clicked.observers).toHaveLength(0); + expect(clear.clicked.observers).toHaveLength(0); }); }); @@ -663,40 +647,40 @@ describe('IgxDatePicker', () => { let fixture: ComponentFixture; beforeEach(fakeAsync(() => { - TestBed.configureTestingModule({ - imports: [IgxDatePickerWithTemplatesComponent] - }).compileComponents(); + TestBed.configureTestingModule({ + imports: [IgxDatePickerWithTemplatesComponent] + }).compileComponents(); - fixture = TestBed.createComponent(IgxDatePickerWithTemplatesComponent); - fixture.detectChanges(); + fixture = TestBed.createComponent(IgxDatePickerWithTemplatesComponent); + fixture.detectChanges(); })); it('Should use the custom template for header title', fakeAsync(() => { - const testDate = new Date(2024, 10, 11); - fixture.componentInstance.datePicker.value = testDate; - fixture.componentInstance.datePicker.open(); - tick(); - fixture.detectChanges(); - - const headerTitleElement = fixture.debugElement.query(By.css('.igx-calendar__header-year')); - expect(headerTitleElement).toBeTruthy('Header title element should be present'); - if (headerTitleElement) { - expect(headerTitleElement.nativeElement.textContent.trim()).toBe('2024'); - } + const testDate = new Date(2024, 10, 11); + fixture.componentInstance.datePicker.value = testDate; + fixture.componentInstance.datePicker.open(); + tick(); + fixture.detectChanges(); + + const headerTitleElement = fixture.debugElement.query(By.css('.igx-calendar__header-year')); + expect(headerTitleElement, 'Header title element should be present').toBeTruthy(); + if (headerTitleElement) { + expect(headerTitleElement.nativeElement.textContent.trim()).toBe('2024'); + } })); it('Should use the custom template for header', fakeAsync(() => { - const testDate = new Date(2024, 10, 11); - fixture.componentInstance.datePicker.value = testDate; - fixture.componentInstance.datePicker.open(); - tick(); - fixture.detectChanges(); - - const headerElement = fixture.debugElement.query(By.css('.igx-calendar__header-date')); - expect(headerElement).toBeTruthy('Header element should be present'); - if (headerElement) { - expect(headerElement.nativeElement.textContent.trim()).toBe('Nov'); - } + const testDate = new Date(2024, 10, 11); + fixture.componentInstance.datePicker.value = testDate; + fixture.componentInstance.datePicker.open(); + tick(); + fixture.detectChanges(); + + const headerElement = fixture.debugElement.query(By.css('.igx-calendar__header-date')); + expect(headerElement, 'Header element should be present').toBeTruthy(); + if (headerElement) { + expect(headerElement.nativeElement.textContent.trim()).toBe('Nov'); + } })); }); @@ -729,9 +713,7 @@ describe('IgxDatePicker', () => { const today = new Date(new Date().setHours(0, 0, 0, 0)).getTime().toString(); const wrapper = fixture.debugElement.query(By.css('.igx-calendar__wrapper')).nativeElement; expect(wrapper.getAttribute('aria-activedescendant')).toEqual(today); - expect(wrapper.contains(document.activeElement)) - .withContext('focus should move to calendar for KB nav') - .toBeTrue(); + expect(wrapper.contains(document.activeElement), 'focus should move to calendar for KB nav').toBe(true); })); it('should focus today\'s date when an invalid date is selected', fakeAsync(() => { @@ -748,9 +730,7 @@ describe('IgxDatePicker', () => { const today = new Date(new Date().setHours(0, 0, 0, 0)).getTime().toString(); const wrapper = fixture.debugElement.query(By.css('.igx-calendar__wrapper')).nativeElement; expect(wrapper.getAttribute('aria-activedescendant')).toEqual(today); - expect(wrapper.contains(document.activeElement)) - .withContext('focus should move to calendar for KB nav') - .toBeTrue(); + expect(wrapper.contains(document.activeElement), 'focus should move to calendar for KB nav').toBe(true); })); it('should return focus to date picker input after calendar click select', fakeAsync(() => { @@ -769,9 +749,7 @@ describe('IgxDatePicker', () => { tick(); fixture.detectChanges(); expect(datePicker.value).toEqual(today); - expect(inputGroup.contains(document.activeElement)) - .withContext('focus should return to the picker input') - .toBeTrue(); + expect(inputGroup.contains(document.activeElement), 'focus should return to the picker input').toBe(true); })); }); @@ -850,14 +828,21 @@ describe('IgxDatePicker', () => { const mockOverlayId = '1'; const today = new Date(); const elementRef = { - nativeElement: jasmine.createSpyObj('mockElement', ['blur', 'click', 'focus']) + nativeElement: { + blur: vi.fn().mockName("mockElement.blur"), + click: vi.fn().mockName("mockElement.click"), + focus: vi.fn().mockName("mockElement.focus") + } }; let mockNgControl: any; let mockControlInstance: any; let renderer2: Renderer2; beforeEach(() => { - renderer2 = jasmine.createSpyObj('Renderer2', ['setAttribute'], [{}, 'aria-labelledby', 'test-label-id-1']); + // TODO: vitest-migration: Cannot transform jasmine.createSpyObj with a dynamic property map. Please migrate this manually. See: https://vitest.dev/api/vi.html#vi-fn + renderer2 = { + setAttribute: vi.fn().mockName("Renderer2.setAttribute") + }; mockControlInstance = { _touched: false, get touched() { @@ -902,12 +887,14 @@ describe('IgxDatePicker', () => { }, valid: true }; - mockInjector = jasmine.createSpyObj('Injector', { - get: mockNgControl - }); + mockInjector = { + get: vi.fn().mockName("Injector.get").mockReturnValue(mockNgControl) + }; - mockCdr = jasmine.createSpyObj('ChangeDetectorRef', ['detectChanges']); - mockCalendar = { selected: new EventEmitter(), selectDate: () => {} }; + mockCdr = { + detectChanges: vi.fn().mockName("ChangeDetectorRef.detectChanges") + }; + mockCalendar = { selected: new EventEmitter(), selectDate: () => { } }; const mockComponentInstance = { calendar: mockCalendar, todaySelection: new EventEmitter(), @@ -968,8 +955,13 @@ describe('IgxDatePicker', () => { this._isRequired = val; }, element: { - nativeElement: jasmine.createSpyObj('mockElement', - ['focus', 'blur', 'click', 'addEventListener', 'removeEventListener']) + nativeElement: { + focus: vi.fn().mockName("mockElement.focus"), + blur: vi.fn().mockName("mockElement.blur"), + click: vi.fn().mockName("mockElement.click"), + addEventListener: vi.fn().mockName("mockElement.addEventListener"), + removeEventListener: vi.fn().mockName("mockElement.removeEventListener") + } } } as any; mockInputDirective = { @@ -1086,7 +1078,7 @@ describe('IgxDatePicker', () => { expect(datePicker.disabled).toBeTruthy(); datePicker.disabled = false; const mockDisabledDates: DateRangeDescriptor[] = [{ type: DateRangeType.Weekdays }, - { type: DateRangeType.Before, dateRange: [today] }]; + { type: DateRangeType.Before, dateRange: [today] }]; datePicker.disabledDates = mockDisabledDates; expect(datePicker.disabledDates).toEqual(mockDisabledDates); datePicker.displayFormat = 'MM/yy/DD'; @@ -1153,15 +1145,18 @@ describe('IgxDatePicker', () => { expect(datePicker.maxValue).toEqual('12/12/1998'); datePicker.outlet = null; expect(datePicker.outlet).toEqual(null); - const mockEl: ElementRef = jasmine.createSpyObj('mockEl', ['nativeElement']); + const mockEl: ElementRef = { + nativeElement: vi.fn().mockName("mockEl.nativeElement") + }; datePicker.outlet = mockEl; expect(datePicker.outlet).toEqual(mockEl); - const mockOverlayDirective: IgxOverlayOutletDirective = - jasmine.createSpyObj('mockEl', ['nativeElement']); + const mockOverlayDirective: IgxOverlayOutletDirective = { + nativeElement: vi.fn().mockName("mockEl.nativeElement") + }; datePicker.outlet = mockOverlayDirective; expect(datePicker.outlet).toEqual(mockOverlayDirective); const specialDates: DateRangeDescriptor[] = [{ type: DateRangeType.Weekdays }, - { type: DateRangeType.Before, dateRange: [today] }]; + { type: DateRangeType.Before, dateRange: [today] }]; datePicker.specialDates = specialDates; expect(datePicker.specialDates).toEqual(specialDates); const spinDeltaSettings = { date: Infinity, month: Infinity }; @@ -1185,7 +1180,7 @@ describe('IgxDatePicker', () => { expect(datePicker.placeholder).toEqual('Buenos dias, muchachos'); datePicker.readOnly = true; expect(datePicker.readOnly).toEqual(true); - spyOn(datePicker.valueChange, 'emit').and.callThrough(); + vi.spyOn(datePicker.valueChange, 'emit'); datePicker.value = today; expect(datePicker.value).toEqual(today); expect(mockDateEditor.value).toEqual(today); @@ -1210,8 +1205,8 @@ describe('IgxDatePicker', () => { }); it('Should properly set date w/ `selectToday` methods', () => { - spyOn(datePicker, 'select'); - spyOn(datePicker, 'close'); + vi.spyOn(datePicker, 'select'); + vi.spyOn(datePicker, 'close'); const now = new Date(); now.setHours(0); now.setMinutes(0); @@ -1223,8 +1218,8 @@ describe('IgxDatePicker', () => { }); it('Should call underlying dateEditor decrement and increment methods', () => { - mockDateEditor.decrement = jasmine.createSpy(); - mockDateEditor.increment = jasmine.createSpy(); + mockDateEditor.decrement = vi.fn(); + mockDateEditor.increment = vi.fn(); datePicker.decrement(); expect(mockDateEditor.decrement).toHaveBeenCalledWith(undefined, undefined); const mockDatePart = {} as DatePart; @@ -1245,54 +1240,43 @@ describe('IgxDatePicker', () => { }); it('Should call underlying overlay `open` and `attach` methods with proper settings', () => { - spyOn(overlay, 'attach').and.returnValue(mockOverlayId); - spyOn(overlay, 'detach'); - spyOn(overlay, 'show'); - spyOn(overlay, 'hide'); - - const baseDialogSettings: OverlaySettings = Object.assign( - {}, - (datePicker as any)._dialogOverlaySettings - ); - const baseDropdownSettings: OverlaySettings = Object.assign( - {}, - (datePicker as any)._dropDownOverlaySettings, - { - target: mockInputGroup.element.nativeElement - } - ); + vi.spyOn(overlay, 'attach').mockReturnValue(mockOverlayId); + vi.spyOn(overlay, 'detach'); + vi.spyOn(overlay, 'show'); + vi.spyOn(overlay, 'hide'); + + const baseDialogSettings: OverlaySettings = Object.assign({}, (datePicker as any)._dialogOverlaySettings); + const baseDropdownSettings: OverlaySettings = Object.assign({}, (datePicker as any)._dropDownOverlaySettings, { + target: mockInputGroup.element.nativeElement + }); - const collapsedSpy = spyOnProperty(datePicker, 'collapsed', 'get'); - collapsedSpy.and.returnValue(false); + const collapsedSpy = vi.spyOn(datePicker, 'collapsed', 'get'); + collapsedSpy.mockReturnValue(false); datePicker.disabled = false; datePicker.open(); expect(overlay.attach).not.toHaveBeenCalled(); - collapsedSpy.and.returnValue(true); + collapsedSpy.mockReturnValue(true); datePicker.disabled = true; datePicker.open(); expect(overlay.attach).not.toHaveBeenCalled(); - collapsedSpy.and.returnValue(false); + collapsedSpy.mockReturnValue(false); datePicker.open(); expect(overlay.attach).not.toHaveBeenCalled(); - collapsedSpy.and.returnValue(true); + collapsedSpy.mockReturnValue(true); datePicker.disabled = false; - const isDropdownSpy = spyOnProperty(datePicker, 'isDropdown', 'get'); - isDropdownSpy.and.returnValue(false); + const isDropdownSpy = vi.spyOn(datePicker, 'isDropdown', 'get'); + isDropdownSpy.mockReturnValue(false); datePicker.open(); expect(overlay.attach).toHaveBeenCalledWith(IgxCalendarContainerComponent, viewsContainerRef, baseDialogSettings); expect(overlay.show).toHaveBeenCalledWith(mockOverlayId); - isDropdownSpy.and.returnValue(true); + isDropdownSpy.mockReturnValue(true); datePicker.open(); expect(overlay.attach).toHaveBeenCalledWith(IgxCalendarContainerComponent, viewsContainerRef, baseDropdownSettings); expect(overlay.show).toHaveBeenCalledWith(mockOverlayId); const mockOutlet = {} as any; datePicker.outlet = mockOutlet; datePicker.open(); - expect(overlay.attach).toHaveBeenCalledWith( - IgxCalendarContainerComponent, - viewsContainerRef, - Object.assign({}, baseDropdownSettings, { outlet: mockOutlet }), - ); + expect(overlay.attach).toHaveBeenCalledWith(IgxCalendarContainerComponent, viewsContainerRef, Object.assign({}, baseDropdownSettings, { outlet: mockOutlet })); expect(overlay.show).toHaveBeenCalledWith(mockOverlayId); let mockSettings: OverlaySettings = { closeOnEscape: true, @@ -1301,26 +1285,18 @@ describe('IgxDatePicker', () => { }; datePicker.outlet = null; datePicker.open(mockSettings); - expect(overlay.attach).toHaveBeenCalledWith( - IgxCalendarContainerComponent, - viewsContainerRef, - Object.assign({}, baseDropdownSettings, mockSettings), - ); + expect(overlay.attach).toHaveBeenCalledWith(IgxCalendarContainerComponent, viewsContainerRef, Object.assign({}, baseDropdownSettings, mockSettings)); expect(overlay.show).toHaveBeenCalledWith(mockOverlayId); - isDropdownSpy.and.returnValue(false); + isDropdownSpy.mockReturnValue(false); mockSettings = { closeOnEscape: false, closeOnOutsideClick: false, modal: false }; datePicker.open(mockSettings); - expect(overlay.attach).toHaveBeenCalledWith( - IgxCalendarContainerComponent, - viewsContainerRef, - Object.assign({}, baseDialogSettings, mockSettings), - ); + expect(overlay.attach).toHaveBeenCalledWith(IgxCalendarContainerComponent, viewsContainerRef, Object.assign({}, baseDialogSettings, mockSettings)); expect(overlay.show).toHaveBeenCalledWith(mockOverlayId); - isDropdownSpy.and.returnValue(true); + isDropdownSpy.mockReturnValue(true); datePicker.overlaySettings = { modal: false }; @@ -1328,30 +1304,26 @@ describe('IgxDatePicker', () => { modal: true }; datePicker.open(mockSettings); - expect(overlay.attach).toHaveBeenCalledWith( - IgxCalendarContainerComponent, - viewsContainerRef, - Object.assign({}, baseDropdownSettings, { modal: true }), - ); + expect(overlay.attach).toHaveBeenCalledWith(IgxCalendarContainerComponent, viewsContainerRef, Object.assign({}, baseDropdownSettings, { modal: true })); }); it('Should call underlying overlay `close` and `detach` methods with proper settings', () => { - spyOn(overlay, 'attach').and.returnValue(mockOverlayId); - spyOn(overlay, 'detach'); - spyOn(overlay, 'show'); - spyOn(overlay, 'hide'); + vi.spyOn(overlay, 'attach').mockReturnValue(mockOverlayId); + vi.spyOn(overlay, 'detach'); + vi.spyOn(overlay, 'show'); + vi.spyOn(overlay, 'hide'); // init subscriptions datePicker.ngAfterViewInit(); // assign overlayId - const collapsedSpy = spyOnProperty(datePicker, 'collapsed', 'get'); - collapsedSpy.and.returnValue(true); + const collapsedSpy = vi.spyOn(datePicker, 'collapsed', 'get'); + collapsedSpy.mockReturnValue(true); datePicker.open(); datePicker.close(); expect(overlay.hide).not.toHaveBeenCalled(); expect(overlay.detach).not.toHaveBeenCalled(); - collapsedSpy.and.returnValue(false); + collapsedSpy.mockReturnValue(false); datePicker.close(); expect(overlay.hide).toHaveBeenCalled(); expect(overlay.hide).toHaveBeenCalledWith(mockOverlayId); @@ -1364,23 +1336,24 @@ describe('IgxDatePicker', () => { expect(renderer2.setAttribute).not.toHaveBeenCalled(); datePicker.ngAfterViewChecked(); expect(renderer2.setAttribute).not.toHaveBeenCalled(); - (datePicker as any).labelDirective = jasmine.createSpyObj('mockLabel', ['any'], { + (datePicker as any).labelDirective = { + any: vi.fn().mockName("mockLabel.any"), id: 'mock-id' - }); + }; datePicker.ngAfterViewChecked(); expect(renderer2.setAttribute).toHaveBeenCalledWith(mockInputDirective.nativeElement, 'aria-labelledby', 'mock-id'); }); it('Should properly handle click on editor provider', () => { datePicker.ngAfterViewInit(); - spyOn(datePicker, 'open'); + vi.spyOn(datePicker, 'open'); expect(datePicker.open).not.toHaveBeenCalled(); expect(datePicker.getEditElement()).toEqual(mockInputDirective.nativeElement); expect(datePicker.isDropdown).toBeTruthy(); datePicker.getEditElement().dispatchEvent('click' as any); // does not call open when in DD mode expect(datePicker.open).toHaveBeenCalledTimes(0); - spyOnProperty(datePicker, 'isDropdown', 'get').and.returnValue(false); + vi.spyOn(datePicker, 'isDropdown', 'get').mockReturnValue(false); datePicker.getEditElement().dispatchEvent('click' as any); expect(datePicker.open).toHaveBeenCalledTimes(1); }); @@ -1390,20 +1363,20 @@ describe('IgxDatePicker', () => { datePicker.ngAfterViewInit(); datePicker.open(); - expect(datePicker.collapsed).toBeFalse(); + expect(datePicker.collapsed).toBe(false); datePicker.close(); - expect(datePicker.collapsed).toBeTrue(); + expect(datePicker.collapsed).toBe(true); datePicker.toggle(); - expect(datePicker.collapsed).toBeFalse(); + expect(datePicker.collapsed).toBe(false); datePicker.toggle(); - expect(datePicker.collapsed).toBeTrue(); + expect(datePicker.collapsed).toBe(true); }); it('should update the picker\'s value with the select method', () => { - spyOn(datePicker.valueChange, 'emit'); + vi.spyOn(datePicker.valueChange, 'emit'); (datePicker as any).dateTimeEditor = { value: null, clear: () => { } }; datePicker.value = new Date(); @@ -1415,7 +1388,7 @@ describe('IgxDatePicker', () => { }); it('should clear the picker\'s value with the clear method', () => { - spyOn(datePicker.valueChange, 'emit'); + vi.spyOn(datePicker.valueChange, 'emit'); datePicker.value = today; @@ -1430,8 +1403,8 @@ describe('IgxDatePicker', () => { //#region Events it('should properly emit open/close events', () => { - spyOn(datePicker.opened, 'emit'); - spyOn(datePicker.closed, 'emit'); + vi.spyOn(datePicker.opened, 'emit'); + vi.spyOn(datePicker.closed, 'emit'); datePicker.ngAfterViewInit(); @@ -1443,8 +1416,8 @@ describe('IgxDatePicker', () => { }); it('should properly emit opening/closing events', () => { - spyOn(datePicker.opening, 'emit'); - spyOn(datePicker.closing, 'emit'); + vi.spyOn(datePicker.opening, 'emit'); + vi.spyOn(datePicker.closing, 'emit'); datePicker.ngAfterViewInit(); @@ -1456,7 +1429,7 @@ describe('IgxDatePicker', () => { }); it('should emit valueChange when the value changes', () => { - spyOn(datePicker.valueChange, 'emit'); + vi.spyOn(datePicker.valueChange, 'emit'); datePicker.ngAfterViewInit(); @@ -1467,10 +1440,10 @@ describe('IgxDatePicker', () => { }); it('should emit validationFailed if a value outside of a given range was provided', () => { - spyOn(datePicker.validationFailed, 'emit'); + vi.spyOn(datePicker.validationFailed, 'emit'); const validDate = new Date(2012, 5, 7); const invalidDate = new Date(2012, 6, 1); - spyOnProperty(mockDateEditor, 'value', 'set').and.callFake((val: Date) => { + vi.spyOn(mockDateEditor, 'value', 'set').mockImplementation((val: Date) => { if (val === invalidDate) { mockDateEditor.validationFailed.emit({ oldValue: validDate }); return; @@ -1486,13 +1459,12 @@ describe('IgxDatePicker', () => { datePicker.value = validDate; expect(datePicker.validationFailed.emit).not.toHaveBeenCalled(); datePicker.value = invalidDate; - expect(datePicker.validationFailed.emit).toHaveBeenCalledWith( - { owner: datePicker, prevValue: validDate, currentValue: invalidDate }); + expect(datePicker.validationFailed.emit).toHaveBeenCalledWith({ owner: datePicker, prevValue: validDate, currentValue: invalidDate }); }); it('Should change own value if value of underlying dateEditor changes', () => { const validDate = new Date(2012, 5, 7); - spyOn(datePicker.valueChange, 'emit'); + vi.spyOn(datePicker.valueChange, 'emit'); datePicker.ngAfterViewInit(); expect(datePicker.value).not.toEqual(validDate); @@ -1508,12 +1480,12 @@ describe('IgxDatePicker', () => { it(`Should initialize and subscribe to underlying calendar's selected event and call proper methods`, () => { datePicker.mode = PickerInteractionMode.Dialog; - spyOn(overlay, 'show'); + vi.spyOn(overlay, 'show'); // assign overlay id datePicker.open(); datePicker.ngAfterViewInit(); overlay.opening.emit(mockOverlayEventArgs); - spyOn(datePicker, 'close'); + vi.spyOn(datePicker, 'close'); expect(datePicker.close).not.toHaveBeenCalled(); // calendar instance is initialized properly expect(mockCalendar.hasHeader).toEqual(!datePicker.isDropdown); @@ -1530,21 +1502,26 @@ describe('IgxDatePicker', () => { // check how calendar.selected is handler const init = DateTimeUtil.parseIsoDate; - const mockDate1 = jasmine.createSpyObj( - 'date', - ['setHours', 'setMinutes', 'setSeconds', 'setMilliseconds'] - ); - const mockDate2 = jasmine.createSpyObj( - 'date', - ['getHours', 'getMinutes', 'getSeconds', 'getMilliseconds', 'getTime'] - ); - mockDate2.getHours.and.returnValue(999); - mockDate2.getMinutes.and.returnValue(999); - mockDate2.getSeconds.and.returnValue(999); - mockDate2.getMilliseconds.and.returnValue(999); - mockDate2.getTime.and.returnValue(999); - const parseIsoDate = spyOn(DateTimeUtil, 'parseIsoDate'); - parseIsoDate.and.callFake((val: string) => { + const mockDate1 = { + setHours: vi.fn().mockName("date.setHours"), + setMinutes: vi.fn().mockName("date.setMinutes"), + setSeconds: vi.fn().mockName("date.setSeconds"), + setMilliseconds: vi.fn().mockName("date.setMilliseconds") + }; + const mockDate2 = { + getHours: vi.fn().mockName("date.getHours"), + getMinutes: vi.fn().mockName("date.getMinutes"), + getSeconds: vi.fn().mockName("date.getSeconds"), + getMilliseconds: vi.fn().mockName("date.getMilliseconds"), + getTime: vi.fn().mockName("date.getTime") + }; + mockDate2.getHours.mockReturnValue(999); + mockDate2.getMinutes.mockReturnValue(999); + mockDate2.getSeconds.mockReturnValue(999); + mockDate2.getMilliseconds.mockReturnValue(999); + mockDate2.getTime.mockReturnValue(999); + const parseIsoDate = vi.spyOn(DateTimeUtil, 'parseIsoDate'); + parseIsoDate.mockImplementation((val: string) => { if (val === undefined || mockDate1) { return mockDate2; } else { @@ -1574,7 +1551,7 @@ describe('IgxDatePicker', () => { expect(mockDate1.setMilliseconds).not.toHaveBeenCalledWith(999); expect(datePicker.close).toHaveBeenCalled(); - parseIsoDate.and.callFake(init); + parseIsoDate.mockImplementation(init); const mockMinValue = new Date('02/02/2002'); const mockMaxValue = new Date('03/03/2003'); @@ -1586,7 +1563,7 @@ describe('IgxDatePicker', () => { return defaultCheck(value); } }; - spyOn(DateTimeUtil, 'isValidDate').and.callFake(mockCheck); + vi.spyOn(DateTimeUtil, 'isValidDate').mockImplementation(mockCheck); expect(datePicker.disabledDates).toEqual(null); expect(datePicker.minValue).toBeUndefined(); expect(datePicker.maxValue).toBeUndefined(); @@ -1633,7 +1610,7 @@ describe('IgxDatePicker', () => { { type: DateRangeType.Before, dateRange: [mockMinValue] }, { type: DateRangeType.After, dateRange: [mockMaxValue] } ]); - mockDate2.getTime.and.returnValue(Infinity); + mockDate2.getTime.mockReturnValue(Infinity); mockCalendar.disabledDates = []; datePicker.minValue = mockMinValue; datePicker.maxValue = mockMaxValue; @@ -1688,7 +1665,8 @@ describe('IgxDatePicker', () => { imports: [IgxDatePickerComponent] }) export class IgxDatePickerTestComponent { - @ViewChild(IgxDatePickerComponent) public datePicker: IgxDatePickerComponent; + @ViewChild(IgxDatePickerComponent) + public datePicker: IgxDatePickerComponent; public mode: PickerInteractionMode = PickerInteractionMode.DropDown; public date = new Date(2021, 24, 2, 11, 45, 0); public minValue; @@ -1702,7 +1680,8 @@ export class IgxDatePickerTestComponent { imports: [IgxDatePickerComponent, FormsModule] }) export class IgxDatePickerNgModelComponent { - @ViewChild(IgxDatePickerComponent) public datePicker: IgxDatePickerComponent; + @ViewChild(IgxDatePickerComponent) + public datePicker: IgxDatePickerComponent; public mode: PickerInteractionMode = PickerInteractionMode.DropDown; public date = new Date(2021, 24, 2, 11, 45, 0); public minValue; @@ -1719,7 +1698,8 @@ export class IgxDatePickerNgModelComponent { imports: [IgxDatePickerComponent, IgxLabelDirective] }) export class IgxDatePickerTestKbrdComponent { - @ViewChild(IgxDatePickerComponent) public datePicker: IgxDatePickerComponent; + @ViewChild(IgxDatePickerComponent) + public datePicker: IgxDatePickerComponent; public mode: PickerInteractionMode = PickerInteractionMode.DropDown; public date = new Date(2021, 24, 2, 11, 45, 0); } @@ -1741,9 +1721,12 @@ export class IgxDatePickerTestKbrdComponent { imports: [IgxDatePickerComponent, IgxPickerToggleComponent, IgxPrefixDirective, IgxPickerClearComponent, IgxLabelDirective, IgxSuffixDirective, IgxHintDirective] }) export class IgxDatePickerWithProjectionsComponent { - @ViewChild(IgxDatePickerComponent) public datePicker: IgxDatePickerComponent; - @ViewChild(IgxPickerToggleComponent) public customToggle: IgxPickerToggleComponent; - @ViewChild(IgxPickerClearComponent) public customClear: IgxPickerClearComponent; + @ViewChild(IgxDatePickerComponent) + public datePicker: IgxDatePickerComponent; + @ViewChild(IgxPickerToggleComponent) + public customToggle: IgxPickerToggleComponent; + @ViewChild(IgxPickerClearComponent) + public customClear: IgxPickerClearComponent; public mode: PickerInteractionMode = PickerInteractionMode.DropDown; public showCustomToggle = false; public showCustomClear = false; @@ -1758,7 +1741,8 @@ export class IgxDatePickerWithProjectionsComponent { imports: [IgxDatePickerComponent, IgxCalendarHeaderTemplateDirective, IgxCalendarHeaderTitleTemplateDirective] }) export class IgxDatePickerWithTemplatesComponent { - @ViewChild(IgxDatePickerComponent) public datePicker: IgxDatePickerComponent; + @ViewChild(IgxDatePickerComponent) + public datePicker: IgxDatePickerComponent; public mode: PickerInteractionMode = PickerInteractionMode.Dialog; } diff --git a/projects/igniteui-angular/date-picker/src/date-range-picker/date-range-picker.component.spec.ts b/projects/igniteui-angular/date-picker/src/date-range-picker/date-range-picker.component.spec.ts index 594ee6a7a9b..70b814750c4 100644 --- a/projects/igniteui-angular/date-picker/src/date-range-picker/date-range-picker.component.spec.ts +++ b/projects/igniteui-angular/date-picker/src/date-range-picker/date-range-picker.component.spec.ts @@ -25,6 +25,7 @@ import localeBg from "@angular/common/locales/bg"; import { CalendarDay, BaseFormatter } from 'igniteui-angular/core'; import { IgxCalendarComponent, IgxCalendarHeaderTemplateDirective, IgxCalendarHeaderTitleTemplateDirective, IgxCalendarSubheaderTemplateDirective } from 'igniteui-angular/calendar'; import { KeyboardNavigationService } from 'igniteui-angular/calendar/src/calendar/calendar.services'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; // The number of milliseconds in one day const DEBOUNCE_TIME = 16; @@ -32,8 +33,8 @@ const DEFAULT_ICON_TEXT = 'date_range'; const CLEAR_ICON_TEXT = 'clear'; const DEFAULT_FORMAT_OPTIONS = { day: 'numeric', month: 'numeric', year: 'numeric' }; const CSS_CLASS_INPUT_BUNDLE = '.igx-input-group__bundle'; -const CSS_CLASS_INPUT_START = '.igx-input-group__bundle-start' -const CSS_CLASS_INPUT_END = '.igx-input-group__bundle-end' +const CSS_CLASS_INPUT_START = '.igx-input-group__bundle-start'; +const CSS_CLASS_INPUT_END = '.igx-input-group__bundle-end'; const CSS_CLASS_INPUT = '.igx-input-group__input'; const CSS_CLASS_INPUT_GROUP_REQUIRED = 'igx-input-group--required'; const CSS_CLASS_INPUT_GROUP_INVALID = 'igx-input-group--invalid'; @@ -59,10 +60,11 @@ describe('IgxDateRangePicker', () => { let fixture: any; let dateRange: IgxDateRangePickerComponent; const elementRef = { nativeElement: null }; - const mockNgControl = jasmine.createSpyObj('NgControl', - ['registerOnChangeCb', - 'registerOnTouchedCb', - 'registerOnValidatorChangeCb']); + const mockNgControl = { + registerOnChangeCb: vi.fn().mockName("NgControl.registerOnChangeCb"), + registerOnTouchedCb: vi.fn().mockName("NgControl.registerOnTouchedCb"), + registerOnValidatorChangeCb: vi.fn().mockName("NgControl.registerOnValidatorChangeCb") + }; /* eslint-disable @typescript-eslint/no-unused-vars */ beforeEach(() => { mockElement = { @@ -79,9 +81,9 @@ describe('IgxDateRangePicker', () => { mockElement.parent = mockElement; mockElement.parentElement = mockElement; - mockCdr = jasmine.createSpyObj('ChangeDetectorRef', { - detectChanges: () => { } - }); + mockCdr = { + detectChanges: vi.fn().mockName("ChangeDetectorRef.detectChanges").mockReturnValue(() => { }) + }; TestBed.configureTestingModule({ imports: [NoopAnimationsModule], @@ -102,7 +104,7 @@ describe('IgxDateRangePicker', () => { mockCalendar = TestBed.inject(IgxCalendarComponent); mockDaysView = { - focusActiveDate: jasmine.createSpy() + focusActiveDate: vi.fn() } as any; mockCalendar.daysView = mockDaysView; }); @@ -128,7 +130,7 @@ describe('IgxDateRangePicker', () => { it('should emit valueChange on selection', () => { //const dateRange = TestBed.inject(IgxDateRangePickerComponent); // dateRange.calendar = calendar; - spyOn(dateRange.valueChange, 'emit'); + vi.spyOn(dateRange.valueChange, 'emit'); let startDate = new Date(2017, 4, 5); const endDate = new Date(2017, 11, 22); @@ -155,7 +157,7 @@ describe('IgxDateRangePicker', () => { // init dateRange.registerOnChange(mockNgControl.registerOnChangeCb); dateRange.registerOnTouched(mockNgControl.registerOnTouchedCb); - spyOn(dateRange as any, 'handleSelection').and.callThrough(); + vi.spyOn(dateRange as any, 'handleSelection'); // writeValue expect(dateRange.value).toBeUndefined(); @@ -211,7 +213,7 @@ describe('IgxDateRangePicker', () => { it('should disable calendar dates when min and/or max values as dates are provided', () => { dateRange.ngOnInit(); - spyOnProperty((dateRange as any), 'calendar').and.returnValue(mockCalendar); + vi.spyOn((dateRange as any), 'calendar').mockReturnValue(mockCalendar); dateRange.minValue = new Date(2000, 10, 1); dateRange.maxValue = new Date(2000, 10, 20); @@ -226,11 +228,11 @@ describe('IgxDateRangePicker', () => { it('should disable calendar dates when min and/or max values as strings are provided', fakeAsync(() => { dateRange.ngOnInit(); - spyOnProperty((dateRange as any), 'calendar').and.returnValue(mockCalendar); + vi.spyOn((dateRange as any), 'calendar').mockReturnValue(mockCalendar); dateRange.minValue = '2000/10/1'; dateRange.maxValue = '2000/10/30'; - spyOn((dateRange as any).calendar, 'deselectDate').and.returnValue(null); + vi.spyOn((dateRange as any).calendar, 'deselectDate').mockReturnValue(null); (dateRange as any).updateCalendar(); expect((dateRange as any).calendar.disabledDates.length).toEqual(2); expect((dateRange as any).calendar.disabledDates[0].type).toEqual(DateRangeType.Before); @@ -244,15 +246,15 @@ describe('IgxDateRangePicker', () => { dateRange.registerOnChange(mockNgControl.registerOnChangeCb); dateRange.registerOnValidatorChange(mockNgControl.registerOnValidatorChangeCb); - mockNgControl.registerOnValidatorChangeCb.calls.reset(); - spyOnProperty((dateRange as any), 'calendar').and.returnValue(mockCalendar); + mockNgControl.registerOnValidatorChangeCb.mockClear(); + vi.spyOn((dateRange as any), 'calendar').mockReturnValue(mockCalendar); const start = new Date(new Date().getFullYear(), new Date().getMonth(), 10); const end = new Date(new Date().getFullYear(), new Date().getMonth(), 18); const disabledDates = [{ - type: DateRangeType.Between, dateRange: [ start, end ] - }]; + type: DateRangeType.Between, dateRange: [start, end] + }]; dateRange.disabledDates = disabledDates; expect(mockNgControl.registerOnValidatorChangeCb).toHaveBeenCalledTimes(1); @@ -283,17 +285,14 @@ describe('IgxDateRangePicker', () => { let calendar: DebugElement | Element; let calendarDays: DebugElement[] | HTMLCollectionOf; - const selectDateRangeFromCalendar = (sDate: Date, eDate: Date, autoClose:boolean = true) => { + const selectDateRangeFromCalendar = (sDate: Date, eDate: Date, autoClose: boolean = true) => { dateRange.open(); fixture.detectChanges(); calendarDays = document.getElementsByClassName(CSS_CLASS_CALENDAR_DATE); const nodesArray = Array.from(calendarDays); - const findNodeIndex: (d: Date) => number = - (d: Date) => nodesArray - .findIndex( - n => n.attributes['aria-label'].value === d.toDateString() - && !n.classList.contains(CSS_CLASS_INACTIVE_DATE) - ); + const findNodeIndex: (d: Date) => number = (d: Date) => nodesArray + .findIndex(n => n.attributes['aria-label'].value === d.toDateString() + && !n.classList.contains(CSS_CLASS_INACTIVE_DATE)); const startIndex = findNodeIndex(sDate); const endIndex = findNodeIndex(eDate); if (startIndex === -1) { @@ -306,7 +305,7 @@ describe('IgxDateRangePicker', () => { fixture.detectChanges(); - if (autoClose){ + if (autoClose) { dateRange.close(); fixture.detectChanges(); } @@ -430,7 +429,7 @@ describe('IgxDateRangePicker', () => { const inputGroup = fixture.debugElement.query(By.directive(IgxInputGroupComponent)); let suffix = inputGroup.query(By.directive(IgxSuffixDirective)); - spyOn(dateRange.valueChange, 'emit'); + vi.spyOn(dateRange.valueChange, 'emit'); UIInteractions.simulateClickAndSelectEvent(suffix.nativeElement); tick(); @@ -439,7 +438,8 @@ describe('IgxDateRangePicker', () => { expect(dateRange.value).toBeNull(); suffix = inputGroup.query(By.directive(IgxSuffixDirective)); expect(suffix).toBeNull(); - expect(dateRange.valueChange.emit).toHaveBeenCalledOnceWith(null); + expect(dateRange.valueChange.emit).toHaveBeenCalledTimes(1); + expect(dateRange.valueChange.emit).toHaveBeenCalledWith(null); })); it('should not clear the value when clicking element in the suffix that is not the clear icon', fakeAsync(() => { @@ -489,13 +489,14 @@ describe('IgxDateRangePicker', () => { dateRange.value = range; fixture.detectChanges(); - spyOn(dateRange.valueChange, 'emit'); + vi.spyOn(dateRange.valueChange, 'emit'); UIInteractions.simulateClickAndSelectEvent(pickerClear.nativeElement); tick(); fixture.detectChanges(); expect(dateRange.value).toBeNull(); - expect(dateRange.valueChange.emit).toHaveBeenCalledOnceWith(null); + expect(dateRange.valueChange.emit).toHaveBeenCalledTimes(1); + expect(dateRange.valueChange.emit).toHaveBeenCalledWith(null); })); }); }); @@ -577,8 +578,8 @@ describe('IgxDateRangePicker', () => { fixture.componentInstance.mode = PickerInteractionMode.Dialog; fixture.componentInstance.dateRange.displayFormat = 'M/d/yyyy'; fixture.detectChanges(); - spyOn(dateRange.closing, 'emit').and.callThrough(); - spyOn(dateRange.closed, 'emit').and.callThrough(); + vi.spyOn(dateRange.closing, 'emit'); + vi.spyOn(dateRange.closed, 'emit'); dateRange.open(); tick(); @@ -590,7 +591,7 @@ describe('IgxDateRangePicker', () => { tick(); fixture.detectChanges(); - expect(dateRange.collapsed).toBeTrue(); + expect(dateRange.collapsed).toBe(true); expect(dateRange.closing.emit).toHaveBeenCalledTimes(1); expect(dateRange.closing.emit).toHaveBeenCalledWith({ owner: dateRange, cancel: false, event: undefined }); expect(dateRange.closed.emit).toHaveBeenCalledTimes(1); @@ -603,8 +604,8 @@ describe('IgxDateRangePicker', () => { fixture.componentInstance.dateRange.value = orig; fixture.detectChanges(); - spyOn(dateRange.closing, 'emit').and.callThrough(); - spyOn(dateRange.closed, 'emit').and.callThrough(); + vi.spyOn(dateRange.closing, 'emit'); + vi.spyOn(dateRange.closed, 'emit'); dateRange.open(); tick(); @@ -618,7 +619,7 @@ describe('IgxDateRangePicker', () => { tick(); fixture.detectChanges(); - expect(dateRange.collapsed).toBeTrue(); + expect(dateRange.collapsed).toBe(true); expect(dateRange.closing.emit).toHaveBeenCalledTimes(1); expect(dateRange.closing.emit).toHaveBeenCalledWith({ owner: dateRange, cancel: false, event: undefined }); expect(dateRange.closed.emit).toHaveBeenCalledTimes(1); @@ -668,7 +669,7 @@ describe('IgxDateRangePicker', () => { fixture.detectChanges(); dateRange.doneButtonText = 'Close'; - dateRange.cancelButtonText = 'Discard' + dateRange.cancelButtonText = 'Discard'; fixture.detectChanges(); dateRange.toggle(); tick(); @@ -681,10 +682,10 @@ describe('IgxDateRangePicker', () => { it('should emit open/close events - open/close methods', fakeAsync(() => { fixture.componentInstance.dateRange.displayFormat = 'M/d/yyyy'; fixture.detectChanges(); - spyOn(dateRange.opening, 'emit').and.callThrough(); - spyOn(dateRange.opened, 'emit').and.callThrough(); - spyOn(dateRange.closing, 'emit').and.callThrough(); - spyOn(dateRange.closed, 'emit').and.callThrough(); + vi.spyOn(dateRange.opening, 'emit'); + vi.spyOn(dateRange.opened, 'emit'); + vi.spyOn(dateRange.closing, 'emit'); + vi.spyOn(dateRange.closed, 'emit'); dateRange.open(); tick(DEBOUNCE_TIME); @@ -707,10 +708,10 @@ describe('IgxDateRangePicker', () => { })); it('should emit open/close events - toggle method', fakeAsync(() => { - spyOn(dateRange.opening, 'emit').and.callThrough(); - spyOn(dateRange.opened, 'emit').and.callThrough(); - spyOn(dateRange.closing, 'emit').and.callThrough(); - spyOn(dateRange.closed, 'emit').and.callThrough(); + vi.spyOn(dateRange.opening, 'emit'); + vi.spyOn(dateRange.opened, 'emit'); + vi.spyOn(dateRange.closing, 'emit'); + vi.spyOn(dateRange.closed, 'emit'); dateRange.toggle(); tick(DEBOUNCE_TIME); @@ -736,8 +737,8 @@ describe('IgxDateRangePicker', () => { })); it('should not close calendar if closing event is canceled', fakeAsync(() => { - spyOn(dateRange.closing, 'emit').and.callThrough(); - spyOn(dateRange.closed, 'emit').and.callThrough(); + vi.spyOn(dateRange.closing, 'emit'); + vi.spyOn(dateRange.closed, 'emit'); dateRange.closing.subscribe((e: CancelableEventArgs) => e.cancel = true); dateRange.toggle(); @@ -763,12 +764,12 @@ describe('IgxDateRangePicker', () => { describe('Keyboard navigation', () => { it('should toggle the calendar with ALT + DOWN/UP ARROW key', fakeAsync(() => { - spyOn(dateRange.opening, 'emit').and.callThrough(); - spyOn(dateRange.opened, 'emit').and.callThrough(); - spyOn(dateRange.closing, 'emit').and.callThrough(); - spyOn(dateRange.closed, 'emit').and.callThrough(); + vi.spyOn(dateRange.opening, 'emit'); + vi.spyOn(dateRange.opened, 'emit'); + vi.spyOn(dateRange.closing, 'emit'); + vi.spyOn(dateRange.closed, 'emit'); expect(dateRange.collapsed).toBeTruthy(); - expect(dateRange.isFocused).toBeFalse(); + expect(dateRange.isFocused).toBe(false); const range = fixture.debugElement.query(By.css(CSS_CLASS_DATE_RANGE)); UIInteractions.triggerEventHandlerKeyDown('ArrowDown', range, true); @@ -781,10 +782,8 @@ describe('IgxDateRangePicker', () => { expect(dateRange.opened.emit).toHaveBeenCalledTimes(1); const calendarWrapper = fixture.debugElement.query(By.css('.igx-calendar__wrapper')).nativeElement; - expect(calendarWrapper.contains(document.activeElement)) - .withContext('focus should move to calendar for KB nav') - .toBeTrue(); - expect(dateRange.isFocused).toBeTrue(); + expect(calendarWrapper.contains(document.activeElement), 'focus should move to calendar for KB nav').toBe(true); + expect(dateRange.isFocused).toBe(true); UIInteractions.triggerKeyDownEvtUponElem('ArrowUp', calendarWrapper, true, true); tick(); @@ -792,15 +791,13 @@ describe('IgxDateRangePicker', () => { expect(dateRange.collapsed).toBeTruthy(); expect(dateRange.closing.emit).toHaveBeenCalledTimes(1); expect(dateRange.closed.emit).toHaveBeenCalledTimes(1); - expect(dateRange.inputDirective.nativeElement.contains(document.activeElement)) - .withContext('focus should return to the picker input') - .toBeTrue(); - expect(dateRange.isFocused).toBeTrue(); + expect(dateRange.inputDirective.nativeElement.contains(document.activeElement), 'focus should return to the picker input').toBe(true); + expect(dateRange.isFocused).toBe(true); })); it('should close the calendar with ESC', fakeAsync(() => { - spyOn(dateRange.closing, 'emit').and.callThrough(); - spyOn(dateRange.closed, 'emit').and.callThrough(); + vi.spyOn(dateRange.closing, 'emit'); + vi.spyOn(dateRange.closed, 'emit'); dateRange.mode = 'dropdown'; expect(dateRange.collapsed).toBeTruthy(); @@ -810,10 +807,8 @@ describe('IgxDateRangePicker', () => { expect(dateRange.collapsed).toBeFalsy(); const calendarWrapper = fixture.debugElement.query(By.css('.igx-calendar__wrapper')).nativeElement; - expect(calendarWrapper.contains(document.activeElement)) - .withContext('focus should move to calendar for KB nav') - .toBeTrue(); - expect(dateRange.isFocused).toBeTrue(); + expect(calendarWrapper.contains(document.activeElement), 'focus should move to calendar for KB nav').toBe(true); + expect(dateRange.isFocused).toBe(true); UIInteractions.triggerKeyDownEvtUponElem('Escape', calendarWrapper, true); tick(); @@ -822,10 +817,8 @@ describe('IgxDateRangePicker', () => { expect(dateRange.collapsed).toBeTruthy(); expect(dateRange.closing.emit).toHaveBeenCalledTimes(1); expect(dateRange.closed.emit).toHaveBeenCalledTimes(1); - expect(dateRange.inputDirective.nativeElement.contains(document.activeElement)) - .withContext('focus should return to the picker input') - .toBeTrue(); - expect(dateRange.isFocused).toBeTrue(); + expect(dateRange.inputDirective.nativeElement.contains(document.activeElement), 'focus should return to the picker input').toBe(true); + expect(dateRange.isFocused).toBe(true); })); it('should not open calendar with ALT + DOWN ARROW key if disabled is set to true', fakeAsync(() => { @@ -833,8 +826,8 @@ describe('IgxDateRangePicker', () => { fixture.componentInstance.disabled = true; fixture.detectChanges(); - spyOn(dateRange.opening, 'emit').and.callThrough(); - spyOn(dateRange.opened, 'emit').and.callThrough(); + vi.spyOn(dateRange.opening, 'emit'); + vi.spyOn(dateRange.opened, 'emit'); const input = document.getElementsByClassName('igx-input-group__input')[0]; UIInteractions.triggerKeyDownEvtUponElem('ArrowDown', input, true, true); @@ -889,15 +882,15 @@ describe('IgxDateRangePicker', () => { disabled$.next(true); testFixture.detectChanges(); - expect(dateRange.inputDirective.disabled).toBeTrue(); + expect(dateRange.inputDirective.disabled).toBe(true); disabled$.next(false); testFixture.detectChanges(); - expect(dateRange.inputDirective.disabled).toBeFalse(); + expect(dateRange.inputDirective.disabled).toBe(false); disabled$.next(true); testFixture.detectChanges(); - expect(dateRange.inputDirective.disabled).toBeTrue(); + expect(dateRange.inputDirective.disabled).toBe(true); disabled$.complete(); })); @@ -1287,12 +1280,12 @@ describe('IgxDateRangePicker', () => { describe('Keyboard navigation', () => { it('should toggle the calendar with ALT + DOWN/UP ARROW key - dropdown mode', fakeAsync(() => { expect(dateRange.collapsed).toBeTruthy(); - expect(dateRange.isFocused).toBeFalse(); + expect(dateRange.isFocused).toBe(false); - spyOn(dateRange.opening, 'emit').and.callThrough(); - spyOn(dateRange.opened, 'emit').and.callThrough(); - spyOn(dateRange.closing, 'emit').and.callThrough(); - spyOn(dateRange.closed, 'emit').and.callThrough(); + vi.spyOn(dateRange.opening, 'emit'); + vi.spyOn(dateRange.opened, 'emit'); + vi.spyOn(dateRange.closing, 'emit'); + vi.spyOn(dateRange.closed, 'emit'); expect(dateRange.collapsed).toBeTruthy(); startInput.nativeElement.focus(); @@ -1306,10 +1299,8 @@ describe('IgxDateRangePicker', () => { expect(dateRange.opened.emit).toHaveBeenCalledTimes(1); let calendarWrapper = document.getElementsByClassName('igx-calendar__wrapper')[0]; - expect(calendarWrapper.contains(document.activeElement)) - .withContext('focus should move to calendar for KB nav') - .toBeTrue(); - expect(dateRange.isFocused).toBeTrue(); + expect(calendarWrapper.contains(document.activeElement), 'focus should move to calendar for KB nav').toBe(true); + expect(dateRange.isFocused).toBe(true); UIInteractions.triggerKeyDownEvtUponElem('ArrowUp', calendarWrapper, true, true); tick(); @@ -1317,10 +1308,8 @@ describe('IgxDateRangePicker', () => { expect(dateRange.collapsed).toBeTruthy(); expect(dateRange.closing.emit).toHaveBeenCalledTimes(1); expect(dateRange.closed.emit).toHaveBeenCalledTimes(1); - expect(startInput.nativeElement.contains(document.activeElement)) - .withContext('focus should return to the picker input') - .toBeTrue(); - expect(dateRange.isFocused).toBeTrue(); + expect(startInput.nativeElement.contains(document.activeElement), 'focus should return to the picker input').toBe(true); + expect(dateRange.isFocused).toBe(true); // reopen and close again UIInteractions.triggerEventHandlerKeyDown('ArrowDown', range, true); @@ -1328,17 +1317,13 @@ describe('IgxDateRangePicker', () => { fixture.detectChanges(); calendarWrapper = document.getElementsByClassName('igx-calendar__wrapper')[0]; - expect(calendarWrapper.contains(document.activeElement)) - .withContext('focus should move to calendar for KB nav') - .toBeTrue(); + expect(calendarWrapper.contains(document.activeElement), 'focus should move to calendar for KB nav').toBe(true); UIInteractions.triggerKeyDownEvtUponElem('ArrowUp', calendarWrapper, true, true); tick(); fixture.detectChanges(); - expect(startInput.nativeElement.contains(document.activeElement)) - .withContext('focus should return to the picker input') - .toBeTrue(); - expect(dateRange.isFocused).toBeTrue(); + expect(startInput.nativeElement.contains(document.activeElement), 'focus should return to the picker input').toBe(true); + expect(dateRange.isFocused).toBe(true); })); it('should toggle the calendar with ALT + DOWN/UP ARROW key - dialog mode', fakeAsync(() => { @@ -1346,10 +1331,10 @@ describe('IgxDateRangePicker', () => { fixture.detectChanges(); expect(dateRange.collapsed).toBeTruthy(); - spyOn(dateRange.opening, 'emit').and.callThrough(); - spyOn(dateRange.opened, 'emit').and.callThrough(); - spyOn(dateRange.closing, 'emit').and.callThrough(); - spyOn(dateRange.closed, 'emit').and.callThrough(); + vi.spyOn(dateRange.opening, 'emit'); + vi.spyOn(dateRange.opened, 'emit'); + vi.spyOn(dateRange.closing, 'emit'); + vi.spyOn(dateRange.closed, 'emit'); expect(dateRange.collapsed).toBeTruthy(); const range = fixture.debugElement.query(By.css(CSS_CLASS_DATE_RANGE)); @@ -1370,8 +1355,8 @@ describe('IgxDateRangePicker', () => { })); it('should close the calendar with ESC', fakeAsync(() => { - spyOn(dateRange.closing, 'emit').and.callThrough(); - spyOn(dateRange.closed, 'emit').and.callThrough(); + vi.spyOn(dateRange.closing, 'emit'); + vi.spyOn(dateRange.closed, 'emit'); dateRange.mode = 'dropdown'; startInput.nativeElement.focus(); @@ -1382,10 +1367,8 @@ describe('IgxDateRangePicker', () => { expect(dateRange.collapsed).toBeFalsy(); let calendarWrapper = document.getElementsByClassName('igx-calendar__wrapper')[0]; - expect(calendarWrapper.contains(document.activeElement)) - .withContext('focus should move to calendar for KB nav') - .toBeTrue(); - expect(dateRange.isFocused).toBeTrue(); + expect(calendarWrapper.contains(document.activeElement), 'focus should move to calendar for KB nav').toBe(true); + expect(dateRange.isFocused).toBe(true); UIInteractions.triggerKeyDownEvtUponElem('Escape', calendarWrapper, true); tick(); @@ -1394,10 +1377,8 @@ describe('IgxDateRangePicker', () => { expect(dateRange.collapsed).toBeTruthy(); expect(dateRange.closing.emit).toHaveBeenCalledTimes(1); expect(dateRange.closed.emit).toHaveBeenCalledTimes(1); - expect(startInput.nativeElement.contains(document.activeElement)) - .withContext('focus should return to the picker input') - .toBeTrue(); - expect(dateRange.isFocused).toBeTrue(); + expect(startInput.nativeElement.contains(document.activeElement), 'focus should return to the picker input').toBe(true); + expect(dateRange.isFocused).toBe(true); // reopen and close again dateRange.open(); @@ -1405,25 +1386,21 @@ describe('IgxDateRangePicker', () => { fixture.detectChanges(); calendarWrapper = document.getElementsByClassName('igx-calendar__wrapper')[0]; - expect(calendarWrapper.contains(document.activeElement)) - .withContext('focus should move to calendar for KB nav') - .toBeTrue(); + expect(calendarWrapper.contains(document.activeElement), 'focus should move to calendar for KB nav').toBe(true); UIInteractions.triggerKeyDownEvtUponElem('ArrowUp', calendarWrapper, true, true); tick(); fixture.detectChanges(); - expect(startInput.nativeElement.contains(document.activeElement)) - .withContext('focus should return to the picker input') - .toBeTrue(); - expect(dateRange.isFocused).toBeTrue(); + expect(startInput.nativeElement.contains(document.activeElement), 'focus should return to the picker input').toBe(true); + expect(dateRange.isFocused).toBe(true); })); it('should not open calendar with ALT + DOWN ARROW key if disabled is set to true', fakeAsync(() => { fixture.componentInstance.disabled = true; fixture.detectChanges(); - spyOn(dateRange.opening, 'emit').and.callThrough(); - spyOn(dateRange.opened, 'emit').and.callThrough(); + vi.spyOn(dateRange.opening, 'emit'); + vi.spyOn(dateRange.opened, 'emit'); // UIInteractions.triggerEventHandlerKeyDown('ArrowDown', calendar, true); tick(DEBOUNCE_TIME * 2); @@ -1582,18 +1559,18 @@ describe('IgxDateRangePicker', () => { disabled$.next(true); testFixture.detectChanges(); - expect(dateRange.projectedInputs.first.inputDirective.disabled).toBeTrue(); - expect(dateRange.projectedInputs.last.inputDirective.disabled).toBeTrue(); + expect(dateRange.projectedInputs.first.inputDirective.disabled).toBe(true); + expect(dateRange.projectedInputs.last.inputDirective.disabled).toBe(true); disabled$.next(false); testFixture.detectChanges(); - expect(dateRange.projectedInputs.first.inputDirective.disabled).toBeFalse(); - expect(dateRange.projectedInputs.last.disabled).toBeFalse(); + expect(dateRange.projectedInputs.first.inputDirective.disabled).toBe(false); + expect(dateRange.projectedInputs.last.disabled).toBe(false); disabled$.next(true); testFixture.detectChanges(); - expect(dateRange.projectedInputs.first.inputDirective.disabled).toBeTrue(); - expect(dateRange.projectedInputs.last.inputDirective.disabled).toBeTrue(); + expect(dateRange.projectedInputs.first.inputDirective.disabled).toBe(true); + expect(dateRange.projectedInputs.last.inputDirective.disabled).toBe(true); disabled$.complete(); })); @@ -1623,7 +1600,7 @@ describe('IgxDateRangePicker', () => { })); }); - describe('Predefined ranges', ()=> { + describe('Predefined ranges', () => { const predefinedRangesLength = 4; const today = CalendarDay.today.native; const last7DaysEnd = CalendarDay.today.add('day', -7).native; @@ -1652,12 +1629,12 @@ describe('IgxDateRangePicker', () => { ]; const dateRanges: DateRange[] = [ - {start: last7DaysEnd, end: today}, - {start: startOfMonth, end: endOfMonth}, - {start: last30DaysEnd, end: today}, - {start: startOfYear, end: today}, - {start: previousThreeDaysStart, end: today}, - {start: today, end: nextThreeDaysEnd}, + { start: last7DaysEnd, end: today }, + { start: startOfMonth, end: endOfMonth }, + { start: last30DaysEnd, end: today }, + { start: startOfYear, end: today }, + { start: previousThreeDaysStart, end: today }, + { start: today, end: nextThreeDaysEnd }, ]; beforeEach(() => { @@ -1724,7 +1701,7 @@ describe('IgxDateRangePicker', () => { }); it('should render predefined area and emit selection event when the user performs selection via chips', () => { - const selectionSpy = spyOn(dateRange as any, 'handleSelection').and.callThrough(); + const selectionSpy = vi.spyOn(dateRange as any, 'handleSelection'); dateRange.usePredefinedRanges = true; dateRange.customRanges = customRanges; @@ -1914,7 +1891,7 @@ describe('IgxDateRangePicker', () => { it('should invoke AutoPositionStrategy by default with proper arguments', fakeAsync(() => { fixture = TestBed.createComponent(DateRangeDefaultComponent); fixture.detectChanges(); - spyOn(AutoPositionStrategy.prototype, 'position'); + vi.spyOn(AutoPositionStrategy.prototype, 'position'); dateRange = fixture.componentInstance.dateRange; dateRange.open(); @@ -1924,8 +1901,7 @@ describe('IgxDateRangePicker', () => { const overlayContent = document.getElementsByClassName(CSS_CLASS_OVERLAY_CONTENT)[0] as HTMLElement; expect(AutoPositionStrategy.prototype.position).toHaveBeenCalledTimes(1); expect(AutoPositionStrategy.prototype.position) - .toHaveBeenCalledWith(overlayContent, jasmine.anything(), document, - jasmine.anything(), dateRange.element.nativeElement); + .toHaveBeenCalledWith(overlayContent, expect.anything(), document, expect.anything(), dateRange.element.nativeElement); })); it('Should the weekStart property takes precedence over locale.', fakeAsync(() => { fixture = TestBed.createComponent(DateRangeCustomComponent); @@ -1958,7 +1934,7 @@ describe('IgxDateRangePicker', () => { fixture.detectChanges(); expect(dateRange.locale).toEqual(locale); - expect(dateRange.weekStart).toEqual(WEEKDAYS.SUNDAY) + expect(dateRange.weekStart).toEqual(WEEKDAYS.SUNDAY); dateRange.locale = 'frrr'; dateRange.weekStart = WEEKDAYS.FRIDAY; @@ -1977,7 +1953,7 @@ describe('IgxDateRangePicker', () => { tick(); fixture.detectChanges(); - expect(dateRange['_calendar'].hasHeader).toBeTrue(); + expect(dateRange['_calendar'].hasHeader).toBe(true); const calendarHeader = fixture.debugElement.query(By.css(CSS_CLASS_CALENDAR_HEADER_TEMPLATE)); expect(calendarHeader).toBeTruthy('Calendar header should be present'); })); @@ -2017,7 +1993,7 @@ describe('IgxDateRangePicker', () => { tick(); fixture.detectChanges(); - expect(dateRange['_calendar'].hasHeader).toBeFalse(); + expect(dateRange['_calendar'].hasHeader).toBe(false); const calendarHeader = fixture.debugElement.query(By.css(CSS_CLASS_CALENDAR_HEADER)); expect(calendarHeader).toBeFalsy('Calendar header should not be present'); })); @@ -2031,7 +2007,7 @@ describe('IgxDateRangePicker', () => { fixture.detectChanges(); expect(dateRange['_calendar'].orientation).toEqual(PickerCalendarOrientation.Horizontal.toString()); - expect(dateRange['_calendar'].wrapper.nativeElement).not.toHaveClass(CSS_CLASS_CALENDAR_WRAPPER_VERTICAL); + expect(dateRange['_calendar'].wrapper.nativeElement.classList.contains(CSS_CLASS_CALENDAR_WRAPPER_VERTICAL)).toBe(false); dateRange.close(); tick(); fixture.detectChanges(); @@ -2042,7 +2018,7 @@ describe('IgxDateRangePicker', () => { fixture.detectChanges(); expect(dateRange['_calendar'].orientation).toEqual(PickerCalendarOrientation.Vertical.toString()); - expect(dateRange['_calendar'].wrapper.nativeElement).toHaveClass(CSS_CLASS_CALENDAR_WRAPPER_VERTICAL); + expect(dateRange['_calendar'].wrapper.nativeElement.classList.contains(CSS_CLASS_CALENDAR_WRAPPER_VERTICAL)).toBe(true); })); it('should limit the displayMonthsCount property between 1 and 2', fakeAsync(() => { @@ -2069,11 +2045,11 @@ describe('IgxDateRangePicker', () => { dateRange = fixture.componentInstance.dateRange; const specialDates = [{ - type: DateRangeType.Between, dateRange: [ - new Date(new Date().getFullYear(), new Date().getMonth(), 3), - new Date(new Date().getFullYear(), new Date().getMonth(), 8) - ] - }]; + type: DateRangeType.Between, dateRange: [ + new Date(new Date().getFullYear(), new Date().getMonth(), 3), + new Date(new Date().getFullYear(), new Date().getMonth(), 8) + ] + }]; dateRange.specialDates = specialDates; fixture.detectChanges(); @@ -2090,11 +2066,11 @@ describe('IgxDateRangePicker', () => { dateRange = fixture.componentInstance.dateRange; const disabledDates = [{ - type: DateRangeType.Between, dateRange: [ - new Date(new Date().getFullYear(), new Date().getMonth(), 3), - new Date(new Date().getFullYear(), new Date().getMonth(), 8) - ] - }]; + type: DateRangeType.Between, dateRange: [ + new Date(new Date().getFullYear(), new Date().getMonth(), 3), + new Date(new Date().getFullYear(), new Date().getMonth(), 8) + ] + }]; dateRange.disabledDates = disabledDates; fixture.detectChanges(); @@ -2105,7 +2081,7 @@ describe('IgxDateRangePicker', () => { expect(dateRange['_calendar'].disabledDates).toEqual(disabledDates); })); - it('should initialize activeDate with current date, when not set', fakeAsync(() => { + it('should initialize activeDate with current date, when not set', fakeAsync(() => { fixture = TestBed.createComponent(DateRangeDefaultComponent); fixture.detectChanges(); dateRange = fixture.componentInstance.dateRange; @@ -2141,7 +2117,7 @@ describe('IgxDateRangePicker', () => { const wrapper = fixture.debugElement.query(By.css('.igx-calendar__wrapper')).nativeElement; expect(wrapper.getAttribute('aria-activedescendant')).toEqual(activeDescendantDate); - range = { ...range, start: null}; + range = { ...range, start: null }; dateRange.value = range; fixture.detectChanges(); @@ -2150,7 +2126,7 @@ describe('IgxDateRangePicker', () => { it('should set activeDate correctly', fakeAsync(() => { const targetDate = new Date(2025, 11, 1); - fixture = TestBed.createComponent(DateRangeDefaultComponent); + fixture = TestBed.createComponent(DateRangeDefaultComponent); fixture.detectChanges(); dateRange = fixture.componentInstance.dateRange; const range = { start: new Date(2025, 0, 1), end: new Date(2025, 0, 5) }; @@ -2382,7 +2358,7 @@ export class DateRangeCustomComponent extends DateRangeTestComponent { .format(date.start as Date)} ${(date.start as Date).getDate()}, ${(date.start as Date).getFullYear()}`; const endDate = `${this.monthFormatter .format(date.end as Date)} ${(date - .end as Date).getDate()}, ${(date.end as Date).getFullYear()}`; + .end as Date).getDate()}, ${(date.end as Date).getFullYear()}`; return `You selected ${startDate}-${endDate}`; }; } @@ -2482,7 +2458,8 @@ export class DateRangeDisabledComponent extends DateRangeTestComponent { changeDetection: ChangeDetectionStrategy.OnPush, imports: [IgxDateRangePickerComponent, IgxDateRangeStartComponent, IgxDateRangeEndComponent, IgxInputDirective, IgxDateTimeEditorDirective, AsyncPipe] }) -export class DateRangeTwoInputsDisabledComponent extends DateRangeDisabledComponent { } +export class DateRangeTwoInputsDisabledComponent extends DateRangeDisabledComponent { +} @Component({ template: ` @@ -2512,8 +2489,10 @@ export class DateRangeTwoInputsDisabledComponent extends DateRangeDisabledCompon export class DateRangeReactiveFormComponent { private fb = inject(UntypedFormBuilder); - @ViewChild('range', { read: IgxDateRangePickerComponent }) public dateRange: IgxDateRangePickerComponent; - @ViewChild('twoInputs', { read: IgxDateRangePickerComponent }) public dateRangeWithTwoInputs: IgxDateRangePickerComponent; + @ViewChild('range', { read: IgxDateRangePickerComponent }) + public dateRange: IgxDateRangePickerComponent; + @ViewChild('twoInputs', { read: IgxDateRangePickerComponent }) + public dateRangeWithTwoInputs: IgxDateRangePickerComponent; public form = this.fb.group({ range: ['', Validators.required], diff --git a/projects/igniteui-angular/date-picker/src/date-range-picker/predefined-ranges/predefined-ranges-area-component.spec.ts b/projects/igniteui-angular/date-picker/src/date-range-picker/predefined-ranges/predefined-ranges-area-component.spec.ts index d070babf807..541a1650341 100644 --- a/projects/igniteui-angular/date-picker/src/date-range-picker/predefined-ranges/predefined-ranges-area-component.spec.ts +++ b/projects/igniteui-angular/date-picker/src/date-range-picker/predefined-ranges/predefined-ranges-area-component.spec.ts @@ -6,151 +6,152 @@ import { CalendarDay, CustomDateRange } from 'igniteui-angular/core'; import { IDateRangePickerResourceStrings } from '../../../../core/src/core/i18n/date-range-picker-resources'; import { IgxChipComponent } from '../../../../chips/src/chips/chip.component'; import { Component, ViewChild } from '@angular/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxPredefinedRangesAreaComponent', () => { - let fixture: ComponentFixture; - let component: PredefinedRangesDefaultComponent; - let predefinedRanges:IgxPredefinedRangesAreaComponent; - - const customRanges: CustomDateRange[] = [ - { - label: 'Previous Three Months', - dateRange: { - start: CalendarDay.today.add('month', -3).set({ date: 1 }).native, - end: CalendarDay.today.set({ date: 1 }).add('day', -1).native, - }, - }, - { - label: 'Next Three Months', - dateRange: { - start: CalendarDay.today.add('month', 1).set({ date: 1 }).native, - end: CalendarDay.today.add('month', 4).add('day', -1).native, - }, - }, - ]; - - function getChips() { - return fixture.debugElement.queryAll(By.css('igx-chip')); - } - - - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [IgxPredefinedRangesAreaComponent, IgxChipComponent, PredefinedRangesDefaultComponent] - }).compileComponents(); - - fixture = TestBed.createComponent(PredefinedRangesDefaultComponent); - component = fixture.componentInstance; - predefinedRanges = component.predefinedRanges; - fixture.detectChanges(); - }); - - it('should render no chips by default', () => { - expect(getChips().length).toBe(0); - }); - - it('should render predefined ranges when usePredefinedRanges = true', () => { - component.usePredefinedRanges = true; - fixture.detectChanges(); - - const chips = getChips(); - expect(chips.length).toBe(predefinedRanges.ranges.length); - chips.forEach((de, i) => { - const text = (de.nativeElement as HTMLElement).innerText.trim(); - expect(text).toBe(predefinedRanges.ranges[i].label); + let fixture: ComponentFixture; + let component: PredefinedRangesDefaultComponent; + let predefinedRanges: IgxPredefinedRangesAreaComponent; + + const customRanges: CustomDateRange[] = [ + { + label: 'Previous Three Months', + dateRange: { + start: CalendarDay.today.add('month', -3).set({ date: 1 }).native, + end: CalendarDay.today.set({ date: 1 }).add('day', -1).native, + }, + }, + { + label: 'Next Three Months', + dateRange: { + start: CalendarDay.today.add('month', 1).set({ date: 1 }).native, + end: CalendarDay.today.add('month', 4).add('day', -1).native, + }, + }, + ]; + + function getChips() { + return fixture.debugElement.queryAll(By.css('igx-chip')); + } + + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [IgxPredefinedRangesAreaComponent, IgxChipComponent, PredefinedRangesDefaultComponent] + }).compileComponents(); + + fixture = TestBed.createComponent(PredefinedRangesDefaultComponent); + component = fixture.componentInstance; + predefinedRanges = component.predefinedRanges; + fixture.detectChanges(); }); - }); - it('should render predefined + custom ranges together', () => { - component.usePredefinedRanges = true; - component.customRanges = customRanges; - fixture.detectChanges(); + it('should render no chips by default', () => { + expect(getChips().length).toBe(0); + }); - const chips = getChips(); - const ranges = predefinedRanges.ranges; + it('should render predefined ranges when usePredefinedRanges = true', () => { + component.usePredefinedRanges = true; + fixture.detectChanges(); - expect(chips.length).toBe(ranges.length); - chips.forEach((de, i) => { - const text = (de.nativeElement as HTMLElement).innerText.trim(); - expect(text).toBe(ranges[i].label); + const chips = getChips(); + expect(chips.length).toBe(predefinedRanges.ranges.length); + chips.forEach((de, i) => { + const text = (de.nativeElement as HTMLElement).innerText.trim(); + expect(text).toBe(predefinedRanges.ranges[i].label); + }); }); - }); - it('should render only custom ranges when usePredefinedRanges = false', () => { - component.usePredefinedRanges = false; - component.customRanges = customRanges; - fixture.detectChanges(); + it('should render predefined + custom ranges together', () => { + component.usePredefinedRanges = true; + component.customRanges = customRanges; + fixture.detectChanges(); - const chips = getChips(); - const ranges = predefinedRanges.ranges; + const chips = getChips(); + const ranges = predefinedRanges.ranges; - expect(chips.length).toBe(ranges.length); - chips.forEach((de, i) => { - const text = (de.nativeElement as HTMLElement).innerText.trim(); - expect(text).toBe(ranges[i].label); + expect(chips.length).toBe(ranges.length); + chips.forEach((de, i) => { + const text = (de.nativeElement as HTMLElement).innerText.trim(); + expect(text).toBe(ranges[i].label); + }); }); - }); - it('should emit selected range on chip click', () => { - component.usePredefinedRanges = true; - component.customRanges = customRanges; - fixture.detectChanges(); + it('should render only custom ranges when usePredefinedRanges = false', () => { + component.usePredefinedRanges = false; + component.customRanges = customRanges; + fixture.detectChanges(); - const chips = getChips(); - const ranges = predefinedRanges.ranges; - expect(chips.length).toBe(ranges.length); + const chips = getChips(); + const ranges = predefinedRanges.ranges; - const emitSpy = spyOn(predefinedRanges.rangeSelect, 'emit'); + expect(chips.length).toBe(ranges.length); + chips.forEach((de, i) => { + const text = (de.nativeElement as HTMLElement).innerText.trim(); + expect(text).toBe(ranges[i].label); + }); + }); - chips.forEach((de, i) => { - (de.nativeElement as HTMLElement).click(); + it('should emit selected range on chip click', () => { + component.usePredefinedRanges = true; + component.customRanges = customRanges; fixture.detectChanges(); - expect(emitSpy).toHaveBeenCalledWith(ranges[i].dateRange); + + const chips = getChips(); + const ranges = predefinedRanges.ranges; + expect(chips.length).toBe(ranges.length); + + const emitSpy = vi.spyOn(predefinedRanges.rangeSelect, 'emit'); + + chips.forEach((de, i) => { + (de.nativeElement as HTMLElement).click(); + fixture.detectChanges(); + expect(emitSpy).toHaveBeenCalledWith(ranges[i].dateRange); + }); + }); + + it('should use provided resourceStrings for labels when available', () => { + const strings: any = { + last7Days: 'Last 7 - localized', + currentMonth: 'Current Month - localized', + yearToDate: 'YTD - localized', + igx_date_range_picker_last7Days: 'Last 7 - localized', + igx_date_range_picker_currentMonth: 'Current Month - localized', + igx_date_range_picker_yearToDate: 'YTD - localized', + // last30Days omitted to test fallback + }; + + predefinedRanges.resourceStrings = strings; + component.usePredefinedRanges = true; + component.customRanges = []; + fixture.detectChanges(); + + const chips = getChips(); + const labels = chips.map(de => (de.nativeElement as HTMLElement).innerText.trim()); + + expect(labels).toContain('Last 7 - localized'); + expect(labels).toContain('Current Month - localized'); + expect(labels).toContain('YTD - localized'); + + expect(labels).toContain('Last 30 Days'); }); - }); - - it('should use provided resourceStrings for labels when available', () => { - const strings: any = { - last7Days: 'Last 7 - localized', - currentMonth: 'Current Month - localized', - yearToDate: 'YTD - localized', - igx_date_range_picker_last7Days: 'Last 7 - localized', - igx_date_range_picker_currentMonth: 'Current Month - localized', - igx_date_range_picker_yearToDate: 'YTD - localized', - // last30Days omitted to test fallback - }; - - predefinedRanges.resourceStrings = strings; - component.usePredefinedRanges = true; - component.customRanges = []; - fixture.detectChanges(); - - const chips = getChips(); - const labels = chips.map(de => (de.nativeElement as HTMLElement).innerText.trim()); - - expect(labels).toContain('Last 7 - localized'); - expect(labels).toContain('Current Month - localized'); - expect(labels).toContain('YTD - localized'); - - expect(labels).toContain('Last 30 Days'); - }); }); @Component({ - standalone: true, - template: ` + standalone: true, + template: ` `, - imports: [IgxPredefinedRangesAreaComponent] + imports: [IgxPredefinedRangesAreaComponent] }) class PredefinedRangesDefaultComponent { - public usePredefinedRanges = false; - public customRanges = []; - public resourceStrings?: IDateRangePickerResourceStrings; + public usePredefinedRanges = false; + public customRanges = []; + public resourceStrings?: IDateRangePickerResourceStrings; - @ViewChild(IgxPredefinedRangesAreaComponent, { static: true }) - public predefinedRanges!: IgxPredefinedRangesAreaComponent; + @ViewChild(IgxPredefinedRangesAreaComponent, { static: true }) + public predefinedRanges!: IgxPredefinedRangesAreaComponent; } diff --git a/projects/igniteui-angular/dialog/src/dialog/dialog.component.spec.ts b/projects/igniteui-angular/dialog/src/dialog/dialog.component.spec.ts index fea22acc8d9..da1f6de99c7 100644 --- a/projects/igniteui-angular/dialog/src/dialog/dialog.component.spec.ts +++ b/projects/igniteui-angular/dialog/src/dialog/dialog.component.spec.ts @@ -9,6 +9,7 @@ import { PositionSettings, HorizontalAlignment, VerticalAlignment } from 'ignite import { IgxToggleDirective } from '../../../directives/src/directives/toggle/toggle.directive'; import { IgxDialogActionsDirective, IgxDialogTitleDirective } from './dialog.directives'; import { slideInTop, slideOutBottom } from 'igniteui-angular/animations'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; const OVERLAY_MAIN_CLASS = 'igx-overlay'; const OVERLAY_WRAPPER_CLASS = `${OVERLAY_MAIN_CLASS}__wrapper--flex`; @@ -263,11 +264,11 @@ describe('Dialog', () => { cancel: false }; - spyOn(dialog.opening, 'emit'); - spyOn(dialog.opened, 'emit'); - spyOn(dialog.isOpenChange, 'emit'); - spyOn(dialog.closing, 'emit'); - spyOn(dialog.closed, 'emit'); + vi.spyOn(dialog.opening, 'emit'); + vi.spyOn(dialog.opened, 'emit'); + vi.spyOn(dialog.isOpenChange, 'emit'); + vi.spyOn(dialog.closing, 'emit'); + vi.spyOn(dialog.closed, 'emit'); dialog.open(); tick(); @@ -293,11 +294,11 @@ describe('Dialog', () => { const leftButton = buttons[0]; const rightButton = buttons[1]; - spyOn(dialog.leftButtonSelect, 'emit'); + vi.spyOn(dialog.leftButtonSelect, 'emit'); dispatchEvent(leftButton, 'click'); expect(dialog.leftButtonSelect.emit).toHaveBeenCalled(); - spyOn(dialog.rightButtonSelect, 'emit'); + vi.spyOn(dialog.rightButtonSelect, 'emit'); dispatchEvent(rightButton, 'click'); tick(); expect(dialog.rightButtonSelect.emit).toHaveBeenCalled(); @@ -357,10 +358,10 @@ describe('Dialog', () => { it('Should initialize igx-dialog custom title and actions', () => { const data = [{ - component: CustomTemplates1DialogComponent - }, { - component: CustomTemplates2DialogComponent - }]; + component: CustomTemplates1DialogComponent + }, { + component: CustomTemplates2DialogComponent + }]; data.forEach((item) => { const fixture = TestBed.createComponent(item.component); @@ -457,9 +458,9 @@ describe('Dialog', () => { expect(dialog.isOpen).toEqual(true); const firstContentRect = document.getElementsByClassName(CLASS_OVERLAY_CONTENT_MODAL)[0].getBoundingClientRect(); const middleDialogPosition = document.documentElement.offsetHeight / 2 - firstContentRect.height / 2; - expect(firstContentRect.left).toEqual(0, 'OffsetLeft position check'); - expect(firstContentRect.top).toBeGreaterThanOrEqual(middleDialogPosition - 2, 'OffsetTop position check'); - expect(firstContentRect.top).toBeLessThanOrEqual(middleDialogPosition + 2, 'OffsetTop position check'); + expect(firstContentRect.left, 'OffsetLeft position check').toEqual(0); + expect(firstContentRect.top, 'OffsetTop position check').toBeGreaterThanOrEqual(middleDialogPosition - 2); + expect(firstContentRect.top, 'OffsetTop position check').toBeLessThanOrEqual(middleDialogPosition + 2); dialog.close(); tick(16); @@ -477,9 +478,9 @@ describe('Dialog', () => { expect(dialog.isOpen).toEqual(true); const secondContentRect = document.getElementsByClassName(CLASS_OVERLAY_CONTENT_MODAL)[0].getBoundingClientRect(); const topDialogPosition = document.documentElement.offsetWidth / 2 - secondContentRect.width / 2; - expect(secondContentRect.top).toEqual(0, 'OffsetTop position check'); - expect(secondContentRect.left).toBeGreaterThanOrEqual(topDialogPosition - 2, 'OffsetLeft position check'); - expect(secondContentRect.left).toBeLessThanOrEqual(topDialogPosition + 2, 'OffsetLeft position check'); + expect(secondContentRect.top, 'OffsetTop position check').toEqual(0); + expect(secondContentRect.left, 'OffsetLeft position check').toBeGreaterThanOrEqual(topDialogPosition - 2); + expect(secondContentRect.left, 'OffsetLeft position check').toBeLessThanOrEqual(topDialogPosition + 2); dialog.close(); tick(16); @@ -492,18 +493,18 @@ describe('Dialog', () => { const currentElement = fix.componentInstance; // Check initial animation settings - expect(dialog.positionSettings.openAnimation.animation.type).toEqual(8, 'Animation type is set'); - expect(dialog.positionSettings.openAnimation.options.params.duration).toEqual('200ms', 'Animation duration is set to 200ms'); + expect(dialog.positionSettings.openAnimation.animation.type, 'Animation type is set').toEqual(8); + expect(dialog.positionSettings.openAnimation.options.params.duration, 'Animation duration is set to 200ms').toEqual('200ms'); - expect(dialog.positionSettings.closeAnimation.animation.type).toEqual(8, 'Animation type is set'); - expect(dialog.positionSettings.closeAnimation.options.params.duration).toEqual('200ms', 'Animation duration is set to 200ms'); + expect(dialog.positionSettings.closeAnimation.animation.type, 'Animation type is set').toEqual(8); + expect(dialog.positionSettings.closeAnimation.options.params.duration, 'Animation duration is set to 200ms').toEqual('200ms'); dialog.positionSettings = currentElement.animationSettings; fix.detectChanges(); // Check the new animation settings - expect(dialog.positionSettings.openAnimation.options.params.duration).toEqual('800ms', 'Animation duration is set to 800ms'); - expect(dialog.positionSettings.closeAnimation.options.params.duration).toEqual('700ms', 'Animation duration is set to 700ms'); + expect(dialog.positionSettings.openAnimation.options.params.duration, 'Animation duration is set to 800ms').toEqual('800ms'); + expect(dialog.positionSettings.closeAnimation.options.params.duration, 'Animation duration is set to 700ms').toEqual('700ms'); }); }); @@ -527,7 +528,8 @@ describe('Dialog', () => { imports: [IgxDialogComponent] }) class AlertComponent { - @ViewChild('dialog', { static: true }) public dialog: IgxDialogComponent; + @ViewChild('dialog', { static: true }) + public dialog: IgxDialogComponent; public isModal = false; } @@ -546,7 +548,8 @@ class AlertComponent { imports: [IgxDialogComponent] }) class DialogComponent { - @ViewChild('dialog', { static: true }) public dialog: IgxDialogComponent; + @ViewChild('dialog', { static: true }) + public dialog: IgxDialogComponent; } @Component({ @@ -565,7 +568,8 @@ class DialogComponent { imports: [IgxDialogComponent] }) class DialogTwoWayDataBindingComponent { - @ViewChild('dialog', { static: true }) public dialog: IgxDialogComponent; + @ViewChild('dialog', { static: true }) + public dialog: IgxDialogComponent; public myDialog = false; } @@ -587,7 +591,8 @@ class DialogTwoWayDataBindingComponent { imports: [IgxDialogComponent] }) class DialogSampleComponent { - @ViewChild('dialog', { static: true }) public dialog: IgxDialogComponent; + @ViewChild('dialog', { static: true }) + public dialog: IgxDialogComponent; } @Component({ template: ` @@ -601,7 +606,8 @@ class DialogSampleComponent { imports: [IgxDialogComponent] }) class CustomDialogComponent { - @ViewChild('dialog', { static: true }) public dialog: IgxDialogComponent; + @ViewChild('dialog', { static: true }) + public dialog: IgxDialogComponent; } @Component({ @@ -622,8 +628,10 @@ class CustomDialogComponent { imports: [IgxDialogComponent] }) class NestedDialogsComponent { - @ViewChild('child', { static: true }) public child: IgxDialogComponent; - @ViewChild('main', { static: true }) public main: IgxDialogComponent; + @ViewChild('child', { static: true }) + public child: IgxDialogComponent; + @ViewChild('main', { static: true }) + public main: IgxDialogComponent; } @Component({ @@ -639,7 +647,8 @@ class NestedDialogsComponent { imports: [IgxDialogComponent, IgxDialogTitleDirective, IgxDialogActionsDirective] }) class CustomTemplates1DialogComponent { - @ViewChild('dialog', { static: true }) public dialog: IgxDialogComponent; + @ViewChild('dialog', { static: true }) + public dialog: IgxDialogComponent; } @Component({ @@ -651,7 +660,8 @@ class CustomTemplates1DialogComponent { imports: [IgxDialogComponent, IgxDialogTitleDirective, IgxDialogActionsDirective] }) class CustomTemplates2DialogComponent { - @ViewChild('dialog', { static: true }) public dialog: IgxDialogComponent; + @ViewChild('dialog', { static: true }) + public dialog: IgxDialogComponent; } @@ -663,7 +673,8 @@ class CustomTemplates2DialogComponent { imports: [IgxDialogComponent] }) class PositionSettingsDialogComponent { - @ViewChild('dialog', { static: true }) public dialog: IgxDialogComponent; + @ViewChild('dialog', { static: true }) + public dialog: IgxDialogComponent; public positionSettings: PositionSettings = { horizontalDirection: HorizontalAlignment.Left, @@ -683,5 +694,4 @@ class PositionSettingsDialogComponent { openAnimation: useAnimation(slideInTop, { params: { duration: '800ms' } }), closeAnimation: useAnimation(slideOutBottom, { params: { duration: '700ms' } }) }; - } diff --git a/projects/igniteui-angular/directives/src/directives/button/button.directive.spec.ts b/projects/igniteui-angular/directives/src/directives/button/button.directive.spec.ts index bfceddb34f1..8c5b5c699ec 100644 --- a/projects/igniteui-angular/directives/src/directives/button/button.directive.spec.ts +++ b/projects/igniteui-angular/directives/src/directives/button/button.directive.spec.ts @@ -5,6 +5,7 @@ import { IgxButtonDirective } from './button.directive'; import { IgxRippleDirective } from '../ripple/ripple.directive'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const BUTTON_COMFORTABLE = 'igx-button'; @@ -87,7 +88,7 @@ describe('IgxButton', () => { const fixture = TestBed.createComponent(InitButtonComponent); fixture.detectChanges(); const button = fixture.componentInstance.button; - spyOn(button.buttonSelected, 'emit'); + vi.spyOn(button.buttonSelected, 'emit'); expect(button.buttonSelected.emit).not.toHaveBeenCalled(); diff --git a/projects/igniteui-angular/directives/src/directives/button/icon-button.directive.spec.ts b/projects/igniteui-angular/directives/src/directives/button/icon-button.directive.spec.ts index bcdf76e8910..eae55699bd1 100644 --- a/projects/igniteui-angular/directives/src/directives/button/icon-button.directive.spec.ts +++ b/projects/igniteui-angular/directives/src/directives/button/icon-button.directive.spec.ts @@ -5,6 +5,7 @@ import { IgxIconButtonDirective } from './icon-button.directive'; import { IgxRippleDirective } from '../ripple/ripple.directive'; import { By } from '@angular/platform-browser'; import { IgxIconComponent } from '../../../../icon/src/icon/icon.component'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('IgxIconButton', () => { diff --git a/projects/igniteui-angular/directives/src/directives/date-time-editor/date-time-editor.directive.spec.ts b/projects/igniteui-angular/directives/src/directives/date-time-editor/date-time-editor.directive.spec.ts index 410c0084e4b..2b195b846ce 100644 --- a/projects/igniteui-angular/directives/src/directives/date-time-editor/date-time-editor.directive.spec.ts +++ b/projects/igniteui-angular/directives/src/directives/date-time-editor/date-time-editor.directive.spec.ts @@ -1,3 +1,4 @@ +import type { MockedObject } from "vitest"; import { IgxDateTimeEditorDirective } from './date-time-editor.directive'; import { formatDate, registerLocaleData } from '@angular/common'; import { Component, ViewChild, DebugElement, EventEmitter, Output, SimpleChange, SimpleChanges, DOCUMENT, inject, Renderer2, ElementRef } from '@angular/core'; @@ -14,12 +15,13 @@ import localeBg from "@angular/common/locales/bg"; import { DatePart } from 'igniteui-angular/core'; import { MaskParsingService } from '../mask/mask-parsing.service'; import { removeUnicodeSpaces } from 'igniteui-angular/test-utils/helper-utils.spec'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxDateTimeEditor', () => { let dateTimeEditor: IgxDateTimeEditorDirective; describe('Unit tests', () => { - let maskParsingService: jasmine.SpyObj; - let renderer2: jasmine.SpyObj; + let maskParsingService: MockedObject; + let renderer2: MockedObject; let elementRef: ElementRef; let inputFormat: string; let displayFormat: string; @@ -37,10 +39,17 @@ describe('IgxDateTimeEditor', () => { beforeEach(() => { const mockNativeEl = document.createElement("div"); - (mockNativeEl as any).setSelectionRange = () => {}; - maskParsingService = jasmine.createSpyObj('MaskParsingService', - ['parseMask', 'restoreValueFromMask', 'parseMaskValue', 'applyMask', 'parseValueFromMask']); - renderer2 = jasmine.createSpyObj('Renderer2', ['setAttribute']); + (mockNativeEl as any).setSelectionRange = () => { }; + maskParsingService = { + parseMask: vi.fn().mockName("MaskParsingService.parseMask"), + restoreValueFromMask: vi.fn().mockName("MaskParsingService.restoreValueFromMask"), + parseMaskValue: vi.fn().mockName("MaskParsingService.parseMaskValue"), + applyMask: vi.fn().mockName("MaskParsingService.applyMask"), + parseValueFromMask: vi.fn().mockName("MaskParsingService.parseValueFromMask") + }; + renderer2 = { + setAttribute: vi.fn().mockName("Renderer2.setAttribute") + }; elementRef = { nativeElement: mockNativeEl }; TestBed.configureTestingModule({ @@ -63,8 +72,8 @@ describe('IgxDateTimeEditor', () => { const date = new Date(2000, 5, 6); dateTimeEditor.value = date; - spyOn(dateTimeEditor.valueChange, 'emit'); - spyOnProperty((dateTimeEditor as any), 'inputValue', 'get').and.returnValue(inputDate); + vi.spyOn(dateTimeEditor.valueChange, 'emit'); + vi.spyOn((dateTimeEditor as any), 'inputValue', 'get').mockReturnValue(inputDate); dateTimeEditor.clear(); expect(dateTimeEditor.value).toBeNull(); @@ -185,7 +194,7 @@ describe('IgxDateTimeEditor', () => { initializeDateTimeEditor(); dateTimeEditor.value = new Date(2015, 11, 12); - spyOnProperty((dateTimeEditor as any), 'inputValue', 'get').and.returnValue(inputDate); + vi.spyOn((dateTimeEditor as any), 'inputValue', 'get').mockReturnValue(inputDate); const date = dateTimeEditor.value.getDate(); const month = dateTimeEditor.value.getMonth(); @@ -203,7 +212,7 @@ describe('IgxDateTimeEditor', () => { initializeDateTimeEditor(); dateTimeEditor.value = new Date(2015, 11, 12); - spyOnProperty((dateTimeEditor as any), 'inputValue', 'get').and.returnValue(inputDate); + vi.spyOn((dateTimeEditor as any), 'inputValue', 'get').mockReturnValue(inputDate); const date = dateTimeEditor.value.getDate(); dateTimeEditor.increment(); @@ -222,7 +231,7 @@ describe('IgxDateTimeEditor', () => { const date = new Date(2015, 11, 12, 14, 35, 12); dateTimeEditor.value = date; dateTimeEditor.spinDelta = { date: 2, month: 2, year: 2, hours: 2, minutes: 2, seconds: 2 }; - spyOnProperty((dateTimeEditor as any), 'inputValue', 'get').and.returnValue(inputDate); + vi.spyOn((dateTimeEditor as any), 'inputValue', 'get').mockReturnValue(inputDate); dateTimeEditor.increment(); expect(dateTimeEditor.value.getDate()).toEqual(14); @@ -244,7 +253,7 @@ describe('IgxDateTimeEditor', () => { initializeDateTimeEditor(); dateTimeEditor.value = new Date(2020, 1, 29); - spyOnProperty((dateTimeEditor as any), 'inputValue', 'get').and.returnValue(inputDate); + vi.spyOn((dateTimeEditor as any), 'inputValue', 'get').mockReturnValue(inputDate); dateTimeEditor.increment(); expect(dateTimeEditor.value.getDate()).toEqual(1); @@ -258,7 +267,7 @@ describe('IgxDateTimeEditor', () => { initializeDateTimeEditor(); dateTimeEditor.value = new Date(2020, 11, 29); - spyOnProperty((dateTimeEditor as any), 'inputValue', 'get').and.returnValue(inputDate); + vi.spyOn((dateTimeEditor as any), 'inputValue', 'get').mockReturnValue(inputDate); dateTimeEditor.increment(DatePart.Month); expect(dateTimeEditor.value.getMonth()).toEqual(0); @@ -272,7 +281,7 @@ describe('IgxDateTimeEditor', () => { initializeDateTimeEditor(); dateTimeEditor.value = new Date(2020, 0, 31); - spyOnProperty((dateTimeEditor as any), 'inputValue', 'get').and.returnValue(inputDate); + vi.spyOn((dateTimeEditor as any), 'inputValue', 'get').mockReturnValue(inputDate); dateTimeEditor.increment(DatePart.Month); expect(dateTimeEditor.value.getDate()).toEqual(29); @@ -286,7 +295,7 @@ describe('IgxDateTimeEditor', () => { initializeDateTimeEditor(); dateTimeEditor.value = new Date(2020, 2, 11); - spyOnProperty((dateTimeEditor as any), 'inputValue', 'get').and.returnValue(inputDate); + vi.spyOn((dateTimeEditor as any), 'inputValue', 'get').mockReturnValue(inputDate); dateTimeEditor.increment(); expect(dateTimeEditor.value.getDate()).toEqual(12); @@ -303,7 +312,7 @@ describe('IgxDateTimeEditor', () => { dateTimeEditor.spinLoop = false; dateTimeEditor.value = new Date(2020, 2, 31); - spyOnProperty((dateTimeEditor as any), 'inputValue', 'get').and.returnValue(inputDate); + vi.spyOn((dateTimeEditor as any), 'inputValue', 'get').mockReturnValue(inputDate); dateTimeEditor.increment(DatePart.Date); expect(dateTimeEditor.value.getDate()).toEqual(31); @@ -320,7 +329,7 @@ describe('IgxDateTimeEditor', () => { initializeDateTimeEditor(); dateTimeEditor.value = new Date(2020, 2, 31); - spyOnProperty((dateTimeEditor as any), 'inputValue', 'get').and.returnValue(inputDate); + vi.spyOn((dateTimeEditor as any), 'inputValue', 'get').mockReturnValue(inputDate); dateTimeEditor.increment(DatePart.Date); expect(dateTimeEditor.value.getDate()).toEqual(1); @@ -338,7 +347,7 @@ describe('IgxDateTimeEditor', () => { initializeDateTimeEditor(); dateTimeEditor.value = new Date(2010, 11, 10, 12, 10, 34, 555); - spyOnProperty((dateTimeEditor as any), 'inputValue', 'get').and.returnValue(inputDate); + vi.spyOn((dateTimeEditor as any), 'inputValue', 'get').mockReturnValue(inputDate); const minutes = dateTimeEditor.value.getMinutes(); const seconds = dateTimeEditor.value.getSeconds(); const ms = dateTimeEditor.value.getMilliseconds(); @@ -364,7 +373,7 @@ describe('IgxDateTimeEditor', () => { */ // do not use new Date. This test will fail if run between 23:00 and 23:59 dateTimeEditor.value = new Date(1900, 1, 1, 12, 0, 0, 0); - spyOnProperty((dateTimeEditor as any), 'inputValue', 'get').and.returnValue(inputDate); + vi.spyOn((dateTimeEditor as any), 'inputValue', 'get').mockReturnValue(inputDate); const hours = dateTimeEditor.value.getHours(); dateTimeEditor.increment(); @@ -381,7 +390,7 @@ describe('IgxDateTimeEditor', () => { initializeDateTimeEditor(); dateTimeEditor.value = new Date(2019, 1, 20, 20, 5, 59); - spyOnProperty((dateTimeEditor as any), 'inputValue', 'get').and.returnValue(inputDate); + vi.spyOn((dateTimeEditor as any), 'inputValue', 'get').mockReturnValue(inputDate); dateTimeEditor.increment(DatePart.Seconds); expect(dateTimeEditor.value.getMinutes()).toEqual(5); @@ -395,7 +404,7 @@ describe('IgxDateTimeEditor', () => { initializeDateTimeEditor(); dateTimeEditor.value = new Date(2019, 1, 20, 20, 59, 12); - spyOnProperty((dateTimeEditor as any), 'inputValue', 'get').and.returnValue(inputDate); + vi.spyOn((dateTimeEditor as any), 'inputValue', 'get').mockReturnValue(inputDate); dateTimeEditor.increment(DatePart.Minutes); expect(dateTimeEditor.value.getHours()).toEqual(20); @@ -409,7 +418,7 @@ describe('IgxDateTimeEditor', () => { initializeDateTimeEditor(); dateTimeEditor.value = new Date(2019, 1, 20, 23, 13, 12); - spyOnProperty((dateTimeEditor as any), 'inputValue', 'get').and.returnValue(inputDate); + vi.spyOn((dateTimeEditor as any), 'inputValue', 'get').mockReturnValue(inputDate); dateTimeEditor.increment(DatePart.Hours); expect(dateTimeEditor.value.getDate()).toEqual(20); @@ -423,7 +432,7 @@ describe('IgxDateTimeEditor', () => { initializeDateTimeEditor(); dateTimeEditor.spinLoop = false; dateTimeEditor.value = new Date(2019, 1, 20, 23, 0, 12); - spyOnProperty((dateTimeEditor as any), 'inputValue', 'get').and.returnValue(inputDate); + vi.spyOn((dateTimeEditor as any), 'inputValue', 'get').mockReturnValue(inputDate); dateTimeEditor.increment(DatePart.Hours); expect(dateTimeEditor.value.getHours()).toEqual(23); @@ -439,7 +448,7 @@ describe('IgxDateTimeEditor', () => { initializeDateTimeEditor(); dateTimeEditor.value = new Date(2019, 1, 20, 23, 15, 0); - spyOnProperty((dateTimeEditor as any), 'inputValue', 'get').and.returnValue(inputDate); + vi.spyOn((dateTimeEditor as any), 'inputValue', 'get').mockReturnValue(inputDate); dateTimeEditor.increment(DatePart.Hours); expect(dateTimeEditor.value.getHours()).toEqual(0); @@ -458,7 +467,7 @@ describe('IgxDateTimeEditor', () => { expect(dateTimeEditor.mask).toEqual('00 LL 0000-00 00-00-00'); dateTimeEditor.value = new Date(2020, 5, 12, 11, 15, 14); - spyOnProperty((dateTimeEditor as any), 'inputValue', 'get').and.returnValue(inputDate); + vi.spyOn((dateTimeEditor as any), 'inputValue', 'get').mockReturnValue(inputDate); dateTimeEditor.increment(DatePart.AmPm); expect(dateTimeEditor.value).toEqual(new Date(2020, 5, 12, 23, 15, 14)); @@ -1010,7 +1019,7 @@ describe('IgxDateTimeEditor', () => { expect(inputElement.nativeElement.value).toEqual('../../.... ..:..:..:...'); }); it('should be en/disabled when the input is en/disabled.', fakeAsync(() => { - spyOn(dateTimeEditorDirective, 'setDisabledState'); + vi.spyOn(dateTimeEditorDirective, 'setDisabledState'); fixture.componentInstance.disabled = true; fixture.detectChanges(); tick(); @@ -1027,7 +1036,7 @@ describe('IgxDateTimeEditor', () => { const newDate = new Date(2004, 11, 18); fixture.componentInstance.dateTimeFormat = 'dd/MM/yy'; fixture.detectChanges(); - spyOn(dateTimeEditorDirective.valueChange, 'emit'); + vi.spyOn(dateTimeEditorDirective.valueChange, 'emit'); inputElement.triggerEventHandler('focus', {}); fixture.detectChanges(); @@ -1045,7 +1054,7 @@ describe('IgxDateTimeEditor', () => { const newDate = new Date(2012, 11, 12); fixture.componentInstance.dateTimeFormat = 'dd/MM/yy'; fixture.detectChanges(); - spyOn(dateTimeEditorDirective.valueChange, 'emit'); + vi.spyOn(dateTimeEditorDirective.valueChange, 'emit'); inputElement.triggerEventHandler('focus', {}); fixture.detectChanges(); UIInteractions.simulateTyping('121212', inputElement); @@ -1058,7 +1067,7 @@ describe('IgxDateTimeEditor', () => { fixture.componentInstance.minDate = new Date(2020, 1, 20); fixture.componentInstance.maxDate = new Date(2020, 1, 25); fixture.detectChanges(); - spyOn(dateTimeEditorDirective.validationFailed, 'emit'); + vi.spyOn(dateTimeEditorDirective.validationFailed, 'emit'); // date within the range let inputDate = '22-02-2020'; @@ -1103,7 +1112,7 @@ describe('IgxDateTimeEditor', () => { fixture.componentInstance.minDate = new Date(2000, 1, 1); fixture.componentInstance.maxDate = new Date(2050, 1, 25); fixture.detectChanges(); - spyOn(dateTimeEditorDirective.validationFailed, 'emit').and.callThrough(); + vi.spyOn(dateTimeEditorDirective.validationFailed, 'emit'); // valid date let inputDate = '22-02-2020'; @@ -1320,7 +1329,7 @@ describe('IgxDateTimeEditor', () => { dateTimeEditorDirective = inputElement.injector.get(IgxDateTimeEditorDirective); }); it('should validate properly when used as form control.', () => { - spyOn(dateTimeEditorDirective.validationFailed, 'emit').and.callThrough(); + vi.spyOn(dateTimeEditorDirective.validationFailed, 'emit'); const dateEditor = form.controls['dateEditor']; const inputDate = '99-99-9999'; @@ -1340,7 +1349,7 @@ describe('IgxDateTimeEditor', () => { it('should validate properly min/max value when used as form control.', () => { fixture.componentInstance.minDate = new Date(2020, 2, 20); fixture.componentInstance.maxDate = new Date(2020, 2, 25); - spyOn(dateTimeEditorDirective.validationFailed, 'emit'); + vi.spyOn(dateTimeEditorDirective.validationFailed, 'emit'); const dateEditor = form.controls['dateEditor']; let inputDate = '21-03-2020'; @@ -1416,7 +1425,8 @@ export class IgxDateTimeEditorBaseTestComponent { imports: [IgxInputGroupComponent, IgxInputDirective, IgxDateTimeEditorDirective, FormsModule] }) export class IgxDateTimeEditorSampleComponent { - @ViewChild('igxInputGroup', { static: true }) public igxInputGroup: IgxInputGroupComponent; + @ViewChild('igxInputGroup', { static: true }) + public igxInputGroup: IgxInputGroupComponent; public date: Date; public dateTimeFormat = 'dd/MM/yyyy HH:mm:ss:SSS'; public displayFormat: string; diff --git a/projects/igniteui-angular/directives/src/directives/divider/divider.spec.ts b/projects/igniteui-angular/directives/src/directives/divider/divider.spec.ts index 3c6eaa204ce..232d8292d4c 100644 --- a/projects/igniteui-angular/directives/src/directives/divider/divider.spec.ts +++ b/projects/igniteui-angular/directives/src/directives/divider/divider.spec.ts @@ -3,6 +3,7 @@ import { TestBed, ComponentFixture, waitForAsync } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { IgxDividerDirective, IgxDividerType } from './divider.directive'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Divider', () => { const baseClass = 'igx-divider'; @@ -31,7 +32,7 @@ describe('Divider', () => { fixture.detectChanges(); expect(divider.nativeElement).toBeDefined(); - expect(divider.nativeElement).toHaveClass(baseClass); + expect(divider.nativeElement.classList.contains(baseClass)).toBe(true); }); it('should initialize dashed divider', () => { @@ -39,8 +40,8 @@ describe('Divider', () => { fixture.componentInstance.type = IgxDividerType.DASHED; fixture.detectChanges(); - expect(divider.nativeElement).toHaveClass(baseClass); - expect(divider.nativeElement).toHaveClass(classes.dashed); + expect(divider.nativeElement.classList.contains(baseClass)).toBe(true); + expect(divider.nativeElement.classList.contains(classes.dashed)).toBe(true); }); it('should initialize vertical divider', () => { @@ -48,7 +49,7 @@ describe('Divider', () => { fixture.componentInstance.vertical = true; fixture.detectChanges(); - expect(divider.nativeElement).toHaveClass(classes.vertical); + expect(divider.nativeElement.classList.contains(classes.vertical)).toBe(true); }); it('should initialize middle divider', () => { @@ -56,8 +57,8 @@ describe('Divider', () => { fixture.componentInstance.middle = true; fixture.detectChanges(); - expect(divider.nativeElement).not.toHaveClass(classes.vertical); - expect(divider.nativeElement).toHaveClass(classes.inset); + expect(divider.nativeElement.classList.contains(classes.vertical)).toBe(false); + expect(divider.nativeElement.classList.contains(classes.inset)).toBe(true); }); it('should initialize middle, vertical divider', () => { @@ -66,8 +67,8 @@ describe('Divider', () => { fixture.componentInstance.middle = true; fixture.detectChanges(); - expect(divider.nativeElement).toHaveClass(classes.vertical); - expect(divider.nativeElement).toHaveClass(classes.inset); + expect(divider.nativeElement.classList.contains(classes.vertical)).toBe(true); + expect(divider.nativeElement.classList.contains(classes.inset)).toBe(true); }); it('should inset the divider by the specified amount', () => { diff --git a/projects/igniteui-angular/directives/src/directives/drag-drop/drag-drop.spec.ts b/projects/igniteui-angular/directives/src/directives/drag-drop/drag-drop.spec.ts index ba3fd6937b1..ddcd2c9dc33 100644 --- a/projects/igniteui-angular/directives/src/directives/drag-drop/drag-drop.spec.ts +++ b/projects/igniteui-angular/directives/src/directives/drag-drop/drag-drop.spec.ts @@ -1,31 +1,24 @@ import { Component, ViewChildren, QueryList, ViewChild, ElementRef, TemplateRef, Renderer2, inject } from '@angular/core'; import { TestBed, ComponentFixture, waitForAsync } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; -import { UIInteractions, wait} from '../../../../test-utils/ui-interactions.spec'; +import { UIInteractions, wait } from '../../../../test-utils/ui-interactions.spec'; import { first } from 'rxjs/operators'; import { IgxInsertDropStrategy, IgxAppendDropStrategy, IgxPrependDropStrategy } from './drag-drop.strategy'; -import { - IgxDragDirective, - IgxDropDirective, - IgxDragLocation, - IDropDroppedEventArgs, - DragDirection, - IgxDragHandleDirective, - IgxDragIgnoreDirective -} from './drag-drop.directive'; +import { IgxDragDirective, IgxDropDirective, IgxDragLocation, IDropDroppedEventArgs, DragDirection, IgxDragHandleDirective, IgxDragIgnoreDirective } from './drag-drop.directive'; import { IgxIconComponent } from '../../../../icon/src/icon/icon.component'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; describe('General igxDrag/igxDrop', () => { let fix: ComponentFixture; let dropArea: IgxDropDirective; - let dropAreaRects = { top: 0, left: 0, right: 0, bottom: 0}; - let dragDirsRects = [{ top: 0, left: 0, right: 0, bottom: 0}]; + let dropAreaRects = { top: 0, left: 0, right: 0, bottom: 0 }; + let dragDirsRects = [{ top: 0, left: 0, right: 0, bottom: 0 }]; beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [TestDragDropComponent] }) - .compileComponents(); + .compileComponents(); })); beforeEach(() => { @@ -61,8 +54,8 @@ describe('General igxDrag/igxDrop', () => { const startingX = (dragDirsRects[0].left + dragDirsRects[0].right) / 2; const startingY = (dragDirsRects[0].top + dragDirsRects[0].bottom) / 2; - spyOn(firstDrag.ghostCreate, 'emit'); - spyOn(firstDrag.ghostDestroy, 'emit'); + vi.spyOn(firstDrag.ghostCreate, 'emit'); + vi.spyOn(firstDrag.ghostDestroy, 'emit'); expect(document.getElementsByClassName('dragElem').length).toEqual(3); // Step 1. @@ -103,9 +96,9 @@ describe('General igxDrag/igxDrop', () => { const startingX = (dragDirsRects[0].left + dragDirsRects[0].right) / 2; const startingY = (dragDirsRects[0].top + dragDirsRects[0].bottom) / 2; - spyOn(firstDrag.dragStart, 'emit'); - spyOn(firstDrag.dragMove, 'emit'); - spyOn(firstDrag.dragEnd, 'emit'); + vi.spyOn(firstDrag.dragStart, 'emit'); + vi.spyOn(firstDrag.dragMove, 'emit'); + vi.spyOn(firstDrag.dragEnd, 'emit'); // Step 1. UIInteractions.simulatePointerEvent('pointerdown', firstElement, startingX, startingY); @@ -151,9 +144,9 @@ describe('General igxDrag/igxDrop', () => { const startingX = (dragDirsRects[0].left + dragDirsRects[0].right) / 2; const startingY = (dragDirsRects[0].top + dragDirsRects[0].bottom) / 2; - spyOn(firstDrag.dragStart, 'emit'); - spyOn(firstDrag.dragMove, 'emit'); - spyOn(firstDrag.dragEnd, 'emit'); + vi.spyOn(firstDrag.dragStart, 'emit'); + vi.spyOn(firstDrag.dragMove, 'emit'); + vi.spyOn(firstDrag.dragEnd, 'emit'); // Step 1. UIInteractions.simulatePointerEvent('pointerdown', firstElement, startingX, startingY); @@ -200,9 +193,9 @@ describe('General igxDrag/igxDrop', () => { const startingY = (dragDirsRects[0].top + dragDirsRects[0].bottom) / 2; firstDrag.dragTolerance = 15; - spyOn(firstDrag.ghostCreate, 'emit'); - spyOn(firstDrag.ghostDestroy, 'emit'); - spyOn(firstDrag.dragClick, 'emit'); + vi.spyOn(firstDrag.ghostCreate, 'emit'); + vi.spyOn(firstDrag.ghostDestroy, 'emit'); + vi.spyOn(firstDrag.dragClick, 'emit'); expect(document.getElementsByClassName('dragElem').length).toEqual(3); // Step 1. @@ -537,9 +530,9 @@ describe('General igxDrag/igxDrop', () => { const startingY = (dragDirsRects[0].top + dragDirsRects[0].bottom) / 2; firstDrag.ghost = false; - spyOn(firstDrag.dragStart, 'emit'); - spyOn(firstDrag.dragMove, 'emit'); - spyOn(firstDrag.dragEnd, 'emit'); + vi.spyOn(firstDrag.dragStart, 'emit'); + vi.spyOn(firstDrag.dragMove, 'emit'); + vi.spyOn(firstDrag.dragEnd, 'emit'); // Step 1. UIInteractions.simulatePointerEvent('pointerdown', firstElement, startingX, startingY); @@ -676,8 +669,8 @@ describe('General igxDrag/igxDrop', () => { firstDrag.ghost = false; firstDrag.dragTolerance = 25; - spyOn(firstDrag.dragStart, 'emit'); - spyOn(firstDrag.dragClick, 'emit'); + vi.spyOn(firstDrag.dragStart, 'emit'); + vi.spyOn(firstDrag.dragClick, 'emit'); // Step 1. UIInteractions.simulatePointerEvent('pointerdown', firstElement, startingX, startingY); @@ -727,7 +720,7 @@ describe('General igxDrag/igxDrop', () => { firstDrag.ghost = false; firstDrag.dragTolerance = 0; - spyOn(firstDrag.dragStart, 'emit'); + vi.spyOn(firstDrag.dragStart, 'emit'); // Step 1. UIInteractions.simulatePointerEvent('pointerdown', firstElement, startingX, startingY); @@ -846,7 +839,7 @@ describe('General igxDrag/igxDrop', () => { expect(firstElement.getBoundingClientRect().left).toEqual(dragDirsRects[0].left + 20); expect(firstElement.getBoundingClientRect().top).toEqual(dragDirsRects[0].top + 20); - firstDrag.setLocation(new IgxDragLocation(initialPageX, initialPageY)); + firstDrag.setLocation(new IgxDragLocation(initialPageX, initialPageY)); expect(firstElement.getBoundingClientRect().left).toEqual(dragDirsRects[0].left); expect(firstElement.getBoundingClientRect().top).toEqual(dragDirsRects[0].top); @@ -882,7 +875,7 @@ describe('General igxDrag/igxDrop', () => { fix.detectChanges(); await wait(100); - firstDrag.setLocation(new IgxDragLocation(initialPageX, initialPageY)); + firstDrag.setLocation(new IgxDragLocation(initialPageX, initialPageY)); fix.detectChanges(); await wait(100); @@ -906,7 +899,7 @@ describe('General igxDrag/igxDrop', () => { thirdDrag.ghost = false; thirdDrag.dragTolerance = 0; - spyOn(thirdDrag.dragStart, 'emit'); + vi.spyOn(thirdDrag.dragStart, 'emit'); // Check if drag element itself is not draggable. UIInteractions.simulatePointerEvent('pointerdown', thirdElement, startingX, startingY); @@ -965,9 +958,9 @@ describe('General igxDrag/igxDrop', () => { const startingX = (dragDirsRects[0].left + dragDirsRects[0].right) / 2; const startingY = (dragDirsRects[0].top + dragDirsRects[0].bottom) / 2; - spyOn(dropArea.enter, 'emit'); - spyOn(dropArea.leave, 'emit'); - spyOn(dropArea.dropped, 'emit'); + vi.spyOn(dropArea.enter, 'emit'); + vi.spyOn(dropArea.leave, 'emit'); + vi.spyOn(dropArea.dropped, 'emit'); UIInteractions.simulatePointerEvent('pointerdown', firstElement, startingX, startingY); fix.detectChanges(); @@ -980,11 +973,7 @@ describe('General igxDrag/igxDrop', () => { fix.detectChanges(); await wait(); - const event = UIInteractions.simulatePointerEvent('pointermove', - firstDrag.ghostElement, - dropAreaRects.left + 100, - dropAreaRects.top + 5 - ); + const event = UIInteractions.simulatePointerEvent('pointermove', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 5); fix.detectChanges(); await wait(100); @@ -995,18 +984,14 @@ describe('General igxDrag/igxDrop', () => { dragData: firstDrag.data, startX: startingX, startY: startingY, - pageX: dropAreaRects.left + 100, - pageY: dropAreaRects.top + 5, + pageX: dropAreaRects.left + 100, + pageY: dropAreaRects.top + 5, offsetX: 100, offsetY: 5 }); // We need to trigger the pointerup on the ghostElement because this is the element we move and is under the mouse - const eventUp = UIInteractions.simulatePointerEvent('pointerup', - firstDrag.ghostElement, - dropAreaRects.left + 100, - dropAreaRects.top + 20 - ); + const eventUp = UIInteractions.simulatePointerEvent('pointerup', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 20); fix.detectChanges(); await wait(); @@ -1017,8 +1002,8 @@ describe('General igxDrag/igxDrop', () => { dragData: firstDrag.data, startX: startingX, startY: startingY, - pageX: dropAreaRects.left + 100, - pageY: dropAreaRects.top + 20, + pageX: dropAreaRects.left + 100, + pageY: dropAreaRects.top + 20, offsetX: 100, offsetY: 20, cancel: false @@ -1030,8 +1015,8 @@ describe('General igxDrag/igxDrop', () => { dragData: firstDrag.data, startX: startingX, startY: startingY, - pageX: dropAreaRects.left + 100, - pageY: dropAreaRects.top + 20, + pageX: dropAreaRects.left + 100, + pageY: dropAreaRects.top + 20, offsetX: 100, offsetY: 20 }); @@ -1151,7 +1136,7 @@ describe('General igxDrag/igxDrop', () => { it('should not create ghost element when executing transitionToOrigin() when no dragging is performed without start.', async () => { const firstDrag = fix.componentInstance.dragElems.first; - spyOn(firstDrag.transitioned, 'emit'); + vi.spyOn(firstDrag.transitioned, 'emit'); expect(firstDrag.ghostElement).not.toBeTruthy(); @@ -1228,11 +1213,7 @@ describe('General igxDrag/igxDrop', () => { expect(firstDrag.element.nativeElement.getBoundingClientRect().left).toEqual(dragDirsRects[0].left); expect(firstDrag.element.nativeElement.getBoundingClientRect().top).toEqual(dragDirsRects[0].top); - firstDrag.transitionTo( - new IgxDragLocation(dragDirsRects[0].left + 50, dragDirsRects[0].top + 50), - {}, - new IgxDragLocation(dragDirsRects[0].left + 100, dragDirsRects[0].top + 100) - ); + firstDrag.transitionTo(new IgxDragLocation(dragDirsRects[0].left + 50, dragDirsRects[0].top + 50), {}, new IgxDragLocation(dragDirsRects[0].left + 100, dragDirsRects[0].top + 100)); await wait(); const currLeft = firstDrag.element.nativeElement.getBoundingClientRect().left; @@ -1308,11 +1289,7 @@ describe('General igxDrag/igxDrop', () => { const startingY = (dragDirsRects[0].top + dragDirsRects[0].bottom) / 2; firstDrag.dragEnd.pipe(first()).subscribe(() => { - firstDrag.transitionTo( - new IgxDragLocation(dragDirsRects[0].left + 50, dragDirsRects[0].top + 50), - {}, - new IgxDragLocation(dragDirsRects[0].left + 100, dragDirsRects[0].top + 100) - ); + firstDrag.transitionTo(new IgxDragLocation(dragDirsRects[0].left + 50, dragDirsRects[0].top + 50), {}, new IgxDragLocation(dragDirsRects[0].left + 100, dragDirsRects[0].top + 100)); }); firstDrag.transitioned.pipe(first()).subscribe(() => { @@ -1368,11 +1345,7 @@ describe('General igxDrag/igxDrop', () => { expect(firstDrag.ghostElement).not.toBeTruthy(); - firstDrag.transitionTo( - new IgxDragLocation(dragDirsRects[0].left + 50, dragDirsRects[0].top + 50), - {}, - new IgxDragLocation(dragDirsRects[0].left + 100, dragDirsRects[0].top + 100) - ); + firstDrag.transitionTo(new IgxDragLocation(dragDirsRects[0].left + 50, dragDirsRects[0].top + 50), {}, new IgxDragLocation(dragDirsRects[0].left + 100, dragDirsRects[0].top + 100)); await wait(); expect(firstDrag.ghostElement).toBeTruthy(); @@ -1399,7 +1372,7 @@ describe('Linked igxDrag/igxDrop ', () => { TestDragDropStrategiesComponent ] }) - .compileComponents(); + .compileComponents(); })); it('should trigger enter/onDrop/leave events when element is dropped inside and is linked with it.', async () => { @@ -1416,9 +1389,9 @@ describe('Linked igxDrag/igxDrop ', () => { const dropArea = fix.componentInstance.dropArea; const dropAreaRects = getElemRects(dropArea.element.nativeElement); - spyOn(dropArea.enter, 'emit'); - spyOn(dropArea.leave, 'emit'); - spyOn(dropArea.dropped, 'emit'); + vi.spyOn(dropArea.enter, 'emit'); + vi.spyOn(dropArea.leave, 'emit'); + vi.spyOn(dropArea.dropped, 'emit'); UIInteractions.simulatePointerEvent('pointerdown', firstElement, startingX, startingY); fix.detectChanges(); @@ -1431,13 +1404,13 @@ describe('Linked igxDrag/igxDrop ', () => { fix.detectChanges(); await wait(100); - UIInteractions.simulatePointerEvent('pointermove', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 5); + UIInteractions.simulatePointerEvent('pointermove', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 5); await wait(100); expect(dropArea.enter.emit).toHaveBeenCalled(); // We need to trigger the pointerup on the ghostElement because this is the element we move and is under the mouse - UIInteractions.simulatePointerEvent('pointerup', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 20 ); + UIInteractions.simulatePointerEvent('pointerup', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 20); await wait(); expect(dropArea.dropped.emit).toHaveBeenCalled(); @@ -1459,9 +1432,9 @@ describe('Linked igxDrag/igxDrop ', () => { const dropArea = fix.componentInstance.dropArea; const dropAreaRects = getElemRects(dropArea.element.nativeElement); - spyOn(dropArea.enter, 'emit'); - spyOn(dropArea.leave, 'emit'); - spyOn(dropArea.dropped, 'emit'); + vi.spyOn(dropArea.enter, 'emit'); + vi.spyOn(dropArea.leave, 'emit'); + vi.spyOn(dropArea.dropped, 'emit'); UIInteractions.simulatePointerEvent('pointerdown', firstElement, startingX, startingY); fix.detectChanges(); @@ -1474,13 +1447,13 @@ describe('Linked igxDrag/igxDrop ', () => { fix.detectChanges(); await wait(100); - UIInteractions.simulatePointerEvent('pointermove', secondDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 5); + UIInteractions.simulatePointerEvent('pointermove', secondDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 5); await wait(100); expect(dropArea.enter.emit).not.toHaveBeenCalled(); // We need to trigger the pointerup on the ghostElement because this is the element we move and is under the mouse - UIInteractions.simulatePointerEvent('pointerup', secondDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 20 ); + UIInteractions.simulatePointerEvent('pointerup', secondDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 20); await wait(); expect(dropArea.dropped.emit).not.toHaveBeenCalled(); @@ -1503,9 +1476,9 @@ describe('Linked igxDrag/igxDrop ', () => { const dropArea = fix.componentInstance.dropArea; const dropAreaRects = getElemRects(dropArea.element.nativeElement); - spyOn(dropArea.enter, 'emit'); - spyOn(dropArea.leave, 'emit'); - spyOn(dropArea.dropped, 'emit'); + vi.spyOn(dropArea.enter, 'emit'); + vi.spyOn(dropArea.leave, 'emit'); + vi.spyOn(dropArea.dropped, 'emit'); UIInteractions.simulatePointerEvent('pointerdown', firstElement, startingX, startingY); fix.detectChanges(); @@ -1518,13 +1491,13 @@ describe('Linked igxDrag/igxDrop ', () => { fix.detectChanges(); await wait(100); - UIInteractions.simulatePointerEvent('pointermove', secondDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 5); + UIInteractions.simulatePointerEvent('pointermove', secondDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 5); await wait(100); expect(dropArea.enter.emit).not.toHaveBeenCalled(); // We need to trigger the pointerup on the ghostElement because this is the element we move and is under the mouse - UIInteractions.simulatePointerEvent('pointerup', secondDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 20 ); + UIInteractions.simulatePointerEvent('pointerup', secondDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 20); await wait(); expect(dropArea.dropped.emit).not.toHaveBeenCalled(); @@ -1546,9 +1519,9 @@ describe('Linked igxDrag/igxDrop ', () => { const dropArea = fix.componentInstance.dropArea; const dropAreaRects = getElemRects(dropArea.element.nativeElement); - spyOn(dropArea.enter, 'emit'); - spyOn(dropArea.leave, 'emit'); - spyOn(dropArea.dropped, 'emit'); + vi.spyOn(dropArea.enter, 'emit'); + vi.spyOn(dropArea.leave, 'emit'); + vi.spyOn(dropArea.dropped, 'emit'); UIInteractions.simulatePointerEvent('pointerdown', firstElement, startingX, startingY); fix.detectChanges(); @@ -1561,13 +1534,13 @@ describe('Linked igxDrag/igxDrop ', () => { fix.detectChanges(); await wait(100); - UIInteractions.simulatePointerEvent('pointermove', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 5); + UIInteractions.simulatePointerEvent('pointermove', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 5); await wait(100); expect(dropArea.enter.emit).toHaveBeenCalled(); // We need to trigger the pointerup on the ghostElement because this is the element we move and is under the mouse - UIInteractions.simulatePointerEvent('pointerup', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 20 ); + UIInteractions.simulatePointerEvent('pointerup', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 20); await wait(); expect(dropArea.dropped.emit).toHaveBeenCalled(); @@ -1594,9 +1567,9 @@ describe('Linked igxDrag/igxDrop ', () => { const dropArea = fix.componentInstance.dropArea; const dropAreaRects = getElemRects(dropArea.element.nativeElement); - spyOn(dropArea.enter, 'emit'); - spyOn(dropArea.leave, 'emit'); - spyOn(dropArea.dropped, 'emit'); + vi.spyOn(dropArea.enter, 'emit'); + vi.spyOn(dropArea.leave, 'emit'); + vi.spyOn(dropArea.dropped, 'emit'); UIInteractions.simulatePointerEvent('pointerdown', firstElement, startingX, startingY); fix.detectChanges(); @@ -1609,13 +1582,13 @@ describe('Linked igxDrag/igxDrop ', () => { fix.detectChanges(); await wait(100); - UIInteractions.simulatePointerEvent('pointermove', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 5); + UIInteractions.simulatePointerEvent('pointermove', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 5); await wait(100); expect(dropArea.enter.emit).toHaveBeenCalled(); // We need to trigger the pointerup on the ghostElement because this is the element we move and is under the mouse - UIInteractions.simulatePointerEvent('pointerup', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 20 ); + UIInteractions.simulatePointerEvent('pointerup', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 20); await wait(); expect(dropArea.dropped.emit).toHaveBeenCalled(); @@ -1640,9 +1613,9 @@ describe('Linked igxDrag/igxDrop ', () => { const dropArea = fix.componentInstance.dropArea; const dropAreaRects = getElemRects(dropArea.element.nativeElement); - spyOn(dropArea.enter, 'emit'); - spyOn(dropArea.leave, 'emit'); - spyOn(dropArea.dropped, 'emit'); + vi.spyOn(dropArea.enter, 'emit'); + vi.spyOn(dropArea.leave, 'emit'); + vi.spyOn(dropArea.dropped, 'emit'); UIInteractions.simulatePointerEvent('pointerdown', firstElement, startingX, startingY); fix.detectChanges(); @@ -1655,13 +1628,13 @@ describe('Linked igxDrag/igxDrop ', () => { fix.detectChanges(); await wait(100); - UIInteractions.simulatePointerEvent('pointermove', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 5); + UIInteractions.simulatePointerEvent('pointermove', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 5); await wait(100); expect(dropArea.enter.emit).toHaveBeenCalled(); // We need to trigger the pointerup on the ghostElement because this is the element we move and is under the mouse - UIInteractions.simulatePointerEvent('pointerup', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 20 ); + UIInteractions.simulatePointerEvent('pointerup', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 20); await wait(); expect(dropArea.dropped.emit).toHaveBeenCalled(); @@ -1687,9 +1660,9 @@ describe('Linked igxDrag/igxDrop ', () => { const dropArea = fix.componentInstance.dropArea; const dropAreaRects = getElemRects(dropArea.element.nativeElement); - spyOn(dropArea.enter, 'emit'); - spyOn(dropArea.leave, 'emit'); - spyOn(dropArea.dropped, 'emit'); + vi.spyOn(dropArea.enter, 'emit'); + vi.spyOn(dropArea.leave, 'emit'); + vi.spyOn(dropArea.dropped, 'emit'); UIInteractions.simulatePointerEvent('pointerdown', firstElement, startingX, startingY); fix.detectChanges(); @@ -1702,13 +1675,13 @@ describe('Linked igxDrag/igxDrop ', () => { fix.detectChanges(); await wait(100); - UIInteractions.simulatePointerEvent('pointermove', firstDrag.ghostElement, dropAreaRects.left + 150, dropAreaRects.top + 5); + UIInteractions.simulatePointerEvent('pointermove', firstDrag.ghostElement, dropAreaRects.left + 150, dropAreaRects.top + 5); await wait(100); expect(dropArea.enter.emit).toHaveBeenCalled(); // We need to trigger the pointerup on the ghostElement because this is the element we move and is under the mouse - UIInteractions.simulatePointerEvent('pointerup', firstDrag.ghostElement, dropAreaRects.left + 150, dropAreaRects.top + 20 ); + UIInteractions.simulatePointerEvent('pointerup', firstDrag.ghostElement, dropAreaRects.left + 150, dropAreaRects.top + 20); await wait(); expect(dropArea.dropped.emit).toHaveBeenCalled(); @@ -1733,8 +1706,8 @@ describe('Linked igxDrag/igxDrop ', () => { const dropArea = fix.componentInstance.dropArea; const dropAreaRects = getElemRects(dropArea.element.nativeElement); - spyOn(dropArea.enter, 'emit'); - spyOn(dropArea.leave, 'emit'); + vi.spyOn(dropArea.enter, 'emit'); + vi.spyOn(dropArea.leave, 'emit'); fix.componentInstance.dropArea.dropped.pipe(first()).subscribe(((e: IDropDroppedEventArgs) => e.cancel = true)); @@ -1749,17 +1722,13 @@ describe('Linked igxDrag/igxDrop ', () => { fix.detectChanges(); await wait(100); - UIInteractions.simulatePointerEvent('pointermove', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 5); + UIInteractions.simulatePointerEvent('pointermove', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 5); await wait(100); expect(dropArea.enter.emit).toHaveBeenCalled(); // We need to trigger the pointerup on the ghostElement because this is the element we move and is under the mouse - UIInteractions.simulatePointerEvent('pointerup', - firstDrag.ghostElement, - dropAreaRects.left + 100, - dropAreaRects.top + 20 - ); + UIInteractions.simulatePointerEvent('pointerup', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 20); fix.detectChanges(); await wait(100); @@ -1790,9 +1759,9 @@ describe('Linked igxDrag/igxDrop ', () => { const dropArea = fix.componentInstance.dropArea; const dropAreaRects = getElemRects(dropArea.element.nativeElement); - spyOn(dropArea.enter, 'emit'); - spyOn(dropArea.leave, 'emit'); - spyOn(dropArea.dropped, 'emit'); + vi.spyOn(dropArea.enter, 'emit'); + vi.spyOn(dropArea.leave, 'emit'); + vi.spyOn(dropArea.dropped, 'emit'); UIInteractions.simulatePointerEvent('pointerdown', firstElement, startingX, startingY); fix.detectChanges(); @@ -1805,13 +1774,13 @@ describe('Linked igxDrag/igxDrop ', () => { fix.detectChanges(); await wait(100); - UIInteractions.simulatePointerEvent('pointermove', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 5); + UIInteractions.simulatePointerEvent('pointermove', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 5); await wait(100); expect(dropArea.enter.emit).toHaveBeenCalled(); // We need to trigger the pointerup on the ghostElement because this is the element we move and is under the mouse - UIInteractions.simulatePointerEvent('pointerup', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 20 ); + UIInteractions.simulatePointerEvent('pointerup', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 20); await wait(); expect(dropArea.dropped.emit).toHaveBeenCalled(); @@ -1839,9 +1808,9 @@ describe('Linked igxDrag/igxDrop ', () => { const dropArea = fix.componentInstance.dropArea; const dropAreaRects = getElemRects(dropArea.element.nativeElement); - spyOn(dropArea.enter, 'emit'); - spyOn(dropArea.leave, 'emit'); - spyOn(dropArea.dropped, 'emit'); + vi.spyOn(dropArea.enter, 'emit'); + vi.spyOn(dropArea.leave, 'emit'); + vi.spyOn(dropArea.dropped, 'emit'); UIInteractions.simulatePointerEvent('pointerdown', firstElement, startingX, startingY); fix.detectChanges(); @@ -1854,13 +1823,13 @@ describe('Linked igxDrag/igxDrop ', () => { fix.detectChanges(); await wait(100); - UIInteractions.simulatePointerEvent('pointermove', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 5); + UIInteractions.simulatePointerEvent('pointermove', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 5); await wait(100); expect(dropArea.enter.emit).toHaveBeenCalled(); // We need to trigger the pointerup on the ghostElement because this is the element we move and is under the mouse - UIInteractions.simulatePointerEvent('pointerup', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 20 ); + UIInteractions.simulatePointerEvent('pointerup', firstDrag.ghostElement, dropAreaRects.left + 100, dropAreaRects.top + 20); await wait(); expect(dropArea.dropped.emit).toHaveBeenCalled(); @@ -1877,7 +1846,7 @@ describe('Nested igxDrag elements', () => { TestBed.configureTestingModule({ imports: [TestDragDropNestedComponent] }) - .compileComponents(); + .compileComponents(); })); it('should correctly move nested element using drag handle.', async () => { @@ -1892,9 +1861,9 @@ describe('Nested igxDrag elements', () => { firstMovie.ghost = false; firstMovie.dragTolerance = 0; - spyOn(rootList.dragStart, 'emit'); - spyOn(firstCategory.dragStart, 'emit'); - spyOn(firstMovie.dragStart, 'emit'); + vi.spyOn(rootList.dragStart, 'emit'); + vi.spyOn(firstCategory.dragStart, 'emit'); + vi.spyOn(firstMovie.dragStart, 'emit'); const dragHandle = thirdElement.children[0].children[0]; const dragHandleRects = dragHandle.getBoundingClientRect(); @@ -1922,7 +1891,7 @@ describe('Nested igxDrag elements', () => { expect(rootList.dragStart.emit).not.toHaveBeenCalled(); expect(firstCategory.dragStart.emit).not.toHaveBeenCalled(); }); -}) +}); const getDragDirsRects = (dragDirs: QueryList) => { const dragDirsRects = []; @@ -2059,7 +2028,8 @@ class TestDragDropComponent { `, imports: [IgxDragDirective, IgxDropDirective] }) -class TestDragDropLinkedSingleComponent extends TestDragDropComponent { } +class TestDragDropLinkedSingleComponent extends TestDragDropComponent { +} @Component({ styles: generalStyles, @@ -2079,7 +2049,8 @@ class TestDragDropLinkedSingleComponent extends TestDragDropComponent { } `, imports: [IgxDragDirective, IgxDropDirective] }) -class TestDragDropLinkedMixedComponent extends TestDragDropComponent { } +class TestDragDropLinkedMixedComponent extends TestDragDropComponent { +} @Component({ styles: generalStyles, @@ -2100,7 +2071,8 @@ class TestDragDropLinkedMixedComponent extends TestDragDropComponent { } `, imports: [IgxDragDirective, IgxDropDirective] }) -class TestDragDropStrategiesComponent extends TestDragDropLinkedSingleComponent { } +class TestDragDropStrategiesComponent extends TestDragDropLinkedSingleComponent { +} @Component({ styles: generalStyles, @@ -2145,7 +2117,7 @@ class TestDragDropNestedComponent extends TestDragDropComponent { { text: 'The Avengers', category: 'Action', dragged: false } ]; - protected getCategoryMovies(inCategory: string){ + protected getCategoryMovies(inCategory: string) { return this.listNotes.filter(item => item.category === inCategory); } - } +} diff --git a/projects/igniteui-angular/directives/src/directives/filter/filter.directive.spec.ts b/projects/igniteui-angular/directives/src/directives/filter/filter.directive.spec.ts index f87edf25810..c6867988a6f 100644 --- a/projects/igniteui-angular/directives/src/directives/filter/filter.directive.spec.ts +++ b/projects/igniteui-angular/directives/src/directives/filter/filter.directive.spec.ts @@ -2,6 +2,7 @@ import { Component, ViewChild } from '@angular/core'; import { ComponentFixtureAutoDetect, TestBed, waitForAsync } from '@angular/core/testing'; import { IgxListComponent, IgxListItemComponent } from 'igniteui-angular/list'; import { IgxFilterDirective, IgxFilterOptions, IgxFilterPipe } from './filter.directive'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Filter', () => { beforeEach(waitForAsync(() => { @@ -23,8 +24,8 @@ describe('Filter', () => { const items = list.items; for (const item of items) { - expect(item instanceof IgxListItemComponent).toBeTruthy(); - } + expect(item instanceof IgxListItemComponent).toBeTruthy(); + } visibleItems = items.filter((listItem) => !listItem.hidden); expect(visibleItems.length).toBe(3); @@ -178,8 +179,10 @@ describe('Filter', () => { imports: [IgxListComponent, IgxListItemComponent, IgxFilterDirective] }) class DeclarativeListTestComponent { - @ViewChild(IgxListComponent, { static: true }) public list: IgxListComponent; - @ViewChild('logInput', { static: true }) public logInput: any; + @ViewChild(IgxListComponent, { static: true }) + public list: IgxListComponent; + @ViewChild('logInput', { static: true }) + public logInput: any; public filterValue: string; public isCanceled = false; @@ -194,13 +197,13 @@ class DeclarativeListTestComponent { return options; } - public filteringHandler = function(args) { + public filteringHandler = function (args) { args.cancel = this.isCanceled; this.logInput.nativeElement.value += 'filtering;'; this.filteringArgs = args; }; - public filteredHandler = function(args) { + public filteredHandler = function (args) { this.logInput.nativeElement.value += 'filtered;'; this.filteredArgs = args; }; @@ -216,7 +219,8 @@ class DeclarativeListTestComponent { imports: [IgxListComponent, IgxListItemComponent, IgxFilterPipe] }) class DynamicListTestComponent { - @ViewChild(IgxListComponent, { static: true }) public list: IgxListComponent; + @ViewChild(IgxListComponent, { static: true }) + public list: IgxListComponent; public filterValue: string; public isCanceled = false; diff --git a/projects/igniteui-angular/directives/src/directives/focus-trap/focus-trap.directive.spec.ts b/projects/igniteui-angular/directives/src/directives/focus-trap/focus-trap.directive.spec.ts index 9c32b9de424..d9057291ccd 100644 --- a/projects/igniteui-angular/directives/src/directives/focus-trap/focus-trap.directive.spec.ts +++ b/projects/igniteui-angular/directives/src/directives/focus-trap/focus-trap.directive.spec.ts @@ -6,6 +6,7 @@ import { IgxFocusTrapDirective } from './focus-trap.directive'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { UIInteractions } from '../../../../test-utils/ui-interactions.spec'; import { IgxTimePickerComponent } from '../../../../time-picker/src/time-picker/time-picker.component'; +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; describe('igxFocusTrap', () => { beforeEach(waitForAsync(() => { diff --git a/projects/igniteui-angular/directives/src/directives/focus/focus.directive.spec.ts b/projects/igniteui-angular/directives/src/directives/focus/focus.directive.spec.ts index 9c0a9de5b04..d26ccbbc8c2 100644 --- a/projects/igniteui-angular/directives/src/directives/focus/focus.directive.spec.ts +++ b/projects/igniteui-angular/directives/src/directives/focus/focus.directive.spec.ts @@ -9,6 +9,7 @@ import { IgxDatePickerComponent } from '../../../../date-picker/src/public_api'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxRadioComponent } from '../../../../radio/src/radio/radio.component'; import { IgxSwitchComponent } from '../../../../switch/src/switch/switch.component'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('igxFocus', () => { beforeEach(waitForAsync(() => { @@ -120,13 +121,15 @@ describe('igxFocus', () => { `, imports: [IgxFocusDirective] }) -class SetFocusComponent { } +class SetFocusComponent { +} @Component({ template: ``, imports: [IgxFocusDirective] }) -class NoFocusComponent { } +class NoFocusComponent { +} @Component({ template: ` @@ -138,12 +141,12 @@ class NoFocusComponent { } imports: [IgxFocusDirective] }) class TriggerFocusOnClickComponent { - @ViewChild(IgxFocusDirective, { static: true }) public focusRef: IgxFocusDirective; + @ViewChild(IgxFocusDirective, { static: true }) + public focusRef: IgxFocusDirective; public focus() { this.focusRef.trigger(); } - } @Component({ @@ -156,11 +159,18 @@ class TriggerFocusOnClickComponent { imports: [IgxFocusDirective, IgxCheckboxComponent, IgxSwitchComponent, IgxRadioComponent, IgxDatePickerComponent] }) class CheckboxPickerComponent { - @ViewChild(IgxCheckboxComponent, { static: true }) public checkbox: IgxCheckboxComponent; - @ViewChild(IgxRadioComponent, { static: true }) public radio: IgxRadioComponent; - @ViewChild(IgxSwitchComponent, { static: true }) public switch: IgxSwitchComponent; - @ViewChild(IgxDatePickerComponent, { static: true }) public picker: IgxDatePickerComponent; - @ViewChild('radio', { read: IgxFocusDirective, static: true }) public radioFocusRef: IgxFocusDirective; - @ViewChild('switch', { read: IgxFocusDirective, static: true }) public switchFocusRef: IgxFocusDirective; - @ViewChild('picker', { read: IgxFocusDirective, static: true }) public pickerFocusRef: IgxFocusDirective; + @ViewChild(IgxCheckboxComponent, { static: true }) + public checkbox: IgxCheckboxComponent; + @ViewChild(IgxRadioComponent, { static: true }) + public radio: IgxRadioComponent; + @ViewChild(IgxSwitchComponent, { static: true }) + public switch: IgxSwitchComponent; + @ViewChild(IgxDatePickerComponent, { static: true }) + public picker: IgxDatePickerComponent; + @ViewChild('radio', { read: IgxFocusDirective, static: true }) + public radioFocusRef: IgxFocusDirective; + @ViewChild('switch', { read: IgxFocusDirective, static: true }) + public switchFocusRef: IgxFocusDirective; + @ViewChild('picker', { read: IgxFocusDirective, static: true }) + public pickerFocusRef: IgxFocusDirective; } diff --git a/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.spec.ts b/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.spec.ts index 68a390706b4..ee3f274fd85 100644 --- a/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.spec.ts +++ b/projects/igniteui-angular/directives/src/directives/for-of/for_of.directive.spec.ts @@ -1,4 +1,4 @@ -import { AsyncPipe, NgClass, NgForOfContext } from '@angular/common'; +import { AsyncPipe, NgClass, NgForOfContext } from '@angular/common'; import { AfterViewInit, ChangeDetectorRef, Component, Directive, Injectable, IterableDiffers, NgZone, OnInit, QueryList, TemplateRef, ViewChild, ViewChildren, ViewContainerRef, DebugElement, Pipe, PipeTransform, inject } from '@angular/core'; import { TestBed, ComponentFixture, waitForAsync } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; @@ -7,6 +7,7 @@ import { IForOfState, IgxForOfDirective } from './for_of.directive'; import { UIInteractions, wait } from '../../../../test-utils/ui-interactions.spec'; import { IgxForOfScrollSyncService } from './for_of.sync.service'; +import { describe, it, expect, beforeAll, beforeEach, afterEach, vi } from 'vitest'; describe('IgxForOf directive -', () => { const INACTIVE_VIRT_CONTAINER = 'igx-display-container--inactive'; @@ -252,7 +253,7 @@ describe('IgxForOf directive -', () => { expect(parseInt(displayContainer.style.top, 10)).toEqual(-5); - spyOn(fix.componentInstance.parentVirtDir.chunkLoad, 'emit'); + vi.spyOn(fix.componentInstance.parentVirtDir.chunkLoad, 'emit'); fix.componentInstance.data = [{ 1: 1, 2: 2, 3: 3, 4: 4 }]; fix.detectChanges(); @@ -486,7 +487,7 @@ describe('IgxForOf directive -', () => { it('should scroll to wheel event correctly', async () => { fix.componentInstance.parentVirtDir.dc.instance._scrollInertia.smoothingDuration = 0; /* 120 is default mousewheel on Chrome, scroll 2 records down */ - await UIInteractions.simulateWheelEvent(displayContainer, 0, - 1 * 2 * 120); + await UIInteractions.simulateWheelEvent(displayContainer, 0, -1 * 2 * 120); fix.detectChanges(); await wait(); @@ -773,14 +774,10 @@ describe('IgxForOf directive -', () => { } }); - xit('should apply inertia when swiping via touch interaction.', async () => { + it.skip('should apply inertia when swiping via touch interaction.', async () => { const dcElem = fix.componentInstance.parentVirtDir.dc.instance._viewContainer.element.nativeElement; // spyOn(fix.componentInstance.parentVirtDir, 'onScroll'); - await UIInteractions.simulateTouchStartEvent( - dcElem, - 0, - -150 - ); + await UIInteractions.simulateTouchStartEvent(dcElem, 0, -150); await wait(1); await UIInteractions.simulateTouchMoveEvent(dcElem, 0, -180); await UIInteractions.simulateTouchEndEvent(dcElem, 0, -200); @@ -923,7 +920,7 @@ describe('IgxForOf directive -', () => { }); it('should correctly scroll to the last element when using the scrollTo method', () => { - spyOn(fix.componentInstance.parentVirtDir.chunkLoad, 'emit'); + vi.spyOn(fix.componentInstance.parentVirtDir.chunkLoad, 'emit'); /** Scroll to the last 49999 row. */ fix.componentInstance.parentVirtDir.scrollTo(49999); @@ -955,8 +952,8 @@ describe('IgxForOf directive -', () => { it('should emit the chunkPreload/chunkLoad only when startIndex or chunkSize have changed.', async () => { const verticalDir = fix.componentInstance.parentVirtDir; - const chunkLoadSpy = spyOn(verticalDir.chunkLoad, 'emit').and.callThrough(); - const chunkPreLoadSpy = spyOn(verticalDir.chunkPreload, 'emit').and.callThrough(); + const chunkLoadSpy = vi.spyOn(verticalDir.chunkLoad, 'emit'); + const chunkPreLoadSpy = vi.spyOn(verticalDir.chunkPreload, 'emit'); // scroll so that start index does not change. fix.componentInstance.scrollTop(1); fix.detectChanges(); @@ -1397,7 +1394,8 @@ export class TestIgxForOfDirective extends IgxForOfDirective { }) export class EmptyVirtualComponent { - @ViewChild('container', { static: true }) public container; + @ViewChild('container', { static: true }) + public container; public data = []; } diff --git a/projects/igniteui-angular/directives/src/directives/form-control/form-control.directive.spec.ts b/projects/igniteui-angular/directives/src/directives/form-control/form-control.directive.spec.ts index 7de8dfb9ae5..d73549bf03b 100644 --- a/projects/igniteui-angular/directives/src/directives/form-control/form-control.directive.spec.ts +++ b/projects/igniteui-angular/directives/src/directives/form-control/form-control.directive.spec.ts @@ -5,6 +5,7 @@ import { By } from '@angular/platform-browser'; import { defineComponents, IgcRatingComponent } from 'igniteui-webcomponents'; import { IgcFormControlDirective } from './form-control.directive'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgcFormControlDirective - ', () => { @@ -29,18 +30,18 @@ describe('IgcFormControlDirective - ', () => { const elementRef = { nativeElement: document.createElement('igc-rating') }; - const mockNgControl = jasmine.createSpyObj('NgControl', [ - 'writeValue', - 'onChange', - 'setDisabledState', - 'onChange', - 'registerOnChangeCb', - 'registerOnTouchedCb' - ]); - - const renderer2Mock = jasmine.createSpyObj('renderer2Mock', [ - 'setProperty' - ]); + const mockNgControl = { + writeValue: vi.fn().mockName("NgControl.writeValue"), + onChange: vi.fn().mockName("NgControl.onChange"), + setDisabledState: vi.fn().mockName("NgControl.setDisabledState"), + onChange: vi.fn().mockName("NgControl.onChange"), + registerOnChangeCb: vi.fn().mockName("NgControl.registerOnChangeCb"), + registerOnTouchedCb: vi.fn().mockName("NgControl.registerOnTouchedCb") + }; + + const renderer2Mock = { + setProperty: vi.fn().mockName("renderer2Mock.setProperty") + }; it('should correctly implement interface methods - ControlValueAccessor ', () => { directive = TestBed.inject(IgcFormControlDirective); diff --git a/projects/igniteui-angular/directives/src/directives/layout/layout.directive.spec.ts b/projects/igniteui-angular/directives/src/directives/layout/layout.directive.spec.ts index 0a416c690ae..47b8e512f4c 100644 --- a/projects/igniteui-angular/directives/src/directives/layout/layout.directive.spec.ts +++ b/projects/igniteui-angular/directives/src/directives/layout/layout.directive.spec.ts @@ -2,6 +2,7 @@ import { Component, ViewChild } from '@angular/core'; import { TestBed, waitForAsync } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { IgxFlexDirective, IgxLayoutDirective } from './layout.directive'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('IgxLayoutDirective', () => { beforeEach(waitForAsync(() => { @@ -142,6 +143,8 @@ describe('IgxLayoutDirective', () => { imports: [IgxLayoutDirective, IgxFlexDirective] }) class TestFlexLayoutComponent { - @ViewChild(IgxLayoutDirective, { static: true }) public instance: IgxLayoutDirective; - @ViewChild(IgxFlexDirective, { static: true }) public inner: IgxFlexDirective; + @ViewChild(IgxLayoutDirective, { static: true }) + public instance: IgxLayoutDirective; + @ViewChild(IgxFlexDirective, { static: true }) + public inner: IgxFlexDirective; } diff --git a/projects/igniteui-angular/directives/src/directives/mask/mask.directive.spec.ts b/projects/igniteui-angular/directives/src/directives/mask/mask.directive.spec.ts index cd08b66bcd9..43a8b887c31 100644 --- a/projects/igniteui-angular/directives/src/directives/mask/mask.directive.spec.ts +++ b/projects/igniteui-angular/directives/src/directives/mask/mask.directive.spec.ts @@ -9,6 +9,7 @@ import { By } from '@angular/platform-browser'; import { IgxInputGroupComponent } from '../../../../input-group/src/input-group/input-group.component'; import { IgxInputDirective } from 'igniteui-angular/input-group'; import { PlatformUtil } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('igxMask', () => { // TODO: Refactor tests to reuse components @@ -516,8 +517,8 @@ describe('igxMask', () => { fixture.detectChanges(); const maskDirective = fixture.componentInstance.mask; - spyOn(maskDirective, 'onFocus').and.callThrough(); - spyOn(maskDirective, 'showMask').and.callThrough(); + vi.spyOn(maskDirective, 'onFocus'); + vi.spyOn(maskDirective, 'showMask'); const input = fixture.debugElement.query(By.css('.igx-input-group__input')); input.triggerEventHandler('focus', {}); @@ -590,7 +591,10 @@ describe('igxMaskDirective ControlValueAccessor Unit', () => { let mask: IgxMaskDirective; let renderer2: Renderer2; it('Should correctly implement interface methods', () => { - const mockNgControl = jasmine.createSpyObj('NgControl', ['registerOnChangeCb', 'registerOnTouchedCb']); + const mockNgControl = { + registerOnChangeCb: vi.fn().mockName("NgControl.registerOnChangeCb"), + registerOnTouchedCb: vi.fn().mockName("NgControl.registerOnTouchedCb") + }; const platformMock = { isIE: false, KEYMAP: { @@ -601,15 +605,17 @@ describe('igxMaskDirective ControlValueAccessor Unit', () => { } }; - const mockParser = jasmine.createSpyObj('MaskParsingService', { - applyMask: 'test____', - replaceInMask: { value: 'test_2__', end: 6 } as Replaced, - parseValueFromMask: 'test2' - }); + const mockParser = { + applyMask: vi.fn().mockName("MaskParsingService.applyMask").mockReturnValue('test____'), + replaceInMask: vi.fn().mockName("MaskParsingService.replaceInMask").mockReturnValue({ value: 'test_2__', end: 6 } as Replaced), + parseValueFromMask: vi.fn().mockName("MaskParsingService.parseValueFromMask").mockReturnValue('test2') + }; const format = 'CCCCCCCC'; // init - renderer2 = jasmine.createSpyObj('Renderer2', ['setAttribute']); + renderer2 = { + setAttribute: vi.fn().mockName("Renderer2.setAttribute") + }; TestBed.configureTestingModule({ providers: [ @@ -625,24 +631,24 @@ describe('igxMaskDirective ControlValueAccessor Unit', () => { mask.mask = format; mask.registerOnChange(mockNgControl.registerOnChangeCb); mask.registerOnTouched(mockNgControl.registerOnTouchedCb); - spyOn(mask.valueChanged, 'emit'); - const inputGet = spyOnProperty(mask as any, 'inputValue', 'get'); - const inputSet = spyOnProperty(mask as any, 'inputValue', 'set'); + vi.spyOn(mask.valueChanged, 'emit'); + const inputGet = vi.spyOn(mask as any, 'inputValue', 'get'); + const inputSet = vi.spyOn(mask as any, 'inputValue', 'set'); // writeValue - inputGet.and.returnValue('formatted'); + inputGet.mockReturnValue('formatted'); mask.writeValue('test'); - expect(mockParser.applyMask).toHaveBeenCalledWith('test', jasmine.objectContaining({ format })); + expect(mockParser.applyMask).toHaveBeenCalledWith('test', expect.objectContaining({ format })); expect(inputSet).toHaveBeenCalledWith('test____'); expect(mockNgControl.registerOnChangeCb).not.toHaveBeenCalled(); expect(mask.valueChanged.emit).toHaveBeenCalledWith({ rawValue: 'test', formattedValue: 'formatted' }); // OnChange callback - inputGet.and.returnValue('test_2___'); - spyOnProperty(mask as any, 'selectionEnd').and.returnValue(6); - const setSelectionSpy = spyOn(mask as any, 'setSelectionRange'); + inputGet.mockReturnValue('test_2___'); + vi.spyOn(mask as any, 'selectionEnd').mockReturnValue(6); + const setSelectionSpy = vi.spyOn(mask as any, 'setSelectionRange'); mask.onInputChanged(false); - expect(mockParser.replaceInMask).toHaveBeenCalledWith('', 'test_2', jasmine.objectContaining({ format }), 0, 0); + expect(mockParser.replaceInMask).toHaveBeenCalledWith('', 'test_2', expect.objectContaining({ format }), 0, 0); expect(inputSet).toHaveBeenCalledWith('test_2__'); expect(setSelectionSpy).toHaveBeenCalledWith(6); expect(mockNgControl.registerOnChangeCb).toHaveBeenCalledWith('test2'); @@ -718,7 +724,8 @@ class MaskComponent { imports: [FormsModule, IgxInputGroupComponent, IgxInputDirective, IgxMaskDirective] }) class IncludeLiteralsComponent { - @Input() public value = '55555'; + @Input() + public value = '55555'; @ViewChild('input', { static: true }) public input: ElementRef; diff --git a/projects/igniteui-angular/directives/src/directives/scroll-inertia/scroll_inertia.directive.spec.ts b/projects/igniteui-angular/directives/src/directives/scroll-inertia/scroll_inertia.directive.spec.ts index 251e29ea7d8..c5077937a5a 100644 --- a/projects/igniteui-angular/directives/src/directives/scroll-inertia/scroll_inertia.directive.spec.ts +++ b/projects/igniteui-angular/directives/src/directives/scroll-inertia/scroll_inertia.directive.spec.ts @@ -3,6 +3,7 @@ import { TestBed, ComponentFixture, fakeAsync, tick, waitForAsync } from '@angul import { IgxScrollInertiaDirective } from './scroll_inertia.directive'; import { wait } from '../../../../test-utils/ui-interactions.spec'; +import { describe, it, test, expect, beforeEach, afterEach, vi } from 'vitest'; describe('Scroll Inertia Directive - Rendering', () => { let fix: ComponentFixture; @@ -31,8 +32,10 @@ describe('Scroll Inertia Directive - Rendering', () => { }); // Unit tests for inertia function. - it('inertia should accelerate and then deccelerate vertically.', async () => { - pending('This should be tested in the e2e test'); + it.skip('inertia should accelerate and then deccelerate vertically.', async () => { + // TODO: vitest-migration: The pending() function was converted to a skipped test (`it.skip`). See: https://vitest.dev/api/vi.html#it-skip + // pending('This should be tested in the e2e test'); + ; const scrInertiaDir = fix.componentInstance.scrInertiaDir; // vertical inertia @@ -50,8 +53,10 @@ describe('Scroll Inertia Directive - Rendering', () => { expect(end).toBeLessThan(mid); }); - it('inertia should accelerate and then deccelerate horizontally.', async () => { - pending('This should be tested in the e2e test'); + it.skip('inertia should accelerate and then deccelerate horizontally.', async () => { + // TODO: vitest-migration: The pending() function was converted to a skipped test (`it.skip`). See: https://vitest.dev/api/vi.html#it-skip + // pending('This should be tested in the e2e test'); + ; const scrInertiaDir = fix.componentInstance.scrInertiaDir; // horizontal inertia @@ -189,18 +194,18 @@ describe('Scroll Inertia Directive - Scrolling', () => { it('should change scroll top for related scrollbar on touch start/move/end', fakeAsync(() => { let evt = { touches: [{ - pageX: 0, - pageY: 0 - }], + pageX: 0, + pageY: 0 + }], preventDefault: () => { } }; scrollInertiaDir.onTouchStart(evt); evt = { touches: [{ - pageX: 0, - pageY: -100 - }], + pageX: 0, + pageY: -100 + }], preventDefault: () => { } }; tick(10); @@ -215,18 +220,18 @@ describe('Scroll Inertia Directive - Scrolling', () => { it('should stop inertia if another touch event is initiated while inertia is executing.', fakeAsync(() => { let evt = { touches: [{ - pageX: 0, - pageY: 0 - }], + pageX: 0, + pageY: 0 + }], preventDefault: () => { } }; scrollInertiaDir.onTouchStart(evt); evt = { touches: [{ - pageX: 0, - pageY: -100 - }], + pageX: 0, + pageY: -100 + }], preventDefault: () => { } }; tick(10); @@ -238,9 +243,9 @@ describe('Scroll Inertia Directive - Scrolling', () => { // don't wait for inertia to end. Instead start another touch interaction. evt = { touches: [{ - pageX: 0, - pageY: 0 - }], + pageX: 0, + pageY: 0 + }], preventDefault: () => { } }; scrollInertiaDir.onTouchStart(evt); @@ -252,17 +257,17 @@ describe('Scroll Inertia Directive - Scrolling', () => { // if scroll is initiated on Y and on X within the defined tolerance no scrolling should occur on X. let evt = { touches: [{ - pageX: 0, - pageY: 0 - }], + pageX: 0, + pageY: 0 + }], preventDefault: () => { } }; scrollInertiaDir.onTouchStart(evt); evt = { touches: [{ - pageX: -10, - pageY: -50 - }], + pageX: -10, + pageY: -50 + }], preventDefault: () => { } }; tick(10); @@ -278,18 +283,18 @@ describe('Scroll Inertia Directive - Scrolling', () => { it('should change scroll left for related scrollbar on touch start/move/end', fakeAsync(() => { let evt = { touches: [{ - pageX: 0, - pageY: 0 - }], + pageX: 0, + pageY: 0 + }], preventDefault: () => { } }; scrollInertiaDir.onTouchStart(evt); evt = { touches: [{ - pageX: -100, - pageY: 0 - }], + pageX: -100, + pageY: 0 + }], preventDefault: () => { } }; tick(10); @@ -349,8 +354,10 @@ export class IgxTestScrollInertiaDirective extends IgxScrollInertiaDirective { imports: [IgxTestScrollInertiaDirective] }) export class ScrollInertiaComponent implements OnInit { - @ViewChild('container', { static: true }) public container: ElementRef; - @ViewChild('scrBar', { static: true }) public scrollContainer: ElementRef; + @ViewChild('container', { static: true }) + public container: ElementRef; + @ViewChild('scrBar', { static: true }) + public scrollContainer: ElementRef; @ViewChild('scrInertiaContainer', { read: IgxTestScrollInertiaDirective, static: true }) public scrInertiaDir: IgxTestScrollInertiaDirective; diff --git a/projects/igniteui-angular/directives/src/directives/size/ig-size.directive.spec.ts b/projects/igniteui-angular/directives/src/directives/size/ig-size.directive.spec.ts index f40061fac5e..e0c2b3011b4 100644 --- a/projects/igniteui-angular/directives/src/directives/size/ig-size.directive.spec.ts +++ b/projects/igniteui-angular/directives/src/directives/size/ig-size.directive.spec.ts @@ -1,45 +1,46 @@ import { Component } from '@angular/core'; import { IgSizeDirective } from './ig-size.directive'; import { TestBed, ComponentFixture } from '@angular/core/testing'; +import { describe, it, expect, beforeEach } from 'vitest'; @Component({ - template: `
Test Element
`, - imports: [IgSizeDirective], + template: `
Test Element
`, + imports: [IgSizeDirective], }) class TestComponent { - public size: 'small' | 'medium' | 'large'; + public size: 'small' | 'medium' | 'large'; } describe('IgSizeDirective', () => { - let fixture: ComponentFixture; - let testComponent: TestComponent; - let divElement: HTMLElement; + let fixture: ComponentFixture; + let testComponent: TestComponent; + let divElement: HTMLElement; - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [TestComponent], - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [TestComponent], + }); - fixture = TestBed.createComponent(TestComponent); - testComponent = fixture.componentInstance; - divElement = fixture.nativeElement.querySelector('div'); - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(TestComponent); + testComponent = fixture.componentInstance; + divElement = fixture.nativeElement.querySelector('div'); + fixture.detectChanges(); + }); - it('should apply the correct --ig-size inline style for each size', () => { - const sizeMap = { - small: 'var(--ig-size-small)', - medium: 'var(--ig-size-medium)', - large: 'var(--ig-size-large)', - }; + it('should apply the correct --ig-size inline style for each size', () => { + const sizeMap = { + small: 'var(--ig-size-small)', + medium: 'var(--ig-size-medium)', + large: 'var(--ig-size-large)', + }; - // Loop through each size and verify the inline style - for (const size in sizeMap) { - testComponent.size = size as 'small' | 'medium' | 'large'; - fixture.detectChanges(); + // Loop through each size and verify the inline style + for (const size in sizeMap) { + testComponent.size = size as 'small' | 'medium' | 'large'; + fixture.detectChanges(); - // Check if the --ig-size style is applied correctly - expect(divElement.style.getPropertyValue('--ig-size')).toBe(sizeMap[size]); - } - }); + // Check if the --ig-size style is applied correctly + expect(divElement.style.getPropertyValue('--ig-size')).toBe(sizeMap[size]); + } + }); }); diff --git a/projects/igniteui-angular/directives/src/directives/text-highlight/text-highlight.directive.spec.ts b/projects/igniteui-angular/directives/src/directives/text-highlight/text-highlight.directive.spec.ts index 32c0e855f0b..8dee4bc3b01 100644 --- a/projects/igniteui-angular/directives/src/directives/text-highlight/text-highlight.directive.spec.ts +++ b/projects/igniteui-angular/directives/src/directives/text-highlight/text-highlight.directive.spec.ts @@ -1,9 +1,10 @@ import { Component, ViewChild, inject } from '@angular/core'; import { TestBed, waitForAsync } from '@angular/core/testing'; -import { IgxTextHighlightDirective, IActiveHighlightInfo} from './text-highlight.directive'; +import { IgxTextHighlightDirective, IActiveHighlightInfo } from './text-highlight.directive'; import { IgxTextHighlightService } from './text-highlight.service'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('IgxHighlight', () => { beforeEach(waitForAsync(() => { @@ -100,10 +101,8 @@ describe('IgxHighlight', () => { fix.detectChanges(); const component: HighlightLoremIpsumComponent = fix.debugElement.componentInstance; - const count = component.highlightText( - 'LoReM ipsuM dolor sit AMET, consectetur adipiscing elit. Vestibulum vulputate LucTUS dui ut maximus.' + - ' Quisque sed suscipit lorem. Vestibulum sit.', - false, true); + const count = component.highlightText('LoReM ipsuM dolor sit AMET, consectetur adipiscing elit. Vestibulum vulputate LucTUS dui ut maximus.' + + ' Quisque sed suscipit lorem. Vestibulum sit.', false, true); let spans = fix.debugElement.nativeElement.querySelectorAll('.' + component.highlightClass); expect(spans.length).toBe(1); diff --git a/projects/igniteui-angular/directives/src/directives/text-selection/text-selection.directive.spec.ts b/projects/igniteui-angular/directives/src/directives/text-selection/text-selection.directive.spec.ts index 2446d1c1eb1..4014ca139de 100644 --- a/projects/igniteui-angular/directives/src/directives/text-selection/text-selection.directive.spec.ts +++ b/projects/igniteui-angular/directives/src/directives/text-selection/text-selection.directive.spec.ts @@ -3,6 +3,7 @@ import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { IgxTextSelectionDirective } from './text-selection.directive'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('IgxSelection', () => { beforeEach(waitForAsync(() => { @@ -28,7 +29,7 @@ describe('IgxSelection', () => { expect(input.value.substring(input.selectionStart, input.selectionEnd)).toEqual(input.value); })); - it('Should select the text when the input is clicked', fakeAsync(()=> { + it('Should select the text when the input is clicked', fakeAsync(() => { const fix = TestBed.createComponent(TriggerTextSelectionOnClickComponent); fix.detectChanges(); @@ -47,7 +48,7 @@ describe('IgxSelection', () => { it('Should check if the value is selected if based on input type', fakeAsync(() => { const fix = TestBed.createComponent(TriggerTextSelectionOnClickComponent); const selectableTypes: Types[] = [ - { "text" : "Some Values!" }, + { "text": "Some Values!" }, { "search": "Search!" }, { "password": "********" }, { "tel": '+(359)554-587-415' }, @@ -56,12 +57,12 @@ describe('IgxSelection', () => { ]; const nonSelectableTypes: Types[] = [ - {'date': new Date() }, - {'datetime-local': "2018-06-12T19:30" }, - {'email': 'JohnSmith@gmail.com'}, - {'month': "2018-05" }, - {'time': "13:30"}, - {'week': "2017-W01"} + { 'date': new Date() }, + { 'datetime-local': "2018-06-12T19:30" }, + { 'email': 'JohnSmith@gmail.com' }, + { 'month': "2018-05" }, + { 'time': "13:30" }, + { 'week': "2017-W01" } ]; //skipped on purpose, if needed feel free to add to any of the above categories @@ -71,7 +72,7 @@ describe('IgxSelection', () => { const inputNativeElem = input.nativeElement; const inputElem: HTMLElement = input.nativeElement; - selectableTypes.forEach( el => { + selectableTypes.forEach(el => { const type = Object.keys(el)[0]; const val = el[type]; fix.componentInstance.inputType = type; @@ -82,20 +83,20 @@ describe('IgxSelection', () => { fix.detectChanges(); tick(16); - if(type !== 'number'){ + if (type !== 'number') { expect(inputNativeElem.selectionEnd).toEqual(inputNativeElem.value.length); expect(inputNativeElem.value.substring(inputNativeElem.selectionStart, inputNativeElem.selectionEnd)) .toEqual(val); } - if(type === 'number'){ + if (type === 'number') { const selection = document.getSelection().toString(); tick(1000); expect((String(val)).length).toBe(selection.length); } }); - nonSelectableTypes.forEach( el => { + nonSelectableTypes.forEach(el => { const type = Object.keys(el)[0]; const val = el[type]; fix.componentInstance.inputType = type; @@ -160,7 +161,8 @@ class IgxTestFocusDirective { `, imports: [IgxTextSelectionDirective] }) -class TriggerTextSelectionComponent { } +class TriggerTextSelectionComponent { +} @Component({ template: ` @@ -171,15 +173,16 @@ class TriggerTextSelectionComponent { } class TriggerTextSelectionOnClickComponent { public selectValue = true; public inputType: any = "text"; - public inputValue: any = "Some custom V!" + public inputValue: any = "Some custom V!"; - @ViewChild('input',{read: HTMLInputElement, static:true}) public input: HTMLInputElement; + @ViewChild('input', { read: HTMLInputElement, static: true }) + public input: HTMLInputElement; public waitForOneSecond() { return new Promise(resolve => { - setTimeout(() => { - resolve("I promise to return after one second!"); - }, 1000); + setTimeout(() => { + resolve("I promise to return after one second!"); + }, 1000); }); } } @@ -188,9 +191,9 @@ class TriggerTextSelectionOnClickComponent { template: ``, imports: [IgxTextSelectionDirective, IgxTestFocusDirective] }) - class TextSelectionWithMultipleFocusHandlersComponent { +class TextSelectionWithMultipleFocusHandlersComponent { public inputValue: any = "12-34-56"; - } +} interface Types { [key: string]: any; diff --git a/projects/igniteui-angular/directives/src/directives/toggle/toggle.directive.spec.ts b/projects/igniteui-angular/directives/src/directives/toggle/toggle.directive.spec.ts index 7db9cfdc34c..8569b404c32 100644 --- a/projects/igniteui-angular/directives/src/directives/toggle/toggle.directive.spec.ts +++ b/projects/igniteui-angular/directives/src/directives/toggle/toggle.directive.spec.ts @@ -6,6 +6,7 @@ import { IgxToggleActionDirective, IgxToggleDirective } from './toggle.directive import { first } from 'rxjs/operators'; import { AbsoluteScrollStrategy, AutoPositionStrategy, CancelableEventArgs, ConnectedPositioningStrategy, HorizontalAlignment, IgxOverlayOutletDirective, IgxOverlayService, OffsetMode, OverlaySettings } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxToggle', () => { const HIDDEN_TOGGLER_CLASS = 'igx-toggle--hidden'; @@ -61,8 +62,8 @@ describe('IgxToggle', () => { fixture.detectChanges(); const toggle = fixture.componentInstance.toggle; - spyOn(toggle.opening, 'emit'); - spyOn(toggle.opened, 'emit'); + vi.spyOn(toggle.opening, 'emit'); + vi.spyOn(toggle.opened, 'emit'); toggle.open(); tick(); fixture.detectChanges(); @@ -76,7 +77,7 @@ describe('IgxToggle', () => { fixture.detectChanges(); const toggle = fixture.componentInstance.toggle; - spyOn(toggle.appended, 'emit'); + vi.spyOn(toggle.appended, 'emit'); toggle.open(); tick(); fixture.detectChanges(); @@ -102,8 +103,8 @@ describe('IgxToggle', () => { tick(); fixture.detectChanges(); - spyOn(toggle.closing, 'emit'); - spyOn(toggle.closed, 'emit'); + vi.spyOn(toggle.closing, 'emit'); + vi.spyOn(toggle.closed, 'emit'); toggle.close(); tick(); fixture.detectChanges(); @@ -118,8 +119,8 @@ describe('IgxToggle', () => { const toggle = fixture.componentInstance.toggle; const overlay = fixture.componentInstance.overlay; - spyOn(toggle.opened, 'emit'); - spyOn(toggle.closed, 'emit'); + vi.spyOn(toggle.opened, 'emit'); + vi.spyOn(toggle.closed, 'emit'); toggle.open(); tick(); @@ -186,8 +187,8 @@ describe('IgxToggle', () => { const divEl = fixture.debugElement.query(By.directive(IgxToggleDirective)).nativeElement; const toggle = fixture.componentInstance.toggle; const p = fixture.debugElement.query(By.css('p')); - spyOn(toggle.opening, 'emit'); - spyOn(toggle.opened, 'emit'); + vi.spyOn(toggle.opening, 'emit'); + vi.spyOn(toggle.opened, 'emit'); fixture.componentInstance.toggleAction.onClick(); tick(); @@ -196,8 +197,8 @@ describe('IgxToggle', () => { expect(fixture.componentInstance.toggle.collapsed).toBe(false); expect(divEl.classList.contains(TOGGLER_CLASS)).toBe(true); - spyOn(toggle.closing, 'emit'); - spyOn(toggle.closed, 'emit'); + vi.spyOn(toggle.closing, 'emit'); + vi.spyOn(toggle.closed, 'emit'); p.nativeElement.click(); tick(); @@ -215,7 +216,7 @@ describe('IgxToggle', () => { fixture.detectChanges(); const overlayService = TestBed.inject(IgxOverlayService); - spyOn(overlayService, 'setOffset').and.callThrough(); + vi.spyOn(overlayService, 'setOffset'); fixture.detectChanges(); // Set initial offset @@ -254,8 +255,8 @@ describe('IgxToggle', () => { const toggleElm = fix.debugElement.query(By.directive(IgxToggleDirective)).nativeElement; const button: DebugElement = fix.debugElement.query(By.css('button')); - spyOn(toggle.opened, 'emit'); - spyOn(toggle.closed, 'emit'); + vi.spyOn(toggle.opened, 'emit'); + vi.spyOn(toggle.closed, 'emit'); button.triggerEventHandler('click', null); tick(); @@ -278,10 +279,10 @@ describe('IgxToggle', () => { const toggle = fixture.componentInstance.toggle; - spyOn(toggle.opening, 'emit').and.callThrough(); - spyOn(toggle.opened, 'emit').and.callThrough(); - spyOn(toggle.closing, 'emit').and.callThrough(); - spyOn(toggle.closed, 'emit').and.callThrough(); + vi.spyOn(toggle.opening, 'emit'); + vi.spyOn(toggle.opened, 'emit'); + vi.spyOn(toggle.closing, 'emit'); + vi.spyOn(toggle.closed, 'emit'); let cancelClosing = true; toggle.closing.pipe(first()).subscribe((e: CancelableEventArgs) => e.cancel = cancelClosing); @@ -421,8 +422,8 @@ describe('IgxToggle', () => { fixture.detectChanges(); const toggle = fixture.componentInstance.toggle; - spyOn(toggle.opening, 'emit'); - spyOn(toggle.opened, 'emit'); + vi.spyOn(toggle.opening, 'emit'); + vi.spyOn(toggle.opened, 'emit'); toggle.open(); tick(); fixture.detectChanges(); @@ -443,8 +444,8 @@ describe('IgxToggle', () => { fixture.detectChanges(); const toggle = fixture.componentInstance.toggle; - spyOn(toggle.opening, 'emit'); - spyOn(toggle.opened, 'emit'); + vi.spyOn(toggle.opening, 'emit'); + vi.spyOn(toggle.opened, 'emit'); toggle.open(); tick(); fixture.detectChanges(); @@ -452,8 +453,8 @@ describe('IgxToggle', () => { expect(toggle.opening.emit).toHaveBeenCalledTimes(1); expect(toggle.opened.emit).toHaveBeenCalledTimes(1); - spyOn(toggle.closing, 'emit'); - spyOn(toggle.closed, 'emit'); + vi.spyOn(toggle.closing, 'emit'); + vi.spyOn(toggle.closed, 'emit'); toggle.close(); tick(); fixture.detectChanges(); @@ -478,8 +479,8 @@ describe('IgxToggle', () => { toggle.open(); }); - spyOn(toggle.opening, 'emit'); - spyOn(toggle.closed, 'emit').and.callThrough(); + vi.spyOn(toggle.opening, 'emit'); + vi.spyOn(toggle.closed, 'emit'); toggle.open(); tick(); @@ -503,15 +504,15 @@ describe('IgxToggle', () => { it('should pass correct defaults from IgxToggleActionDirective and respect outsideClickClose', fakeAsync(() => { const fixture = TestBed.createComponent(IgxToggleActionTestComponent); fixture.detectChanges(); - spyOn(IgxToggleDirective.prototype, 'toggle'); + vi.spyOn(IgxToggleDirective.prototype, 'toggle'); const button = fixture.debugElement.query(By.directive(IgxToggleActionDirective)).nativeElement as HTMLElement; const defaults: OverlaySettings = { target: button, - positionStrategy: jasmine.any(ConnectedPositioningStrategy) as any, + positionStrategy: expect.any(ConnectedPositioningStrategy) as any, closeOnOutsideClick: true, modal: false, - scrollStrategy: jasmine.any(AbsoluteScrollStrategy) as any, + scrollStrategy: expect.any(AbsoluteScrollStrategy) as any, excludeFromOutsideClick: [button] }; @@ -528,15 +529,15 @@ describe('IgxToggle', () => { it('should pass overlaySettings input from IgxToggleActionDirective and respect outsideClickClose', () => { const fixture = TestBed.createComponent(IgxToggleActionTestComponent); fixture.detectChanges(); - spyOn(IgxToggleDirective.prototype, 'toggle'); + vi.spyOn(IgxToggleDirective.prototype, 'toggle'); const button = fixture.debugElement.query(By.directive(IgxToggleActionDirective)).nativeElement; const settings: OverlaySettings = { target: button, - positionStrategy: jasmine.any(ConnectedPositioningStrategy) as any, + positionStrategy: expect.any(ConnectedPositioningStrategy) as any, closeOnOutsideClick: true, modal: false, - scrollStrategy: jasmine.any(AbsoluteScrollStrategy) as any, + scrollStrategy: expect.any(AbsoluteScrollStrategy) as any, excludeFromOutsideClick: [button] }; @@ -548,7 +549,7 @@ describe('IgxToggle', () => { fixture.componentInstance.settings.modal = true; fixture.componentInstance.settings.positionStrategy = new AutoPositionStrategy(); settings.modal = true; - settings.positionStrategy = jasmine.any(AutoPositionStrategy) as any; + settings.positionStrategy = expect.any(AutoPositionStrategy) as any; fixture.detectChanges(); fixture.componentInstance.toggleAction.onClick(); expect(IgxToggleDirective.prototype.toggle).toHaveBeenCalledWith(settings); @@ -564,14 +565,14 @@ describe('IgxToggle', () => { it('should pass input overlaySettings from igxToggleAction and set position target if not provided', () => { const fixture = TestBed.createComponent(IgxToggleActionTestComponent); fixture.detectChanges(); - const toggleSpy = spyOn(IgxToggleDirective.prototype, 'toggle'); + const toggleSpy = vi.spyOn(IgxToggleDirective.prototype, 'toggle'); const button = fixture.debugElement.query(By.directive(IgxToggleActionDirective)).nativeElement; const settings: OverlaySettings = { - positionStrategy: jasmine.any(ConnectedPositioningStrategy) as any, + positionStrategy: expect.any(ConnectedPositioningStrategy) as any, closeOnOutsideClick: true, modal: false, - scrollStrategy: jasmine.any(AbsoluteScrollStrategy) as any, + scrollStrategy: expect.any(AbsoluteScrollStrategy) as any, excludeFromOutsideClick: [button] }; fixture.componentInstance.settings.positionStrategy = new ConnectedPositioningStrategy(); @@ -588,11 +589,11 @@ describe('IgxToggle', () => { const toggle = fixture.componentInstance.toggle; - spyOn(toggle, 'toggle').and.callThrough(); - spyOn(toggle.closed, 'emit').and.callThrough(); - spyOn(toggle.closing, 'emit').and.callThrough(); - spyOn(toggle.opening, 'emit').and.callThrough(); - spyOn(toggle.opened, 'emit').and.callThrough(); + vi.spyOn(toggle, 'toggle'); + vi.spyOn(toggle.closed, 'emit'); + vi.spyOn(toggle.closing, 'emit'); + vi.spyOn(toggle.opening, 'emit'); + vi.spyOn(toggle.opened, 'emit'); const button = fixture.debugElement.query(By.css('button')).nativeElement; button.click(); @@ -614,23 +615,23 @@ describe('IgxToggle', () => { it('should pass IgxOverlayOutletDirective input from IgxToggleActionDirective', () => { const fixture = TestBed.createComponent(IgxToggleOutletComponent); const outlet = fixture.debugElement.query(By.css('.outlet-container')).nativeElement; - const toggleSpy = spyOn(IgxToggleDirective.prototype, 'toggle'); + const toggleSpy = vi.spyOn(IgxToggleDirective.prototype, 'toggle'); const button = fixture.debugElement.query(By.directive(IgxToggleActionDirective)).nativeElement; fixture.detectChanges(); const settings: OverlaySettings = { target: button, - positionStrategy: jasmine.any(ConnectedPositioningStrategy) as any, + positionStrategy: expect.any(ConnectedPositioningStrategy) as any, closeOnOutsideClick: true, modal: false, - scrollStrategy: jasmine.any(AbsoluteScrollStrategy) as any, - outlet: jasmine.any(IgxOverlayOutletDirective) as any, + scrollStrategy: expect.any(AbsoluteScrollStrategy) as any, + outlet: expect.any(IgxOverlayOutletDirective) as any, excludeFromOutsideClick: [button] }; fixture.componentInstance.toggleAction.onClick(); expect(IgxToggleDirective.prototype.toggle).toHaveBeenCalledWith(settings); - const directive = toggleSpy.calls.mostRecent().args[0].outlet as IgxOverlayOutletDirective; + const directive = vi.mocked(toggleSpy).mock.lastCall[0].outlet as IgxOverlayOutletDirective; expect(directive.nativeElement).toBe(outlet); }); }); @@ -650,7 +651,8 @@ describe('IgxToggle', () => { imports: [IgxToggleDirective] }) export class IgxToggleTestComponent { - @ViewChild(IgxToggleDirective, { static: true }) public toggle: IgxToggleDirective; + @ViewChild(IgxToggleDirective, { static: true }) + public toggle: IgxToggleDirective; public open() { } public close() { } } @@ -670,8 +672,10 @@ export class IgxToggleTestComponent { imports: [IgxToggleDirective, IgxToggleActionDirective] }) export class IgxToggleActionTestComponent { - @ViewChild(IgxToggleDirective, { static: true }) public toggle: IgxToggleDirective; - @ViewChild(IgxToggleActionDirective, { static: true }) public toggleAction: IgxToggleActionDirective; + @ViewChild(IgxToggleDirective, { static: true }) + public toggle: IgxToggleDirective; + @ViewChild(IgxToggleActionDirective, { static: true }) + public toggleAction: IgxToggleActionDirective; public settings: OverlaySettings = {}; constructor() { this.settings.closeOnOutsideClick = true; @@ -686,7 +690,8 @@ export class IgxToggleActionTestComponent { `, imports: [IgxToggleActionDirective, IgxToggleDirective, IgxOverlayOutletDirective] }) -export class IgxToggleOutletComponent extends IgxToggleActionTestComponent { } +export class IgxToggleOutletComponent extends IgxToggleActionTestComponent { +} @Component({ template: ` @@ -699,8 +704,10 @@ export class IgxToggleOutletComponent extends IgxToggleActionTestComponent { } imports: [IgxToggleActionDirective, IgxToggleDirective] }) export class IgxToggleServiceInjectComponent { - @ViewChild(IgxToggleDirective, { static: true }) public toggle: IgxToggleDirective; - @ViewChild(IgxToggleActionDirective, { static: true }) public toggleAction: IgxToggleActionDirective; + @ViewChild(IgxToggleDirective, { static: true }) + public toggle: IgxToggleDirective; + @ViewChild(IgxToggleActionDirective, { static: true }) + public toggleAction: IgxToggleActionDirective; } @Component({ @@ -718,8 +725,10 @@ export class IgxToggleServiceInjectComponent { export class IgxOverlayServiceComponent { public overlay = inject(IgxOverlayService); - @ViewChild(IgxToggleDirective, { static: true }) public toggle: IgxToggleDirective; - @ViewChild(`other`, { static: true }) public other: ElementRef; + @ViewChild(IgxToggleDirective, { static: true }) + public toggle: IgxToggleDirective; + @ViewChild(`other`, { static: true }) + public other: ElementRef; } @Component({ @@ -734,7 +743,8 @@ export class IgxOverlayServiceComponent { imports: [IgxToggleActionDirective, IgxToggleDirective] }) export class TestWithOnPushComponent { - @ViewChild(IgxToggleDirective, { static: true }) public toggle: IgxToggleDirective; + @ViewChild(IgxToggleDirective, { static: true }) + public toggle: IgxToggleDirective; } @Component({ @@ -763,9 +773,12 @@ export class TestWithOnPushComponent { imports: [IgxToggleActionDirective, IgxToggleDirective] }) export class TestWithThreeToggleActionsComponent implements OnInit { - @ViewChild('button1', { static: true }) public button1: ElementRef; - @ViewChild('button2', { static: true }) public button2: ElementRef; - @ViewChild('button3', { static: true }) public button3: ElementRef; + @ViewChild('button1', { static: true }) + public button1: ElementRef; + @ViewChild('button2', { static: true }) + public button2: ElementRef; + @ViewChild('button3', { static: true }) + public button3: ElementRef; public overlaySettings: OverlaySettings = {}; diff --git a/projects/igniteui-angular/directives/src/directives/tooltip/tooltip.directive.spec.ts b/projects/igniteui-angular/directives/src/directives/tooltip/tooltip.directive.spec.ts index 26ea0aee198..93eacec73b8 100644 --- a/projects/igniteui-angular/directives/src/directives/tooltip/tooltip.directive.spec.ts +++ b/projects/igniteui-angular/directives/src/directives/tooltip/tooltip.directive.spec.ts @@ -8,6 +8,7 @@ import { HorizontalAlignment, VerticalAlignment, AutoPositionStrategy } from '.. import { IgxTooltipDirective } from './tooltip.directive'; import { IgxTooltipTargetDirective } from './tooltip-target.directive'; import { Placement, PositionsMap } from './tooltip.common'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; const HIDDEN_TOOLTIP_CLASS = 'igx-tooltip--hidden'; const TOOLTIP_CLASS = 'igx-tooltip'; @@ -89,7 +90,7 @@ describe('IgxTooltip', () => { })); it('should not render a default arrow', fakeAsync(() => { - expect(tooltipTarget.hasArrow).toBeFalse(); + expect(tooltipTarget.hasArrow).toBe(false); hoverElement(button); flush(); @@ -102,7 +103,7 @@ describe('IgxTooltip', () => { })); it('should show/hide the arrow via the `hasArrow` property', fakeAsync(() => { - expect(tooltipTarget.hasArrow).toBeFalse(); + expect(tooltipTarget.hasArrow).toBe(false); tooltipTarget.hasArrow = true; fix.detectChanges(); @@ -112,7 +113,7 @@ describe('IgxTooltip', () => { verifyTooltipVisibility(tooltipNativeElement, tooltipTarget, true); - expect(tooltipTarget.hasArrow).toBeTrue(); + expect(tooltipTarget.hasArrow).toBe(true); const arrow = tooltipNativeElement.querySelector(TOOLTIP_ARROW_SELECTOR) as HTMLElement; expect(arrow.style.display).toEqual(""); @@ -306,8 +307,8 @@ describe('IgxTooltip', () => { describe('Tooltip events', () => { it('should emit the proper events when hovering/unhovering target', fakeAsync(() => { - spyOn(tooltipTarget.tooltipShow, 'emit'); - spyOn(tooltipTarget.tooltipHide, 'emit'); + vi.spyOn(tooltipTarget.tooltipShow, 'emit'); + vi.spyOn(tooltipTarget.tooltipHide, 'emit'); hoverElement(button); expect(tooltipTarget.tooltipShow.emit).toHaveBeenCalled(); @@ -320,8 +321,8 @@ describe('IgxTooltip', () => { })); it('should emit the proper events when showing/hiding tooltip through API', fakeAsync(() => { - spyOn(tooltipTarget.tooltipShow, 'emit'); - spyOn(tooltipTarget.tooltipHide, 'emit'); + vi.spyOn(tooltipTarget.tooltipShow, 'emit'); + vi.spyOn(tooltipTarget.tooltipHide, 'emit'); tooltipTarget.showTooltip(); expect(tooltipTarget.tooltipShow.emit).toHaveBeenCalled(); @@ -334,8 +335,8 @@ describe('IgxTooltip', () => { })); it('should emit the proper events with correct eventArgs when hover/unhover', fakeAsync(() => { - spyOn(tooltipTarget.tooltipShow, 'emit'); - spyOn(tooltipTarget.tooltipHide, 'emit'); + vi.spyOn(tooltipTarget.tooltipShow, 'emit'); + vi.spyOn(tooltipTarget.tooltipHide, 'emit'); const tooltipShowArgs = { target: tooltipTarget, tooltip: fix.componentInstance.tooltip, cancel: false }; const tooltipHideArgs = { target: tooltipTarget, tooltip: fix.componentInstance.tooltip, cancel: false }; @@ -351,8 +352,8 @@ describe('IgxTooltip', () => { })); it('should emit the proper events with correct eventArgs when show/hide through API', fakeAsync(() => { - spyOn(tooltipTarget.tooltipShow, 'emit'); - spyOn(tooltipTarget.tooltipHide, 'emit'); + vi.spyOn(tooltipTarget.tooltipShow, 'emit'); + vi.spyOn(tooltipTarget.tooltipHide, 'emit'); const tooltipShowArgs = { target: tooltipTarget, tooltip: fix.componentInstance.tooltip, cancel: false }; const tooltipHideArgs = { target: tooltipTarget, tooltip: fix.componentInstance.tooltip, cancel: false }; @@ -603,7 +604,7 @@ describe('IgxTooltip', () => { const arrowTopOffset = '-4px'; const arrowLeftOffset = getArrowLeftOffset(tooltip) + 'px'; - expect(tooltip.arrow.classList.contains(arrowClassName)).toBeTrue(); + expect(tooltip.arrow.classList.contains(arrowClassName)).toBe(true); expect(tooltip.arrow.style.top).toBe(arrowTopOffset); expect(tooltip.arrow.style.left).toBe(arrowLeftOffset); }; @@ -625,19 +626,19 @@ describe('IgxTooltip', () => { hoverElement(tooltipTarget1); flush(); verifyTooltipVisibility(tooltip1.element, tooltipTarget1, true); - expect(tooltipTarget1.hasArrow).toBeTrue(); + expect(tooltipTarget1.hasArrow).toBe(true); verifyTooltipArrowAlignment(tooltip1); hoverElement(tooltipTarget2); flush(); verifyTooltipVisibility(tooltip2.element, tooltipTarget2, true); - expect(tooltipTarget2.hasArrow).toBeTrue(); + expect(tooltipTarget2.hasArrow).toBe(true); verifyTooltipArrowAlignment(tooltip2); hoverElement(tooltipTarget3); flush(); verifyTooltipVisibility(tooltip3.element, tooltipTarget3, true); - expect(tooltipTarget3.hasArrow).toBeTrue(); + expect(tooltipTarget3.hasArrow).toBe(true); verifyTooltipArrowAlignment(tooltip3); })); @@ -748,8 +749,8 @@ describe('IgxTooltip', () => { })); it('should not emit tooltipHide event multiple times', fakeAsync(() => { - spyOn(targetOne.tooltipHide, 'emit'); - spyOn(targetTwo.tooltipHide, 'emit'); + vi.spyOn(targetOne.tooltipHide, 'emit'); + vi.spyOn(targetTwo.tooltipHide, 'emit'); hoverElement(buttonOne); flush(); @@ -759,7 +760,8 @@ describe('IgxTooltip', () => { unhoverElement(buttonOne); tick(500); - expect(targetOne.tooltipHide.emit).toHaveBeenCalledOnceWith(tooltipHideArgsTargetOne); + expect(targetOne.tooltipHide.emit).toHaveBeenCalledTimes(1); + expect(targetOne.tooltipHide.emit).toHaveBeenCalledWith(tooltipHideArgsTargetOne); expect(targetTwo.tooltipHide.emit).not.toHaveBeenCalled(); flush(); @@ -768,8 +770,10 @@ describe('IgxTooltip', () => { unhoverElement(buttonTwo); tick(500); - expect(targetOne.tooltipHide.emit).toHaveBeenCalledOnceWith(tooltipHideArgsTargetOne); - expect(targetTwo.tooltipHide.emit).toHaveBeenCalledOnceWith(tooltipHideArgsTargetTwo); + expect(targetOne.tooltipHide.emit).toHaveBeenCalledTimes(1); + expect(targetOne.tooltipHide.emit).toHaveBeenCalledWith(tooltipHideArgsTargetOne); + expect(targetTwo.tooltipHide.emit).toHaveBeenCalledTimes(1); + expect(targetTwo.tooltipHide.emit).toHaveBeenCalledWith(tooltipHideArgsTargetTwo); flush(); })); @@ -1070,9 +1074,9 @@ describe('IgxTooltip', () => { cancelable: true }); document.dispatchEvent(escapeEvent); - flush() + flush(); - verifyTooltipVisibility(tooltipNativeElement, tooltipTarget, false) + verifyTooltipVisibility(tooltipNativeElement, tooltipTarget, false); })); it('should correctly display a sticky tooltip on custom show trigger', fakeAsync(() => { @@ -1149,11 +1153,11 @@ describe('IgxTooltip', () => { expect(arrow).not.toBeNull(); expect(arrow.style.left).toBe(""); })); - }) + }); }); interface ElementRefLike { - nativeElement: HTMLElement + nativeElement: HTMLElement; } const hoverElement = (element: ElementRefLike) => element.nativeElement.dispatchEvent(new MouseEvent('pointerenter')); @@ -1172,13 +1176,9 @@ const directionTolerance = 2; const alignmentTolerance = 2; -export const verifyTooltipPosition = ( - tooltipNativeElement: HTMLElement, - actualTarget: { nativeElement: HTMLElement }, - shouldAlign:boolean = true, - placement: Placement = Placement.Bottom, - offset: number = 6 -) => { +export const verifyTooltipPosition = (tooltipNativeElement: HTMLElement, actualTarget: { + nativeElement: HTMLElement; +}, shouldAlign: boolean = true, placement: Placement = Placement.Bottom, offset: number = 6) => { const tooltip = tooltipNativeElement.getBoundingClientRect(); const target = actualTarget.nativeElement.getBoundingClientRect(); @@ -1213,21 +1213,13 @@ export const verifyTooltipPosition = ( const result = directionCheckPassed && alignmentCheckPassed; if (shouldAlign) { - expect(result).toBeTruthy( - `Tooltip misaligned for "${placement}": actual offset=${actualOffset}, wanted offset=${offset}, accurate placement=${directionCheckPassed}, accurate alignment=${alignmentCheckPassed}` - ); + expect(result).toBeTruthy(`Tooltip misaligned for "${placement}": actual offset=${actualOffset}, wanted offset=${offset}, accurate placement=${directionCheckPassed}, accurate alignment=${alignmentCheckPassed}`); } else { - expect(result).toBeFalsy( - `Tooltip was unexpectedly aligned` - ); + expect(result).toBeFalsy(`Tooltip was unexpectedly aligned`); } }; -function horizontalAlignmentMatches( - tooltip: DOMRect, - target: DOMRect, - placement: Placement -): boolean { +function horizontalAlignmentMatches(tooltip: DOMRect, target: DOMRect, placement: Placement): boolean { if (placement.endsWith('start')) { return Math.abs(tooltip.left - target.left) <= alignmentTolerance; } else if (placement.endsWith('end')) { @@ -1239,11 +1231,7 @@ function horizontalAlignmentMatches( } } -function verticalAlignmentMatches( - tooltip: DOMRect, - target: DOMRect, - placement: Placement -): boolean { +function verticalAlignmentMatches(tooltip: DOMRect, target: DOMRect, placement: Placement): boolean { if (placement.endsWith('start')) { return Math.abs(tooltip.top - target.top) <= alignmentTolerance; } else if (placement.endsWith('end')) { diff --git a/projects/igniteui-angular/drop-down/src/drop-down/autocomplete/autocomplete.directive.spec.ts b/projects/igniteui-angular/drop-down/src/drop-down/autocomplete/autocomplete.directive.spec.ts index 5d61ef65741..1f19cd1a85c 100644 --- a/projects/igniteui-angular/drop-down/src/drop-down/autocomplete/autocomplete.directive.spec.ts +++ b/projects/igniteui-angular/drop-down/src/drop-down/autocomplete/autocomplete.directive.spec.ts @@ -10,6 +10,7 @@ import { ConnectedPositioningStrategy, VerticalAlignment, HorizontalAlignment } import { IgxRippleDirective } from '../../../../directives/src/directives/ripple/ripple.directive'; import { IgxIconComponent } from '../../../../icon/src/icon/icon.component'; import { IgxInputDirective, IgxInputGroupComponent, IgxLabelDirective, IgxPrefixDirective, IgxSuffixDirective } from 'igniteui-angular/input-group'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const CSS_CLASS_DROPDOWNLIST = 'igx-drop-down__list'; const CSS_CLASS_DROPDOWNLIST_SCROLL = 'igx-drop-down__list-scroll'; @@ -121,9 +122,9 @@ describe('IgxAutocomplete', () => { })); it('Should close the dropdown when no items match the filter', fakeAsync(() => { expect((autocomplete as any).collapsed).toEqual(true); - spyOn(autocomplete.target, 'close').and.callThrough(); - spyOn(autocomplete, 'open').and.callThrough(); - spyOn(autocomplete.target, 'open').and.callThrough(); + vi.spyOn(autocomplete.target, 'close'); + vi.spyOn(autocomplete, 'open'); + vi.spyOn(autocomplete.target, 'open'); expect(autocomplete.target.close).not.toHaveBeenCalled(); UIInteractions.setInputElementValue(input, 'a', fixture); tick(); @@ -150,8 +151,8 @@ describe('IgxAutocomplete', () => { })); it('Should close the dropdown when disabled dynamically', fakeAsync(() => { - spyOn(autocomplete.target, 'open').and.callThrough(); - spyOn(autocomplete.target, 'close').and.callThrough(); + vi.spyOn(autocomplete.target, 'open'); + vi.spyOn(autocomplete.target, 'close'); UIInteractions.setInputElementValue(input, 's', fixture); tick(); @@ -190,9 +191,7 @@ describe('IgxAutocomplete', () => { // Click in center of the body. const bodyRect = document.body.getBoundingClientRect(); - UIInteractions.simulateMouseEvent('click', document.body, - bodyRect.left + bodyRect.width / 2, - bodyRect.top + bodyRect.height / 2); + UIInteractions.simulateMouseEvent('click', document.body, bodyRect.left + bodyRect.width / 2, bodyRect.top + bodyRect.height / 2); tick(); fixture.detectChanges(); expect(dropDown.collapsed).toBeTruthy(); @@ -312,7 +311,7 @@ describe('IgxAutocomplete', () => { }); it('Should not open dropdown when disabled', fakeAsync(() => { fixture.detectChanges(); - spyOn(autocomplete.target, 'open').and.callThrough(); + vi.spyOn(autocomplete.target, 'open'); const dropdownListScrollElement = fixture.debugElement.query(By.css('.' + CSS_CLASS_DROPDOWNLIST_SCROLL)); autocomplete.disabled = true; @@ -388,10 +387,9 @@ describe('IgxAutocomplete', () => { for (let itemIndex = 0; itemIndex < filteredTowns.length; itemIndex++) { const itemElement = dropdownListScrollElement.children[itemIndex].nativeElement; expect(itemElement.textContent.trim()). - toEqual(filteredTowns[itemIndex]); + toEqual(filteredTowns[itemIndex]); const isFocused = itemIndex === 0 ? true : false; - const hasFocusedClass = - itemElement.classList.contains(CSS_CLASS_DROP_DOWN_ITEM_FOCUSED); + const hasFocusedClass = itemElement.classList.contains(CSS_CLASS_DROP_DOWN_ITEM_FOCUSED); if (isFocused) { expect(hasFocusedClass).toBeTruthy(); } else { @@ -585,7 +583,7 @@ describe('IgxAutocomplete', () => { it('Should trigger selectionChanging event on item selection', fakeAsync(() => { let startsWith = 'st'; let filteredTowns = fixture.componentInstance.filterTowns(startsWith); - spyOn(autocomplete.selectionChanging, 'emit').and.callThrough(); + vi.spyOn(autocomplete.selectionChanging, 'emit'); UIInteractions.setInputElementValue(input, startsWith, fixture); tick(); @@ -616,7 +614,7 @@ describe('IgxAutocomplete', () => { expect(fixture.componentInstance.townSelected).toBe('s'); })); it('Should trigger selectionChanging only once when the event is cancelled (issue #7483)', fakeAsync(() => { - spyOn(autocomplete.selectionChanging, 'emit').and.callThrough(); + vi.spyOn(autocomplete.selectionChanging, 'emit'); fixture.componentInstance.selectionChanging = (args) => { args.cancel = true; @@ -646,12 +644,12 @@ describe('IgxAutocomplete', () => { })); it('Should call onInput/open/close methods properly', fakeAsync(() => { let startsWith = 'g'; - spyOn(autocomplete, 'onInput').and.callThrough(); - spyOn(autocomplete, 'handleKeyDown').and.callThrough(); - spyOn(autocomplete, 'close').and.callThrough(); - spyOn(autocomplete.target, 'close').and.callThrough(); - spyOn(autocomplete.target, 'open').and.callThrough(); - spyOn(autocomplete.target.opening, 'emit').and.callThrough(); + vi.spyOn(autocomplete, 'onInput'); + vi.spyOn(autocomplete, 'handleKeyDown'); + vi.spyOn(autocomplete, 'close'); + vi.spyOn(autocomplete.target, 'close'); + vi.spyOn(autocomplete.target, 'open'); + vi.spyOn(autocomplete.target.opening, 'emit'); UIInteractions.setInputElementValue(input, startsWith, fixture); tick(); @@ -681,7 +679,7 @@ describe('IgxAutocomplete', () => { expect(autocomplete.target.close).toHaveBeenCalledTimes(2); // IgxDropDownItemNavigationDirective handleKeyDown is not called when dropdown is closed - spyOn(IgxDropDownItemNavigationDirective.prototype, 'handleKeyDown').and.callThrough(); + vi.spyOn(IgxDropDownItemNavigationDirective.prototype, 'handleKeyDown'); UIInteractions.triggerKeyDownEvtUponElem('ArrowDown', input.nativeElement, true); fixture.detectChanges(); tick(); @@ -726,9 +724,9 @@ describe('IgxAutocomplete', () => { const mockObj = { key: 'Home', code: 'Home', - preventDefault: () => {} + preventDefault: () => { } }; - spyOn(mockObj, 'preventDefault'); + vi.spyOn(mockObj, 'preventDefault'); const inputDebug = fixture.debugElement.queryAll(By.css('.' + INPUT_CSS_CLASS))[0]; inputDebug.triggerEventHandler('keydown', mockObj); expect(mockObj.preventDefault).not.toHaveBeenCalled(); @@ -965,10 +963,14 @@ export class IgxAutocompletePipeStartsWith implements PipeTransform { ] }) class AutocompleteComponent { - @ViewChild(IgxAutocompleteDirective, { static: true }) public autocomplete: IgxAutocompleteDirective; - @ViewChild(IgxInputGroupComponent, { static: true }) public group: IgxInputGroupComponent; - @ViewChild(IgxInputDirective, { static: true }) public input: IgxInputDirective; - @ViewChild(IgxDropDownComponent, { static: true }) public dropDown: IgxDropDownComponent; + @ViewChild(IgxAutocompleteDirective, { static: true }) + public autocomplete: IgxAutocompleteDirective; + @ViewChild(IgxInputGroupComponent, { static: true }) + public group: IgxInputGroupComponent; + @ViewChild(IgxInputDirective, { static: true }) + public input: IgxInputDirective; + @ViewChild(IgxDropDownComponent, { static: true }) + public dropDown: IgxDropDownComponent; public townSelected; public towns; public ddWidth = null; @@ -1010,8 +1012,10 @@ class AutocompleteComponent { ] }) class AutocompleteInputComponent extends AutocompleteComponent { - @ViewChild('plainInput', { static: true }) public plainInput: ElementRef; - @ViewChild('textarea', { static: true }) public textarea: ElementRef; + @ViewChild('plainInput', { static: true }) + public plainInput: ElementRef; + @ViewChild('textarea', { static: true }) + public textarea: ElementRef; } @Component({ @@ -1052,11 +1056,16 @@ class AutocompleteInputComponent extends AutocompleteComponent { }) class AutocompleteFormComponent { - @ViewChild(IgxAutocompleteDirective, { static: true }) public autocomplete: IgxAutocompleteDirective; - @ViewChild(IgxInputGroupComponent, { static: true }) public group: IgxInputGroupComponent; - @ViewChild(IgxInputDirective, { static: true }) public input: IgxInputDirective; - @ViewChild(IgxDropDownComponent, { static: true }) public dropDown: IgxDropDownComponent; - @ViewChild('plainInput', { static: true }) public plainInput: ElementRef; + @ViewChild(IgxAutocompleteDirective, { static: true }) + public autocomplete: IgxAutocompleteDirective; + @ViewChild(IgxInputGroupComponent, { static: true }) + public group: IgxInputGroupComponent; + @ViewChild(IgxInputDirective, { static: true }) + public input: IgxInputDirective; + @ViewChild(IgxDropDownComponent, { static: true }) + public dropDown: IgxDropDownComponent; + @ViewChild('plainInput', { static: true }) + public plainInput: ElementRef; public towns: string[]; public reactiveForm: UntypedFormGroup; diff --git a/projects/igniteui-angular/drop-down/src/drop-down/drop-down.component.spec.ts b/projects/igniteui-angular/drop-down/src/drop-down/drop-down.component.spec.ts index cd854d289a5..1909d21d431 100644 --- a/projects/igniteui-angular/drop-down/src/drop-down/drop-down.component.spec.ts +++ b/projects/igniteui-angular/drop-down/src/drop-down/drop-down.component.spec.ts @@ -1,3 +1,4 @@ +import type { Mock } from "vitest"; import { Component, ViewChild, OnInit, ElementRef, ViewChildren, QueryList, ChangeDetectorRef, DOCUMENT } from '@angular/core'; import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; @@ -16,6 +17,7 @@ import { IgxDropDownItemBaseDirective } from './drop-down-item.base'; import { IgxSelectionAPIService } from 'igniteui-angular/core'; import { IgxButtonDirective } from '../../../directives/src/directives/button/button.directive'; import { ConnectedPositioningStrategy, HorizontalAlignment, OverlaySettings, VerticalAlignment } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const CSS_CLASS_DROP_DOWN_BASE = 'igx-drop-down'; const CSS_CLASS_LIST = 'igx-drop-down__list'; @@ -39,14 +41,28 @@ describe('IgxDropDown ', () => { { value: 'Item2', index: 2 } as IgxDropDownItemComponent, { value: 'Item3', index: 3 } as IgxDropDownItemComponent, { value: 'Item4', index: 4 } as IgxDropDownItemComponent, - { value: 'Item5', index: 5 } as IgxDropDownItemComponent]; + { value: 'Item5', index: 5 } as IgxDropDownItemComponent + ]; const mockSelection: { - [key: string]: jasmine.Spy; - } = jasmine.createSpyObj('IgxSelectionAPIService', ['get', 'set', 'add_items', 'select_items', 'delete']); - const mockCdr = jasmine.createSpyObj('ChangeDetectorRef', ['markForCheck', 'detectChanges']); - mockSelection.get.and.returnValue(new Set([])); - const mockForOf = jasmine.createSpyObj('IgxForOfDirective', ['totalItemCount']); - const mockDocument = jasmine.createSpyObj('DOCUMENT', [], { 'defaultView': { getComputedStyle: () => null }}); + [key: string]: Mock; + } = { + get: vi.fn().mockName("IgxSelectionAPIService.get"), + set: vi.fn().mockName("IgxSelectionAPIService.set"), + add_items: vi.fn().mockName("IgxSelectionAPIService.add_items"), + select_items: vi.fn().mockName("IgxSelectionAPIService.select_items"), + delete: vi.fn().mockName("IgxSelectionAPIService.delete") + }; + const mockCdr = { + markForCheck: vi.fn().mockName("ChangeDetectorRef.markForCheck"), + detectChanges: vi.fn().mockName("ChangeDetectorRef.detectChanges") + }; + mockSelection.get.mockReturnValue(new Set([])); + const mockForOf = { + totalItemCount: vi.fn().mockName("IgxForOfDirective.totalItemCount") + }; + const mockDocument = { + 'defaultView': { getComputedStyle: () => null } + }; beforeEach(() => { TestBed.configureTestingModule({ @@ -63,8 +79,8 @@ describe('IgxDropDown ', () => { }); it('should notify when selection has changed', () => { (dropdown as any).virtDir = mockForOf; - spyOnProperty(dropdown, 'items', 'get').and.returnValue(data); - spyOn(dropdown.selectionChanging, 'emit').and.callThrough(); + vi.spyOn(dropdown, 'items', 'get').mockReturnValue(data); + vi.spyOn(dropdown.selectionChanging, 'emit'); dropdown.selectItem(data[0]); expect(dropdown.selectedItem).toEqual(data[0]); @@ -76,8 +92,8 @@ describe('IgxDropDown ', () => { }); it('should fire selectionChanging with correct args', () => { (dropdown as any).virtDir = mockForOf; - spyOnProperty(dropdown, 'items', 'get').and.returnValue(data); - spyOn(dropdown.selectionChanging, 'emit').and.callThrough(); + vi.spyOn(dropdown, 'items', 'get').mockReturnValue(data); + vi.spyOn(dropdown.selectionChanging, 'emit'); const selectionArgs: ISelectionEventArgs = { newSelection: dropdown.items[1], @@ -99,9 +115,9 @@ describe('IgxDropDown ', () => { }); it('should notify when selection is cleared', () => { (dropdown as any).virtDir = mockForOf; - spyOnProperty(dropdown, 'items', 'get').and.returnValue(data); - spyOn(dropdown.selectionChanging, 'emit').and.callThrough(); - spyOn(dropdown.closed, 'emit').and.callThrough(); + vi.spyOn(dropdown, 'items', 'get').mockReturnValue(data); + vi.spyOn(dropdown.selectionChanging, 'emit'); + vi.spyOn(dropdown.closed, 'emit'); dropdown.selectItem(data[1]); const selected = dropdown.selectedItem; @@ -129,7 +145,7 @@ describe('IgxDropDown ', () => { it('setSelectedItem should return selected item', () => { (dropdown as any).virtDir = mockForOf; (dropdown as any).virtDir.igxForOf = data; - spyOnProperty(dropdown, 'items', 'get').and.returnValue(data); + vi.spyOn(dropdown, 'items', 'get').mockReturnValue(data); expect(dropdown.selectedItem).toBeNull(); @@ -141,7 +157,7 @@ describe('IgxDropDown ', () => { it('setSelectedItem should return null when selection is cleared', () => { (dropdown as any).virtDir = mockForOf; (dropdown as any).virtDir.igxForOf = data; - spyOnProperty(dropdown, 'items', 'get').and.returnValue(data); + vi.spyOn(dropdown, 'items', 'get').mockReturnValue(data); dropdown.setSelectedItem(3); expect(dropdown.selectedItem).toBeTruthy(); @@ -152,28 +168,30 @@ describe('IgxDropDown ', () => { }); it('toggle should call open method when dropdown is collapsed', () => { (dropdown as any).virtDir = mockForOf; - spyOnProperty(dropdown, 'items', 'get').and.returnValue(data); - spyOnProperty(dropdown, 'collapsed', 'get').and.returnValue(true); - spyOn(dropdown, 'open'); + vi.spyOn(dropdown, 'items', 'get').mockReturnValue(data); + vi.spyOn(dropdown, 'collapsed', 'get').mockReturnValue(true); + vi.spyOn(dropdown, 'open'); dropdown.toggle(); expect(dropdown.open).toHaveBeenCalledTimes(1); }); it('toggle should call close method when dropdown is opened', () => { (dropdown as any).virtDir = mockForOf; - const mockToggle = jasmine.createSpyObj('IgxToggleDirective', ['open']); + const mockToggle = { + open: vi.fn().mockName("IgxToggleDirective.open") + }; mockToggle.isClosing = false; (dropdown as any).toggleDirective = mockToggle; - spyOnProperty(dropdown, 'items', 'get').and.returnValue(data); - spyOnProperty(dropdown, 'collapsed', 'get').and.returnValue(false); - spyOn(dropdown, 'close'); + vi.spyOn(dropdown, 'items', 'get').mockReturnValue(data); + vi.spyOn(dropdown, 'collapsed', 'get').mockReturnValue(false); + vi.spyOn(dropdown, 'close'); dropdown.toggle(); expect(dropdown.close).toHaveBeenCalledTimes(1); }); it('should remove selection on destroy', () => { const selectionService = TestBed.inject(IgxSelectionAPIService); - const selectionDeleteSpy = spyOn(selectionService, 'delete'); + const selectionDeleteSpy = vi.spyOn(selectionService, 'delete'); dropdown.ngOnDestroy(); expect(selectionDeleteSpy).toHaveBeenCalled(); }); @@ -194,10 +212,10 @@ describe('IgxDropDown ', () => { dropdown = fixture.componentInstance.dropdown; }); it('should toggle drop down on open/close methods call', fakeAsync(() => { - spyOn(dropdown, 'onToggleOpening'); - spyOn(dropdown, 'onToggleOpened'); - spyOn(dropdown, 'onToggleClosing'); - spyOn(dropdown, 'onToggleClosed'); + vi.spyOn(dropdown, 'onToggleOpening'); + vi.spyOn(dropdown, 'onToggleOpened'); + vi.spyOn(dropdown, 'onToggleClosing'); + vi.spyOn(dropdown, 'onToggleClosed'); expect(dropdown.collapsed).toBeTruthy(); dropdown.open(); @@ -215,8 +233,8 @@ describe('IgxDropDown ', () => { expect(dropdown.onToggleClosed).toHaveBeenCalledTimes(1); })); it('#3810 - should not emit events when calling open on opened dropdown', fakeAsync(() => { - spyOn(dropdown.opening, 'emit').and.callThrough(); - spyOn(dropdown.opened, 'emit').and.callThrough(); + vi.spyOn(dropdown.opening, 'emit'); + vi.spyOn(dropdown.opened, 'emit'); dropdown.open(); tick(); @@ -235,13 +253,13 @@ describe('IgxDropDown ', () => { it('should use default overlay settings if none are provided', () => { const toggle: IgxToggleDirective = (dropdown as any).toggleDirective; - spyOn(toggle, 'open').and.callThrough(); + vi.spyOn(toggle, 'open'); dropdown.open(); fixture.detectChanges(); expect(toggle.open).toHaveBeenCalledTimes(1); - const appliedSettings = (toggle.open as jasmine.Spy).calls.mostRecent().args[0]; + const appliedSettings = vi.mocked((toggle.open as Mock)).mock.lastCall[0]; expect(appliedSettings.closeOnOutsideClick).toBe(true); expect(appliedSettings.modal).toBe(false); expect(appliedSettings.positionStrategy instanceof ConnectedPositioningStrategy).toBe(true); @@ -265,13 +283,13 @@ describe('IgxDropDown ', () => { }) }; - spyOn(toggle, 'open').and.callThrough(); + vi.spyOn(toggle, 'open'); dropdown.open(customOverlaySettings); fixture.detectChanges(); expect(toggle.open).toHaveBeenCalledTimes(1); - const appliedSettings = (toggle.open as jasmine.Spy).calls.mostRecent().args[0]; + const appliedSettings = vi.mocked((toggle.open as Mock)).mock.lastCall[0]; expect(appliedSettings.closeOnOutsideClick).toBe(customOverlaySettings.closeOnOutsideClick); expect(appliedSettings.modal).toBe(customOverlaySettings.modal); expect(appliedSettings.positionStrategy instanceof ConnectedPositioningStrategy).toBe(true); @@ -284,10 +302,10 @@ describe('IgxDropDown ', () => { }); it('#2798 - should allow canceling of open/close through opening/closing events', fakeAsync(() => { const toggle: IgxToggleDirective = (dropdown as any).toggleDirective; - const onOpeningSpy = spyOn(dropdown.opening, 'emit').and.callThrough(); - const onOpenedSpy = spyOn(dropdown.opened, 'emit').and.callThrough(); - spyOn(dropdown.closing, 'emit').and.callThrough(); - spyOn(dropdown.closed, 'emit').and.callThrough(); + const onOpeningSpy = vi.spyOn(dropdown.opening, 'emit'); + const onOpenedSpy = vi.spyOn(dropdown.opened, 'emit'); + vi.spyOn(dropdown.closing, 'emit'); + vi.spyOn(dropdown.closed, 'emit'); dropdown.closing.pipe(take(1)).subscribe((e: CancelableEventArgs) => e.cancel = true); @@ -307,8 +325,8 @@ describe('IgxDropDown ', () => { toggle.close(); fixture.detectChanges(); - onOpeningSpy.calls.reset(); - onOpenedSpy.calls.reset(); + onOpeningSpy.mockClear(); + onOpenedSpy.mockClear(); dropdown.opening.pipe(take(1)).subscribe((e: CancelableEventArgs) => e.cancel = true); dropdown.toggle(); @@ -361,11 +379,11 @@ describe('IgxDropDown ', () => { expect(dropdown.collapsed).toEqual(false); })); it('should close the dropdown and not change selection by pressing ESC key', fakeAsync(() => { - spyOn(dropdown.selectionChanging, 'emit').and.callThrough(); - spyOn(dropdown.opening, 'emit').and.callThrough(); - spyOn(dropdown.opened, 'emit').and.callThrough(); - spyOn(dropdown.closing, 'emit').and.callThrough(); - spyOn(dropdown.closed, 'emit').and.callThrough(); + vi.spyOn(dropdown.selectionChanging, 'emit'); + vi.spyOn(dropdown.opening, 'emit'); + vi.spyOn(dropdown.opened, 'emit'); + vi.spyOn(dropdown.closing, 'emit'); + vi.spyOn(dropdown.closed, 'emit'); dropdown.toggle(); tick(); @@ -541,7 +559,7 @@ describe('IgxDropDown ', () => { expect(dropdown.selectedItem.itemIndex).toEqual(2); })); it('should return the proper eventArgs if selection has been cancelled', fakeAsync(() => { - spyOn(dropdown.selectionChanging, 'emit').and.callThrough(); + vi.spyOn(dropdown.selectionChanging, 'emit'); dropdown.toggle(); tick(); @@ -571,7 +589,7 @@ describe('IgxDropDown ', () => { expect(dropdown.selectionChanging.emit).toHaveBeenCalledWith(canceledSelectionArgs); })); it('should provide correct event argument when closing through keyboard', fakeAsync(() => { - spyOn(dropdown.closing, 'emit').and.callThrough(); + vi.spyOn(dropdown.closing, 'emit'); const dropdownElement = fixture.debugElement.query(By.css(`.${CSS_CLASS_DROP_DOWN_BASE}`)); dropdown.toggle(); @@ -642,7 +660,7 @@ describe('IgxDropDown ', () => { expectedSelected = dropdown.items[4]; dropdown.items[4].isHeader = true; - spyOn(dropdown, 'selectItem').and.callThrough(); + vi.spyOn(dropdown, 'selectItem'); expect(() => { dropdown.selectItem(calledSelected); }).toThrow(); @@ -855,8 +873,8 @@ describe('IgxDropDown ', () => { const itemToClick = fixture.debugElement.queryAll(By.css(`.${CSS_CLASS_ITEM}`))[0]; - const event = new Event('mousedown', { }); - spyOn(event, 'preventDefault'); + const event = new Event('mousedown', {}); + vi.spyOn(event, 'preventDefault'); itemToClick.triggerEventHandler('mousedown', event); fixture.detectChanges(); @@ -867,7 +885,7 @@ describe('IgxDropDown ', () => { fixture.detectChanges(); dropdown = fixture.componentInstance.dropdown; const input = fixture.debugElement.query(By.css('input')); - spyOn(dropdown, 'selectItem').and.callThrough(); + vi.spyOn(dropdown, 'selectItem'); expect(dropdown).toBeDefined(); expect(dropdown.focusedItem).toEqual(null); @@ -956,7 +974,7 @@ describe('IgxDropDown ', () => { expect(firstItemElement.textContent.trim()).toEqual('Item 1990'); expect(lastItemElement.textContent.trim()).toEqual('Item 2000'); }); - xit('Should properly handle keyboard navigation when virtualized', async () => { + it.skip('Should properly handle keyboard navigation when virtualized', async () => { pending('does not have time to focus last item on navigateLast()'); // dropdown.toggle(); // fixture.detectChanges(); @@ -1298,10 +1316,10 @@ describe('IgxDropDown ', () => { const tabs = fixture.debugElement.query(By.css(CSS_CLASS_TABS)); const input = fixture.debugElement.query(By.css('input')); const img = fixture.debugElement.query(By.css('img')); - spyOn(dropdown.opening, 'emit').and.callThrough(); - spyOn(dropdown.opened, 'emit').and.callThrough(); - spyOn(dropdown.closing, 'emit').and.callThrough(); - spyOn(dropdown.closed, 'emit').and.callThrough(); + vi.spyOn(dropdown.opening, 'emit'); + vi.spyOn(dropdown.opened, 'emit'); + vi.spyOn(dropdown.closing, 'emit'); + vi.spyOn(dropdown.closed, 'emit'); tabs.triggerEventHandler('click', UIInteractions.getMouseEvent('click')); tick(); fixture.detectChanges(); diff --git a/projects/igniteui-angular/expansion-panel/src/expansion-panel/expansion-panel.spec.ts b/projects/igniteui-angular/expansion-panel/src/expansion-panel/expansion-panel.spec.ts index 6e6b570d4e7..9ed5ca8e225 100644 --- a/projects/igniteui-angular/expansion-panel/src/expansion-panel/expansion-panel.spec.ts +++ b/projects/igniteui-angular/expansion-panel/src/expansion-panel/expansion-panel.spec.ts @@ -11,6 +11,7 @@ import { IgxListComponent } from 'igniteui-angular/list'; import { IgxListItemComponent } from 'igniteui-angular/list'; import { IGX_EXPANSION_PANEL_DIRECTIVES } from './public_api'; import { IgxGridComponent } from 'igniteui-angular/grids/grid'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const CSS_CLASS_EXPANSION_PANEL = 'igx-expansion-panel'; const CSS_CLASS_PANEL_HEADER = 'igx-expansion-panel__header'; @@ -28,7 +29,7 @@ const CSS_CLASS_GRID = 'igx-grid'; const enum IconPositionClass { LEFT = 'igx-expansion-panel__header-icon--start', RIGHT = 'igx-expansion-panel__header-icon--end', - NONE = 'igx-expansion-panel__header-icon--none', + NONE = 'igx-expansion-panel__header-icon--none' } describe('igxExpansionPanel', () => { @@ -103,14 +104,14 @@ describe('igxExpansionPanel', () => { expect(header.panel).toEqual(panel); expect(header.interaction).toBeDefined(); - spyOn(panel.contentCollapsed, 'emit'); - spyOn(panel.contentExpanded, 'emit'); - spyOn(panel.contentCollapsing, 'emit'); - spyOn(panel.contentExpanding, 'emit'); - spyOn(header.interaction, 'emit').and.callThrough(); - spyOn(panel, 'toggle').and.callThrough(); - spyOn(panel, 'expand').and.callThrough(); - spyOn(panel, 'collapse').and.callThrough(); + vi.spyOn(panel.contentCollapsed, 'emit'); + vi.spyOn(panel.contentExpanded, 'emit'); + vi.spyOn(panel.contentCollapsing, 'emit'); + vi.spyOn(panel.contentExpanding, 'emit'); + vi.spyOn(header.interaction, 'emit'); + vi.spyOn(panel, 'toggle'); + vi.spyOn(panel, 'expand'); + vi.spyOn(panel, 'collapse'); header.onAction(mockEvent); tick(); @@ -206,10 +207,10 @@ describe('igxExpansionPanel', () => { panel.animationSettings = null; expect(panel).toBeTruthy(); - spyOn(panel.contentCollapsed, 'emit'); - spyOn(panel.contentExpanded, 'emit'); - spyOn(panel.contentCollapsing, 'emit'); - spyOn(panel.contentExpanding, 'emit'); + vi.spyOn(panel.contentCollapsed, 'emit'); + vi.spyOn(panel.contentExpanded, 'emit'); + vi.spyOn(panel.contentCollapsing, 'emit'); + vi.spyOn(panel.contentExpanding, 'emit'); panel.toggle(); tick(); @@ -218,7 +219,7 @@ describe('igxExpansionPanel', () => { expect(panel.contentCollapsing.emit).toHaveBeenCalledTimes(0); expect(panel.contentExpanded.emit).toHaveBeenCalledTimes(1); expect(panel.contentExpanding.emit).toHaveBeenCalledTimes(1); - expect(panel.contentExpanding.emit).toHaveBeenCalledBefore(panel.contentExpanded.emit); + expect(Math.min(...vi.mocked(panel.contentExpanding.emit).mock.invocationCallOrder)).toBeLessThan(Math.min(...vi.mocked(panel.contentExpanded.emit).mock.invocationCallOrder)); expect(panel.collapsed).toBeFalsy(); panel.toggle(); @@ -228,7 +229,7 @@ describe('igxExpansionPanel', () => { expect(panel.contentCollapsing.emit).toHaveBeenCalledTimes(1); expect(panel.contentExpanded.emit).toHaveBeenCalledTimes(1); expect(panel.contentExpanding.emit).toHaveBeenCalledTimes(1); - expect(panel.contentCollapsing.emit).toHaveBeenCalledBefore(panel.contentCollapsed.emit); + expect(Math.min(...vi.mocked(panel.contentCollapsing.emit).mock.invocationCallOrder)).toBeLessThan(Math.min(...vi.mocked(panel.contentCollapsed.emit).mock.invocationCallOrder)); expect(panel.collapsed).toBeTruthy(); })); @@ -236,8 +237,8 @@ describe('igxExpansionPanel', () => { const fixture = TestBed.createComponent(IgxExpansionPanelSampleComponent); fixture.detectChanges(); const panel = fixture.componentInstance.panel; - spyOn(panel.contentExpanded, 'emit').and.callThrough(); - spyOn(panel.contentCollapsed, 'emit').and.callThrough(); + vi.spyOn(panel.contentExpanded, 'emit'); + vi.spyOn(panel.contentCollapsed, 'emit'); expect(panel).toBeDefined(); expect(panel.collapsed).toBeTruthy(); expect(panel.contentExpanded.emit).not.toHaveBeenCalled(); @@ -291,14 +292,7 @@ describe('igxExpansionPanel', () => { }); describe('Expansion tests: ', () => { - const verifyPanelExpansionState = ( - collapsed: boolean, - panel: IgxExpansionPanelComponent, - panelContainer: any, - panelHeader: HTMLElement, - button: DebugElement, - timesCollapsed = 0, - timesExpanded = 0) => { + const verifyPanelExpansionState = (collapsed: boolean, panel: IgxExpansionPanelComponent, panelContainer: any, panelHeader: HTMLElement, button: DebugElement, timesCollapsed = 0, timesExpanded = 0) => { expect(panel.collapsed).toEqual(collapsed); const ariaExpanded = collapsed ? 'false' : 'true'; expect(panelHeader.querySelector('div [role = \'button\']').getAttribute('aria-expanded')).toMatch(ariaExpanded); @@ -330,9 +324,9 @@ describe('igxExpansionPanel', () => { let timesCollapsed = 0; let timesExpanded = 0; - spyOn(panel.contentCollapsed, 'emit').and.callThrough(); - spyOn(panel.contentExpanded, 'emit').and.callThrough(); - spyOn(header.interaction, 'emit'); + vi.spyOn(panel.contentCollapsed, 'emit'); + vi.spyOn(panel.contentExpanded, 'emit'); + vi.spyOn(header.interaction, 'emit'); verifyPanelExpansionState(true, panel, panelContainer, panelHeader, button, timesCollapsed, timesExpanded); panelHeader.click(); @@ -391,12 +385,12 @@ describe('igxExpansionPanel', () => { let timesCollapsed = 0; let timesExpanded = 0; - spyOn(panel.contentCollapsed, 'emit').and.callThrough(); - spyOn(panel.contentExpanded, 'emit').and.callThrough(); - spyOn(header.interaction, 'emit'); + vi.spyOn(panel.contentCollapsed, 'emit'); + vi.spyOn(panel.contentExpanded, 'emit'); + vi.spyOn(header.interaction, 'emit'); verifyPanelExpansionState(true, panel, panelContainer, panelHeader, button, timesCollapsed, timesExpanded); - button.nativeElement.click() + button.nativeElement.click(); tick(); fixture.detectChanges(); tick(); @@ -404,7 +398,7 @@ describe('igxExpansionPanel', () => { verifyPanelExpansionState(false, panel, panelContainer, panelHeader, button, timesCollapsed, timesExpanded); expect(header.interaction.emit).toHaveBeenCalledTimes(1); - button.nativeElement.click() + button.nativeElement.click(); tick(); fixture.detectChanges(); tick(); @@ -412,7 +406,7 @@ describe('igxExpansionPanel', () => { verifyPanelExpansionState(true, panel, panelContainer, panelHeader, button, timesCollapsed, timesExpanded); expect(header.interaction.emit).toHaveBeenCalledTimes(2); - button.nativeElement.click() + button.nativeElement.click(); tick(); fixture.detectChanges(); tick(); @@ -427,7 +421,7 @@ describe('igxExpansionPanel', () => { tick(); button = fixture.debugElement.query(By.css('.' + CSS_CLASS_PANEL_ICON)) as DebugElement; - button.nativeElement.click() + button.nativeElement.click(); tick(); fixture.detectChanges(); tick(); @@ -435,7 +429,7 @@ describe('igxExpansionPanel', () => { verifyPanelExpansionState(true, panel, panelContainer, panelHeader, button, timesCollapsed, timesExpanded); expect(header.interaction.emit).toHaveBeenCalledTimes(4); - button.nativeElement.click() + button.nativeElement.click(); tick(); fixture.detectChanges(); tick(); @@ -443,7 +437,7 @@ describe('igxExpansionPanel', () => { verifyPanelExpansionState(false, panel, panelContainer, panelHeader, button, timesCollapsed, timesExpanded); expect(header.interaction.emit).toHaveBeenCalledTimes(5); - button.nativeElement.click() + button.nativeElement.click(); tick(); fixture.detectChanges(); tick(); @@ -458,8 +452,8 @@ describe('igxExpansionPanel', () => { const panelContainer = fixture.nativeElement.querySelector('.' + CSS_CLASS_EXPANSION_PANEL); const panelHeader = fixture.nativeElement.querySelector('.' + CSS_CLASS_PANEL_HEADER) as HTMLElement; const button = fixture.debugElement.query(By.css('.' + CSS_CLASS_PANEL_ICON)) as DebugElement; - spyOn(panel.contentCollapsed, 'emit').and.callThrough(); - spyOn(panel.contentExpanded, 'emit').and.callThrough(); + vi.spyOn(panel.contentCollapsed, 'emit'); + vi.spyOn(panel.contentExpanded, 'emit'); verifyPanelExpansionState(true, panel, panelContainer, panelHeader, button); panel.collapsed = false; @@ -490,8 +484,8 @@ describe('igxExpansionPanel', () => { let timesCollapsed = 0; let timesExpanded = 0; - spyOn(panel.contentCollapsed, 'emit').and.callThrough(); - spyOn(panel.contentExpanded, 'emit').and.callThrough(); + vi.spyOn(panel.contentCollapsed, 'emit'); + vi.spyOn(panel.contentExpanded, 'emit'); verifyPanelExpansionState(true, panel, panelContainer, panelHeader, button, timesCollapsed, timesExpanded); panel.expand(); @@ -532,8 +526,8 @@ describe('igxExpansionPanel', () => { let timesCollapsed = 0; let timesExpanded = 0; - spyOn(panel.contentCollapsed, 'emit').and.callThrough(); - spyOn(panel.contentExpanded, 'emit').and.callThrough(); + vi.spyOn(panel.contentCollapsed, 'emit'); + vi.spyOn(panel.contentExpanded, 'emit'); verifyPanelExpansionState(true, panel, panelContainer, panelHeader, button, timesCollapsed, timesExpanded); panel.toggle(); @@ -579,9 +573,9 @@ describe('igxExpansionPanel', () => { let timesCollapsed = 0; let timesExpanded = 0; - spyOn(panel.contentCollapsed, 'emit').and.callThrough(); - spyOn(panel.contentExpanded, 'emit').and.callThrough(); - spyOn(header.interaction, 'emit').and.callThrough(); + vi.spyOn(panel.contentCollapsed, 'emit'); + vi.spyOn(panel.contentExpanded, 'emit'); + vi.spyOn(header.interaction, 'emit'); verifyPanelExpansionState(true, panel, panelContainer, panelHeader, button, timesCollapsed, timesExpanded); panelHeader.dispatchEvent(enterEvent); @@ -668,10 +662,10 @@ describe('igxExpansionPanel', () => { tick(); fixture.detectChanges(); - // currently expanded - expect(panel.collapsed).toEqual(false); + // currently expanded + expect(panel.collapsed).toEqual(false); - // cancel closing + // cancel closing panelHeader.dispatchEvent(arrowUpEvent); fixture.detectChanges(); tick(); @@ -692,9 +686,9 @@ describe('igxExpansionPanel', () => { let timesCollapsed = 0; let timesExpanded = 0; - spyOn(panel.contentCollapsed, 'emit').and.callThrough(); - spyOn(panel.contentExpanded, 'emit').and.callThrough(); - spyOn(header.interaction, 'emit'); + vi.spyOn(panel.contentCollapsed, 'emit'); + vi.spyOn(panel.contentExpanded, 'emit'); + vi.spyOn(header.interaction, 'emit'); verifyPanelExpansionState(true, panel, panelContainer, panelHeader, button, timesCollapsed, timesExpanded); panel.expand(); @@ -712,7 +706,7 @@ describe('igxExpansionPanel', () => { verifyPanelExpansionState(true, panel, panelContainer, panelHeader, button, timesCollapsed, timesExpanded); expect(header.interaction.emit).toHaveBeenCalledTimes(1); - button.nativeElement.click() + button.nativeElement.click(); tick(); fixture.detectChanges(); tick(); @@ -768,9 +762,9 @@ describe('igxExpansionPanel', () => { let timesCollapsed = 0; const timesExpanded = 1; - spyOn(panel.contentCollapsed, 'emit').and.callThrough(); - spyOn(panel.contentExpanded, 'emit').and.callThrough(); - spyOn(header.interaction, 'emit'); + vi.spyOn(panel.contentCollapsed, 'emit'); + vi.spyOn(panel.contentExpanded, 'emit'); + vi.spyOn(header.interaction, 'emit'); panel.expand(); tick(); @@ -792,7 +786,7 @@ describe('igxExpansionPanel', () => { verifyPanelExpansionState(false, panel, panelContainer, panelHeader, button, timesCollapsed, timesExpanded); expect(header.interaction.emit).toHaveBeenCalledTimes(0); - button.nativeElement.click() + button.nativeElement.click(); tick(); fixture.detectChanges(); tick(); @@ -821,7 +815,7 @@ describe('igxExpansionPanel', () => { verifyPanelExpansionState(true, panel, panelContainer, panelHeader, button, timesCollapsed, timesExpanded); expect(header.interaction.emit).toHaveBeenCalledTimes(0); - button.nativeElement.click() + button.nativeElement.click(); tick(); fixture.detectChanges(); tick(); @@ -946,7 +940,7 @@ describe('igxExpansionPanel', () => { const fixture = TestBed.createComponent(IgxExpansionPanelSampleComponent); fixture.detectChanges(); const panel = fixture.componentInstance.panel; - const animationSpy = spyOn(panel, 'playCloseAnimation'); + const animationSpy = vi.spyOn(panel, 'playCloseAnimation'); panel.collapse(); expect(animationSpy).not.toHaveBeenCalled(); }); @@ -955,7 +949,7 @@ describe('igxExpansionPanel', () => { const fixture = TestBed.createComponent(IgxExpansionPanelSampleComponent); fixture.detectChanges(); const panel = fixture.componentInstance.panel; - const animationSpy = spyOn(panel, 'playOpenAnimation'); + const animationSpy = vi.spyOn(panel, 'playOpenAnimation'); panel.collapse(); expect(animationSpy).not.toHaveBeenCalled(); }); @@ -1244,7 +1238,7 @@ describe('igxExpansionPanel', () => { expect(textWrapper.childElementCount).toEqual(1); const image = textWrapper.children[0] as HTMLElement; expect(image.tagName).toEqual('IMG'); - expect (textWrapper.textContent.trim()).toEqual(fixture.componentInstance.text); + expect(textWrapper.textContent.trim()).toEqual(fixture.componentInstance.text); })); it('Should display tooltip with the title and description text content', () => { const fixture: ComponentFixture = TestBed.createComponent(IgxExpansionPanelTooltipComponent); diff --git a/projects/igniteui-angular/expansion-panel/src/expansion-panel/toggle-animation-component.spec.ts b/projects/igniteui-angular/expansion-panel/src/expansion-panel/toggle-animation-component.spec.ts index f4905be4d77..95225a9fb9e 100644 --- a/projects/igniteui-angular/expansion-panel/src/expansion-panel/toggle-animation-component.spec.ts +++ b/projects/igniteui-angular/expansion-panel/src/expansion-panel/toggle-animation-component.spec.ts @@ -4,12 +4,15 @@ import { noop } from 'rxjs'; import { IgxAngularAnimationService } from 'igniteui-angular/core'; import { ANIMATION_TYPE, ToggleAnimationPlayer } from './toggle-animation-component'; import { growVerIn, growVerOut } from 'igniteui-angular/animations'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; class MockTogglePlayer extends ToggleAnimationPlayer { } describe('Toggle animation component', () => { - const mockBuilder = jasmine.createSpyObj('mockBuilder', ['build'], {}); + const mockBuilder = { + build: vi.fn().mockName("mockBuilder.build") + }; beforeEach(() => { TestBed.configureTestingModule({ imports: [ @@ -24,13 +27,15 @@ describe('Toggle animation component', () => { describe('Unit tests', () => { it('Should initialize player with give settings', () => { const player = TestBed.inject(MockTogglePlayer); - const startPlayerSpy = spyOn(player, 'startPlayer'); - const mockEl = jasmine.createSpyObj('mockRef', ['focus'], {}); + const startPlayerSpy = vi.spyOn(player, 'startPlayer'); + const mockEl = { + focus: vi.fn().mockName("mockRef.focus") + }; player.playOpenAnimation(mockEl); expect(startPlayerSpy).toHaveBeenCalledWith(ANIMATION_TYPE.OPEN, mockEl, noop); player.playCloseAnimation(mockEl); expect(startPlayerSpy).toHaveBeenCalledWith(ANIMATION_TYPE.CLOSE, mockEl, noop); - const mockCB = () => {}; + const mockCB = () => { }; player.playOpenAnimation(mockEl, mockCB); expect(startPlayerSpy).toHaveBeenCalledWith(ANIMATION_TYPE.OPEN, mockEl, mockCB); player.playCloseAnimation(mockEl, mockCB); @@ -54,19 +59,19 @@ describe('Toggle animation component', () => { it('Should not throw if called with a falsy animationSettings value', () => { const player = TestBed.inject(MockTogglePlayer); player.animationSettings = null; - const mockCb = jasmine.createSpy('mockCb'); - const mockElement = jasmine.createSpy('element'); - spyOn(player.openAnimationStart, 'emit'); - spyOn(player.openAnimationDone, 'emit'); - spyOn(player.closeAnimationStart, 'emit'); - spyOn(player.closeAnimationDone, 'emit'); + const mockCb = vi.fn(); + const mockElement = vi.fn(); + vi.spyOn(player.openAnimationStart, 'emit'); + vi.spyOn(player.openAnimationDone, 'emit'); + vi.spyOn(player.closeAnimationStart, 'emit'); + vi.spyOn(player.closeAnimationDone, 'emit'); player.playOpenAnimation({ nativeElement: mockElement }, mockCb); expect(player.openAnimationStart.emit).toHaveBeenCalledTimes(1); expect(player.openAnimationDone.emit).toHaveBeenCalledTimes(1); expect(player.closeAnimationStart.emit).toHaveBeenCalledTimes(0); expect(player.closeAnimationDone.emit).toHaveBeenCalledTimes(0); - expect(player.openAnimationStart.emit).toHaveBeenCalledBefore(player.openAnimationDone.emit); + expect(Math.min(...vi.mocked(player.openAnimationStart.emit).mock.invocationCallOrder)).toBeLessThan(Math.min(...vi.mocked(player.openAnimationDone.emit).mock.invocationCallOrder)); expect(mockCb).toHaveBeenCalledTimes(1); player.playCloseAnimation({ nativeElement: mockElement }, mockCb); @@ -74,7 +79,7 @@ describe('Toggle animation component', () => { expect(player.openAnimationDone.emit).toHaveBeenCalledTimes(1); expect(player.closeAnimationStart.emit).toHaveBeenCalledTimes(1); expect(player.closeAnimationDone.emit).toHaveBeenCalledTimes(1); - expect(player.closeAnimationStart.emit).toHaveBeenCalledBefore(player.closeAnimationDone.emit); + expect(Math.min(...vi.mocked(player.closeAnimationStart.emit).mock.invocationCallOrder)).toBeLessThan(Math.min(...vi.mocked(player.closeAnimationDone.emit).mock.invocationCallOrder)); expect(mockCb).toHaveBeenCalledTimes(2); }); diff --git a/projects/igniteui-angular/grids/core/src/common/random.spec.ts b/projects/igniteui-angular/grids/core/src/common/random.spec.ts index 1f6a6fc56d3..96b760263c8 100644 --- a/projects/igniteui-angular/grids/core/src/common/random.spec.ts +++ b/projects/igniteui-angular/grids/core/src/common/random.spec.ts @@ -1,4 +1,5 @@ import { getUUID } from './random'; +import { describe, it, expect, beforeAll, afterAll } from 'vitest'; describe('Random (crypto.randomUuid()) fallback unit tests', () => { const originalRandomUuid = crypto.randomUUID; @@ -23,4 +24,4 @@ describe('Random (crypto.randomUuid()) fallback unit tests', () => { afterAll(() => { crypto.randomUUID = originalRandomUuid; // Restore the original function }); -}); \ No newline at end of file +}); diff --git a/projects/igniteui-angular/grids/core/src/grid-actions/grid-editing-actions.component.spec.ts b/projects/igniteui-angular/grids/core/src/grid-actions/grid-editing-actions.component.spec.ts index 52e08f45b4f..8383760046e 100644 --- a/projects/igniteui-angular/grids/core/src/grid-actions/grid-editing-actions.component.spec.ts +++ b/projects/igniteui-angular/grids/core/src/grid-actions/grid-editing-actions.component.spec.ts @@ -18,6 +18,7 @@ import { IgxTreeGridComponent } from 'igniteui-angular/grids/tree-grid'; import { IRowDataCancelableEventArgs } from '../common/events'; import { IgxColumnComponent } from '../columns/column.component'; import { IgxGridNavigationService } from 'igniteui-angular'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('igxGridEditingActions #grid ', () => { let fixture; @@ -81,7 +82,7 @@ describe('igxGridEditingActions #grid ', () => { it('should focus the first cell when editing mode is cell', () => { fixture.detectChanges(); - grid.selectRange({rowStart: 0, rowEnd: 0, columnStart: 'ContactName', columnEnd: 'ContactName'}); + grid.selectRange({ rowStart: 0, rowEnd: 0, columnStart: 'ContactName', columnEnd: 'ContactName' }); fixture.detectChanges(); grid.actionStrip.show(grid.rowList.first); fixture.detectChanges(); @@ -95,23 +96,23 @@ describe('igxGridEditingActions #grid ', () => { }); it('should allow hiding/showing the edit/delete actions via the related property.', () => { - const editActions = fixture.componentInstance.actionStrip.actionButtons.first; - editActions.editRow = false; - fixture.detectChanges(); - - grid.actionStrip.show(grid.rowList.first); - fixture.detectChanges(); - let icons = fixture.debugElement.queryAll(By.css(`igx-grid-editing-actions igx-icon`)); - let iconsText = icons.map(x => x.nativeElement.innerText); - expect(iconsText).toEqual(['delete']); - - editActions.editRow = true; - editActions.deleteRow = false; - fixture.detectChanges(); - - icons = fixture.debugElement.queryAll(By.css(`igx-grid-editing-actions igx-icon`)); - iconsText = icons.map(x => x.nativeElement.innerText); - expect(iconsText).toEqual(['edit']); + const editActions = fixture.componentInstance.actionStrip.actionButtons.first; + editActions.editRow = false; + fixture.detectChanges(); + + grid.actionStrip.show(grid.rowList.first); + fixture.detectChanges(); + let icons = fixture.debugElement.queryAll(By.css(`igx-grid-editing-actions igx-icon`)); + let iconsText = icons.map(x => x.nativeElement.innerText); + expect(iconsText).toEqual(['delete']); + + editActions.editRow = true; + editActions.deleteRow = false; + fixture.detectChanges(); + + icons = fixture.debugElement.queryAll(By.css(`igx-grid-editing-actions igx-icon`)); + iconsText = icons.map(x => x.nativeElement.innerText); + expect(iconsText).toEqual(['edit']); }); }); @@ -136,7 +137,7 @@ describe('igxGridEditingActions #grid ', () => { actionStrip.menu.selectItem(editMenuItem); fixture.detectChanges(); - expect(row.inEditMode).toBeTrue(); + expect(row.inEditMode).toBe(true); grid.gridAPI.crudService.endEdit(); fixture.detectChanges(); @@ -170,7 +171,7 @@ describe('igxGridEditingActions #grid ', () => { UIInteractions.simulateMouseEvent('mouseleave', rowElem.element.nativeElement, 0, 200); fixture.detectChanges(); - expect(actionStrip.hidden).toBeFalse(); + expect(actionStrip.hidden).toBe(false); }); }); @@ -194,7 +195,7 @@ describe('igxGridEditingActions #grid ', () => { }); it('should emit correct rowPinning arguments with pinning actions', () => { - spyOn(grid.rowPinning, 'emit').and.callThrough(); + vi.spyOn(grid.rowPinning, 'emit'); const row = grid.getRowByIndex(1); actionStrip.show(grid.rowList.toArray()[1]); @@ -206,7 +207,7 @@ describe('igxGridEditingActions #grid ', () => { expect(grid.rowPinning.emit).toHaveBeenCalledTimes(1); expect(grid.rowPinning.emit).toHaveBeenCalledWith({ - rowID : row.key, + rowID: row.key, rowKey: row.key, insertAtIndex: 0, isPinned: true, @@ -224,7 +225,7 @@ describe('igxGridEditingActions #grid ', () => { expect(grid.rowPinning.emit).toHaveBeenCalledTimes(2); expect(grid.rowPinning.emit).toHaveBeenCalledWith({ - rowID : row5.key, + rowID: row5.key, rowKey: row5.key, insertAtIndex: 1, isPinned: true, @@ -248,7 +249,7 @@ describe('igxGridEditingActions #grid ', () => { fixture.detectChanges(); expect(actionStrip.context).toBe(row); - expect(actionStrip.hidden).toBeFalse(); + expect(actionStrip.hidden).toBe(false); }); it('should auto-hide on mouse leave of row.', async () => { fixture = TestBed.createComponent(IgxActionStripOneRowComponent); @@ -263,22 +264,22 @@ describe('igxGridEditingActions #grid ', () => { actionStrip.show(row); fixture.detectChanges(); - expect(actionStrip.hidden).toBeFalse(); + expect(actionStrip.hidden).toBe(false); UIInteractions.simulateMouseEvent('mouseleave', rowElem.element.nativeElement, 0, 200); fixture.detectChanges(); - expect(actionStrip.hidden).toBeTrue(); + expect(actionStrip.hidden).toBe(true); }); it('should auto-hide on mouse leave of grid.', () => { const row = grid.getRowByIndex(0); actionStrip.show(row); fixture.detectChanges(); - expect(actionStrip.hidden).toBeFalse(); + expect(actionStrip.hidden).toBe(false); UIInteractions.simulateMouseEvent('mouseleave', grid.nativeElement, 0, 0); fixture.detectChanges(); - expect(actionStrip.hidden).toBeTrue(); + expect(actionStrip.hidden).toBe(true); }); it('should auto-hide on delete action click.', () => { @@ -286,14 +287,14 @@ describe('igxGridEditingActions #grid ', () => { actionStrip.show(row); fixture.detectChanges(); - expect(actionStrip.hidden).toBeFalse(); + expect(actionStrip.hidden).toBe(false); const deleteIcon = fixture.debugElement.queryAll(By.css(`igx-grid-editing-actions igx-icon`))[1]; expect(deleteIcon.nativeElement.innerText).toBe('delete'); deleteIcon.parent.triggerEventHandler('click', new Event('click')); fixture.detectChanges(); - expect(actionStrip.hidden).toBeTrue(); + expect(actionStrip.hidden).toBe(true); }); @@ -302,14 +303,14 @@ describe('igxGridEditingActions #grid ', () => { actionStrip.show(row); fixture.detectChanges(); - expect(actionStrip.hidden).toBeFalse(); + expect(actionStrip.hidden).toBe(false); // bind to no data, which removes all rows. grid.data = []; grid.cdr.detectChanges(); - expect((row.cdr as any).destroyed).toBeTrue(); - expect(actionStrip.hidden).toBeTrue(); + expect((row.cdr as any).destroyed).toBe(true); + expect(actionStrip.hidden).toBe(true); }); it('should auto-hide if context row is cached.', () => { @@ -327,16 +328,18 @@ describe('igxGridEditingActions #grid ', () => { fixture.detectChanges(); // not destroyed, but not in DOM anymore - expect((row.cdr as any).destroyed).toBeFalse(); + expect((row.cdr as any).destroyed).toBe(false); expect(row.element.nativeElement.isConnected).toBe(false); // action strip should be hidden - expect(actionStrip.hidden).toBeTrue(); + expect(actionStrip.hidden).toBe(true); }); }); describe('auto show/hide in HierarchicalGrid', () => { - let actionStripRoot; let actionStripChild; let hierarchicalGrid: IgxHierarchicalGridComponent; + let actionStripRoot; + let actionStripChild; + let hierarchicalGrid: IgxHierarchicalGridComponent; beforeEach(() => { fixture = TestBed.createComponent(IgxHierarchicalGridActionStripComponent); fixture.detectChanges(); @@ -352,7 +355,7 @@ describe('igxGridEditingActions #grid ', () => { fixture.detectChanges(); expect(actionStripRoot.context).toBe(row); - expect(actionStripRoot.hidden).toBeFalse(); + expect(actionStripRoot.hidden).toBe(false); expect(actionStripChild.context).toBeUndefined(); }); @@ -369,7 +372,7 @@ describe('igxGridEditingActions #grid ', () => { fixture.detectChanges(); expect(actionStripChild.context).toBe(childRow); - expect(actionStripChild.hidden).toBeFalse(); + expect(actionStripChild.hidden).toBe(false); expect(actionStripRoot.context).toBeUndefined(); }); @@ -389,8 +392,8 @@ describe('igxGridEditingActions #grid ', () => { UIInteractions.simulateMouseEvent('mouseleave', hierarchicalGrid.nativeElement, 0, 0); fixture.detectChanges(); - expect(actionStripRoot.hidden).toBeTrue(); - expect(actionStripChild.hidden).toBeTrue(); + expect(actionStripRoot.hidden).toBe(true); + expect(actionStripChild.hidden).toBe(true); }); }); @@ -404,8 +407,8 @@ describe('igxGridEditingActions #grid ', () => { }); it('should allow deleting row', () => { - spyOn(treeGrid.rowDelete, 'emit').and.callThrough(); - spyOn(treeGrid.rowDeleted, 'emit').and.callThrough(); + vi.spyOn(treeGrid.rowDelete, 'emit'); + vi.spyOn(treeGrid.rowDeleted, 'emit'); const row = treeGrid.rowList.toArray()[0]; actionStrip.show(row); fixture.detectChanges(); @@ -437,8 +440,11 @@ describe('igxGridEditingActions #grid ', () => { deleteChildBtn.actionClick.emit(); fixture.detectChanges(); - expect(treeGrid.rowDelete.emit).toHaveBeenCalledOnceWith(rowDeleteArgs); - expect(treeGrid.rowDeleted.emit).toHaveBeenCalledOnceWith(rowDeletedArgs); + expect(treeGrid.rowDelete.emit).toHaveBeenCalledTimes(1); + + expect(treeGrid.rowDelete.emit).toHaveBeenCalledWith(rowDeleteArgs); + expect(treeGrid.rowDeleted.emit).toHaveBeenCalledTimes(1); + expect(treeGrid.rowDeleted.emit).toHaveBeenCalledWith(rowDeletedArgs); expect(treeGrid.rowList.first.data['ID']).toBe(6); }); }); diff --git a/projects/igniteui-angular/grids/core/src/grid-actions/grid-pinning-actions.component.spec.ts b/projects/igniteui-angular/grids/core/src/grid-actions/grid-pinning-actions.component.spec.ts index f5e53ee37a2..a45077fca9a 100644 --- a/projects/igniteui-angular/grids/core/src/grid-actions/grid-pinning-actions.component.spec.ts +++ b/projects/igniteui-angular/grids/core/src/grid-actions/grid-pinning-actions.component.spec.ts @@ -8,6 +8,7 @@ import { IgxColumnComponent } from '../public_api'; import { SampleTestData } from '../../../../test-utils/sample-test-data.spec'; import { IgxActionStripComponent } from 'igniteui-angular/action-strip'; import { IgxGridComponent } from 'igniteui-angular/grids/grid'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('igxGridPinningActions #grid ', () => { diff --git a/projects/igniteui-angular/grids/core/src/services/csv/csv-exporter-grid.spec.ts b/projects/igniteui-angular/grids/core/src/services/csv/csv-exporter-grid.spec.ts index 86cbf3b58b4..31105047c7d 100644 --- a/projects/igniteui-angular/grids/core/src/services/csv/csv-exporter-grid.spec.ts +++ b/projects/igniteui-angular/grids/core/src/services/csv/csv-exporter-grid.spec.ts @@ -5,12 +5,7 @@ import { TestMethods } from '../exporter-common/test-methods.spec'; import { IgxCsvExporterService } from './csv-exporter'; import { CsvFileTypes, IgxCsvExporterOptions } from './csv-exporter-options'; import { IgxTreeGridPrimaryForeignKeyComponent } from '../../../../../test-utils/tree-grid-components.spec'; -import { ReorderedColumnsComponent, - GridIDNameJobTitleComponent, - ProductsComponent, - ColumnsAddedOnInitComponent, - EmptyGridComponent, - GridCustomSummaryComponent } from '../../../../../test-utils/grid-samples.spec'; +import { ReorderedColumnsComponent, GridIDNameJobTitleComponent, ProductsComponent, ColumnsAddedOnInitComponent, EmptyGridComponent, GridCustomSummaryComponent } from '../../../../../test-utils/grid-samples.spec'; import { SampleTestData } from '../../../../../test-utils/sample-test-data.spec'; import { first } from 'rxjs/operators'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; @@ -23,6 +18,7 @@ import { IgxGridNavigationService, IgxPivotNumericAggregate } from 'igniteui-ang import { DefaultSortingStrategy, FilteringExpressionsTree, FilteringLogic, IgxNumberFilteringOperand, IgxStringFilteringOperand, SortingDirection } from 'igniteui-angular/core'; import { CSVWrapper } from './csv-verification-wrapper.spec'; import { OneGroupThreeColsGridComponent } from '../../../../../test-utils/grid-mch-sample.spec'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; describe('CSV Grid Exporter', () => { let exporter: IgxCsvExporterService; @@ -49,7 +45,7 @@ describe('CSV Grid Exporter', () => { options = new IgxCsvExporterOptions('CsvGridExport', CsvFileTypes.CSV); // Spy the saveBlobToFile method so the files are not really created - spyOn(ExportUtilities as any, 'saveBlobToFile'); + vi.spyOn(ExportUtilities as any, 'saveBlobToFile'); }); afterEach(() => { @@ -96,7 +92,7 @@ describe('CSV Grid Exporter', () => { grid.filter('JobTitle', 'Director', IgxStringFilteringOperand.instance().condition('equals'), true); fix.detectChanges(); - expect(grid.rowList.length).toEqual(2, 'Invalid number of rows after filtering!'); + expect(grid.rowList.length, 'Invalid number of rows after filtering!').toEqual(2); wrapper = await getExportedData(grid, options); wrapper.verifyData(wrapper.gridTwoDirectors, 'Two rows should have been exported!'); }); @@ -110,7 +106,7 @@ describe('CSV Grid Exporter', () => { options.ignoreColumnsVisibility = false; fix.detectChanges(); - expect(grid.visibleColumns.length).toEqual(2, 'Invalid number of visible columns!'); + expect(grid.visibleColumns.length, 'Invalid number of visible columns!').toEqual(2); let wrapper = await getExportedData(grid, options); wrapper.verifyData(wrapper.gridNameJobTitle, 'Two columns data should have been exported!'); @@ -128,25 +124,25 @@ describe('CSV Grid Exporter', () => { options.ignoreColumnsOrder = true; fix.detectChanges(); - expect(grid.visibleColumns.length).toEqual(3, 'Invalid number of visible columns!'); + expect(grid.visibleColumns.length, 'Invalid number of visible columns!').toEqual(3); let wrapper = await getExportedData(grid, options); wrapper.verifyData(wrapper.simpleGridData, 'All columns data should have been exported!'); grid.columnList.get(0).hidden = true; fix.detectChanges(); - expect(grid.visibleColumns.length).toEqual(2, 'Invalid number of visible columns!'); + expect(grid.visibleColumns.length, 'Invalid number of visible columns!').toEqual(2); wrapper = await getExportedData(grid, options); wrapper.verifyData(wrapper.gridNameJobTitle, 'Two columns data should have been exported!'); grid.columnList.get(0).hidden = false; fix.detectChanges(); - expect(grid.visibleColumns.length).toEqual(3, 'Invalid number of visible columns!'); + expect(grid.visibleColumns.length, 'Invalid number of visible columns!').toEqual(3); wrapper = await getExportedData(grid, options); wrapper.verifyData(wrapper.simpleGridData, 'All columns data should have been exported!'); grid.columnList.get(0).hidden = undefined; fix.detectChanges(); - expect(grid.visibleColumns.length).toEqual(3, 'Invalid number of visible columns!'); + expect(grid.visibleColumns.length, 'Invalid number of visible columns!').toEqual(3); wrapper = await getExportedData(grid, options); wrapper.verifyData(wrapper.simpleGridData, 'All columns data should have been exported!'); }); @@ -164,7 +160,7 @@ describe('CSV Grid Exporter', () => { const fix = TestBed.createComponent(GridIDNameJobTitleComponent); fix.detectChanges(); const grid = fix.componentInstance.grid; - grid.sort({fieldName: 'Name', dir: SortingDirection.Asc, ignoreCase: true}); + grid.sort({ fieldName: 'Name', dir: SortingDirection.Asc, ignoreCase: true }); fix.detectChanges(); const wrapper = await getExportedData(grid, options); @@ -176,18 +172,18 @@ describe('CSV Grid Exporter', () => { fix.detectChanges(); const grid = fix.componentInstance.grid; - grid.sort({fieldName: 'Name', dir: SortingDirection.Asc, ignoreCase: true}); + grid.sort({ fieldName: 'Name', dir: SortingDirection.Asc, ignoreCase: true }); fix.detectChanges(); let wrapper = await getExportedData(grid, options); wrapper.verifyData(wrapper.sortedSimpleGridData); - grid.sort({fieldName: 'Name', dir: SortingDirection.Desc, ignoreCase: true}); + grid.sort({ fieldName: 'Name', dir: SortingDirection.Desc, ignoreCase: true }); fix.detectChanges(); wrapper = await getExportedData(grid, options); wrapper.verifyData(wrapper.sortedDescSimpleGridData); grid.clearSort(); - grid.sort({fieldName: 'ID', dir: SortingDirection.Asc, ignoreCase: true}); + grid.sort({ fieldName: 'ID', dir: SortingDirection.Asc, ignoreCase: true }); fix.detectChanges(); wrapper = await getExportedData(grid, options); wrapper.verifyData(wrapper.simpleGridData); @@ -414,7 +410,7 @@ describe('CSV Grid Exporter', () => { const wrapper = await getExportedData(grid, options); const exportedData = wrapper['_data']; - expect(exportedData.includes('[object Object]')).toBe(false, 'CSV export should not contain [object Object]'); + expect(exportedData.includes('[object Object]'), 'CSV export should not contain [object Object]').toBe(false); const lines = exportedData.split('\r\n'); @@ -422,11 +418,9 @@ describe('CSV Grid Exporter', () => { const summaryLines = lines.slice(-4); // Verify at least one summary line contains proper formatting (label: value pattern) - const hasProperlySummary = summaryLines.some(line => - line.includes(':') && !line.includes('[object Object]') - ); + const hasProperlySummary = summaryLines.some(line => line.includes(':') && !line.includes('[object Object]')); - expect(hasProperlySummary).toBe(true, 'Summary data should be formatted as "label: value"'); + expect(hasProperlySummary, 'Summary data should be formatted as "label: value"').toBe(true); }); describe('Tree Grid CSV export', () => { @@ -444,7 +438,7 @@ describe('CSV Grid Exporter', () => { }); it('should export sorted tree grid properly.', async () => { - treeGrid.sort({fieldName: 'ID', dir: SortingDirection.Desc, ignoreCase: true, strategy: DefaultSortingStrategy.instance()}); + treeGrid.sort({ fieldName: 'ID', dir: SortingDirection.Desc, ignoreCase: true, strategy: DefaultSortingStrategy.instance() }); options.ignoreSorting = true; fix.detectChanges(); @@ -486,7 +480,7 @@ describe('CSV Grid Exporter', () => { it('should export filtered and sorted tree grid properly.', async () => { treeGrid.filter('ID', 3, IgxNumberFilteringOperand.instance().condition('greaterThan')); fix.detectChanges(); - treeGrid.sort({fieldName: 'Name', dir: SortingDirection.Desc, ignoreCase: true, strategy: DefaultSortingStrategy.instance()}); + treeGrid.sort({ fieldName: 'Name', dir: SortingDirection.Desc, ignoreCase: true, strategy: DefaultSortingStrategy.instance() }); fix.detectChanges(); const wrapper = await getExportedData(treeGrid, options); @@ -511,8 +505,7 @@ describe('CSV Grid Exporter', () => { it('should skip the column formatter when columnExportinging skipFormatter is true.', async () => { treeGrid.columnList.get(3).formatter = ((val: string) => val.toLowerCase()); - treeGrid.columnList.get(4).formatter = ((val: number) => - val * 12 // months + treeGrid.columnList.get(4).formatter = ((val: number) => val * 12 // months ); treeGrid.cdr.detectChanges(); let wrapper = await getExportedData(treeGrid, options); diff --git a/projects/igniteui-angular/grids/core/src/services/csv/csv-exporter.spec.ts b/projects/igniteui-angular/grids/core/src/services/csv/csv-exporter.spec.ts index c4267eaee88..b5cf0bb1a69 100644 --- a/projects/igniteui-angular/grids/core/src/services/csv/csv-exporter.spec.ts +++ b/projects/igniteui-angular/grids/core/src/services/csv/csv-exporter.spec.ts @@ -4,16 +4,17 @@ import { CsvFileTypes, IgxCsvExporterOptions } from './csv-exporter-options'; import { CSVWrapper } from './csv-verification-wrapper.spec'; import { SampleTestData } from '../../../../../test-utils/sample-test-data.spec'; import { first } from 'rxjs/operators'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; describe('CSV exporter', () => { let exporter: IgxCsvExporterService; - const fileTypes = [ CsvFileTypes.CSV, CsvFileTypes.TSV, CsvFileTypes.TAB ]; + const fileTypes = [CsvFileTypes.CSV, CsvFileTypes.TSV, CsvFileTypes.TAB]; beforeEach(() => { exporter = new IgxCsvExporterService(); // Spy the saveBlobToFile method so the files are not really created - spyOn(ExportUtilities as any, 'saveBlobToFile'); + vi.spyOn(ExportUtilities as any, 'saveBlobToFile'); }); afterEach(() => { exporter.columnExporting.unsubscribe(); diff --git a/projects/igniteui-angular/grids/core/src/services/csv/csv-verification-wrapper.spec.ts b/projects/igniteui-angular/grids/core/src/services/csv/csv-verification-wrapper.spec.ts index 45062bdbff1..726469edcb6 100644 --- a/projects/igniteui-angular/grids/core/src/services/csv/csv-verification-wrapper.spec.ts +++ b/projects/igniteui-angular/grids/core/src/services/csv/csv-verification-wrapper.spec.ts @@ -1,3 +1,4 @@ +import { expect } from 'vitest'; export class CSVWrapper { private _data: string; @@ -15,284 +16,284 @@ export class CSVWrapper { public get noHeadersStringData() { return `Column 1${this._eor}` + -`Terrance Orta${this._eor}` + -`Richard Mahoney LongerName${this._eor}` + -`Donna Price${this._eor}` + -`Lisa Landers${this._eor}` + -`Dorothy H. Spencer${this._eor}`; + `Terrance Orta${this._eor}` + + `Richard Mahoney LongerName${this._eor}` + + `Donna Price${this._eor}` + + `Lisa Landers${this._eor}` + + `Dorothy H. Spencer${this._eor}`; } public get noHeadersObjectData() { return `value${this._eor}` + -`1${this._eor}` + -`2${this._eor}` + -`3${this._eor}`; + `1${this._eor}` + + `2${this._eor}` + + `3${this._eor}`; } public get noHeadersNumberData() { return `Column 1${this._eor}` + -`10${this._eor}` + -`20${this._eor}` + -`30${this._eor}`; + `10${this._eor}` + + `20${this._eor}` + + `30${this._eor}`; } public get noHeadersDateTimeData() { return `Column 1${this._eor}` + -`${new Date('2018').toString()}${this._eor}` + -`${new Date(2018, 3, 23).toString()}${this._eor}` + -`${new Date(30).toString()}${this._eor}` + -`${new Date('2018/03/23').toString()}${this._eor}`; + `${new Date('2018').toString()}${this._eor}` + + `${new Date(2018, 3, 23).toString()}${this._eor}` + + `${new Date(30).toString()}${this._eor}` + + `${new Date('2018/03/23').toString()}${this._eor}`; } public get contactsData() { return `name${this._delimiter}phone${this._eor}Terrance Orta${this._delimiter}770-504-2217${this._eor}` + - `Richard Mahoney LongerName${this._delimiter}${this._eor}Donna Price${this._delimiter}859-496-2817${this._eor}` + - `${this._delimiter}901-747-3428${this._eor}Dorothy H. Spencer${this._delimiter}573-394-9254${this._eor}`; + `Richard Mahoney LongerName${this._delimiter}${this._eor}Donna Price${this._delimiter}859-496-2817${this._eor}` + + `${this._delimiter}901-747-3428${this._eor}Dorothy H. Spencer${this._delimiter}573-394-9254${this._eor}`; } public get contactsFunkyData() { return `name${this._delimiter}phone${this._eor}Terrance Mc'Orta${this._delimiter}(+359)770-504-2217 | 2218${this._eor}` + - `Richard Mahoney /LongerName/${this._delimiter}${this._eor}"Donna${this._delimiter} /; Price"${this._delimiter}` + - `859 496 28**${this._eor}"\r\n"${this._delimiter}901-747-3428${this._eor}Dorothy "H." Spencer${this._delimiter}` + - `573-394-9254[fax]${this._eor}"Иван Иванов (1${this._delimiter}2)"${this._delimiter}№ 573-394-9254${this._eor}`; + `Richard Mahoney /LongerName/${this._delimiter}${this._eor}"Donna${this._delimiter} /; Price"${this._delimiter}` + + `859 496 28**${this._eor}"\r\n"${this._delimiter}901-747-3428${this._eor}Dorothy "H." Spencer${this._delimiter}` + + `573-394-9254[fax]${this._eor}"Иван Иванов (1${this._delimiter}2)"${this._delimiter}№ 573-394-9254${this._eor}`; } public get contactsPartialData() { return `name${this._delimiter}phone${this._eor}Terrance Orta${this._delimiter}770-504-2217${this._eor}` + - `Richard Mahoney LongerName${this._delimiter}${this._eor}${this._delimiter}780-555-1331${this._eor}`; + `Richard Mahoney LongerName${this._delimiter}${this._eor}${this._delimiter}780-555-1331${this._eor}`; } public get simpleGridData() { return `ID${this._delimiter}Name${this._delimiter}JobTitle${this._eor}` + - `1${this._delimiter}Casey Houston${this._delimiter}Vice President${this._eor}` + - `2${this._delimiter}Gilberto Todd${this._delimiter}Director${this._eor}` + - `3${this._delimiter}Tanya Bennett${this._delimiter}Director${this._eor}` + - `4${this._delimiter}Jack Simon${this._delimiter}Software Developer${this._eor}` + - `5${this._delimiter}Celia Martinez${this._delimiter}Senior Software Developer${this._eor}` + - `6${this._delimiter}Erma Walsh${this._delimiter}CEO${this._eor}` + - `7${this._delimiter}Debra Morton${this._delimiter}Associate Software Developer${this._eor}` + - `8${this._delimiter}Erika Wells${this._delimiter}Software Development Team Lead${this._eor}` + - `9${this._delimiter}Leslie Hansen${this._delimiter}Associate Software Developer${this._eor}` + - `10${this._delimiter}Eduardo Ramirez${this._delimiter}Manager${this._eor}`; + `1${this._delimiter}Casey Houston${this._delimiter}Vice President${this._eor}` + + `2${this._delimiter}Gilberto Todd${this._delimiter}Director${this._eor}` + + `3${this._delimiter}Tanya Bennett${this._delimiter}Director${this._eor}` + + `4${this._delimiter}Jack Simon${this._delimiter}Software Developer${this._eor}` + + `5${this._delimiter}Celia Martinez${this._delimiter}Senior Software Developer${this._eor}` + + `6${this._delimiter}Erma Walsh${this._delimiter}CEO${this._eor}` + + `7${this._delimiter}Debra Morton${this._delimiter}Associate Software Developer${this._eor}` + + `8${this._delimiter}Erika Wells${this._delimiter}Software Development Team Lead${this._eor}` + + `9${this._delimiter}Leslie Hansen${this._delimiter}Associate Software Developer${this._eor}` + + `10${this._delimiter}Eduardo Ramirez${this._delimiter}Manager${this._eor}`; } public get simpleGridDataFormatted() { return `ID${this._delimiter}Name${this._delimiter}JobTitle${this._eor}` + - `1${this._delimiter}CASEY HOUSTON${this._delimiter}vice president${this._eor}` + - `2${this._delimiter}GILBERTO TODD${this._delimiter}director${this._eor}` + - `3${this._delimiter}TANYA BENNETT${this._delimiter}director${this._eor}` + - `4${this._delimiter}JACK SIMON${this._delimiter}software developer${this._eor}` + - `5${this._delimiter}CELIA MARTINEZ${this._delimiter}senior software developer${this._eor}` + - `6${this._delimiter}ERMA WALSH${this._delimiter}ceo${this._eor}` + - `7${this._delimiter}DEBRA MORTON${this._delimiter}associate software developer${this._eor}` + - `8${this._delimiter}ERIKA WELLS${this._delimiter}software development team lead${this._eor}` + - `9${this._delimiter}LESLIE HANSEN${this._delimiter}associate software developer${this._eor}` + - `10${this._delimiter}EDUARDO RAMIREZ${this._delimiter}manager${this._eor}`; + `1${this._delimiter}CASEY HOUSTON${this._delimiter}vice president${this._eor}` + + `2${this._delimiter}GILBERTO TODD${this._delimiter}director${this._eor}` + + `3${this._delimiter}TANYA BENNETT${this._delimiter}director${this._eor}` + + `4${this._delimiter}JACK SIMON${this._delimiter}software developer${this._eor}` + + `5${this._delimiter}CELIA MARTINEZ${this._delimiter}senior software developer${this._eor}` + + `6${this._delimiter}ERMA WALSH${this._delimiter}ceo${this._eor}` + + `7${this._delimiter}DEBRA MORTON${this._delimiter}associate software developer${this._eor}` + + `8${this._delimiter}ERIKA WELLS${this._delimiter}software development team lead${this._eor}` + + `9${this._delimiter}LESLIE HANSEN${this._delimiter}associate software developer${this._eor}` + + `10${this._delimiter}EDUARDO RAMIREZ${this._delimiter}manager${this._eor}`; } public get sortedSimpleGridData() { return `ID${this._delimiter}Name${this._delimiter}JobTitle${this._eor}` + - `1${this._delimiter}Casey Houston${this._delimiter}Vice President${this._eor}` + - `5${this._delimiter}Celia Martinez${this._delimiter}Senior Software Developer${this._eor}` + - `7${this._delimiter}Debra Morton${this._delimiter}Associate Software Developer${this._eor}` + - `10${this._delimiter}Eduardo Ramirez${this._delimiter}Manager${this._eor}` + - `8${this._delimiter}Erika Wells${this._delimiter}Software Development Team Lead${this._eor}` + - `6${this._delimiter}Erma Walsh${this._delimiter}CEO${this._eor}` + - `2${this._delimiter}Gilberto Todd${this._delimiter}Director${this._eor}` + - `4${this._delimiter}Jack Simon${this._delimiter}Software Developer${this._eor}` + - `9${this._delimiter}Leslie Hansen${this._delimiter}Associate Software Developer${this._eor}` + - `3${this._delimiter}Tanya Bennett${this._delimiter}Director${this._eor}`; + `1${this._delimiter}Casey Houston${this._delimiter}Vice President${this._eor}` + + `5${this._delimiter}Celia Martinez${this._delimiter}Senior Software Developer${this._eor}` + + `7${this._delimiter}Debra Morton${this._delimiter}Associate Software Developer${this._eor}` + + `10${this._delimiter}Eduardo Ramirez${this._delimiter}Manager${this._eor}` + + `8${this._delimiter}Erika Wells${this._delimiter}Software Development Team Lead${this._eor}` + + `6${this._delimiter}Erma Walsh${this._delimiter}CEO${this._eor}` + + `2${this._delimiter}Gilberto Todd${this._delimiter}Director${this._eor}` + + `4${this._delimiter}Jack Simon${this._delimiter}Software Developer${this._eor}` + + `9${this._delimiter}Leslie Hansen${this._delimiter}Associate Software Developer${this._eor}` + + `3${this._delimiter}Tanya Bennett${this._delimiter}Director${this._eor}`; } public get sortedDescSimpleGridData() { return `ID${this._delimiter}Name${this._delimiter}JobTitle${this._eor}` + - `3${this._delimiter}Tanya Bennett${this._delimiter}Director${this._eor}` + - `9${this._delimiter}Leslie Hansen${this._delimiter}Associate Software Developer${this._eor}` + - `4${this._delimiter}Jack Simon${this._delimiter}Software Developer${this._eor}` + - `2${this._delimiter}Gilberto Todd${this._delimiter}Director${this._eor}` + - `6${this._delimiter}Erma Walsh${this._delimiter}CEO${this._eor}` + - `8${this._delimiter}Erika Wells${this._delimiter}Software Development Team Lead${this._eor}` + - `10${this._delimiter}Eduardo Ramirez${this._delimiter}Manager${this._eor}` + - `7${this._delimiter}Debra Morton${this._delimiter}Associate Software Developer${this._eor}` + - `5${this._delimiter}Celia Martinez${this._delimiter}Senior Software Developer${this._eor}` + - `1${this._delimiter}Casey Houston${this._delimiter}Vice President${this._eor}`; + `3${this._delimiter}Tanya Bennett${this._delimiter}Director${this._eor}` + + `9${this._delimiter}Leslie Hansen${this._delimiter}Associate Software Developer${this._eor}` + + `4${this._delimiter}Jack Simon${this._delimiter}Software Developer${this._eor}` + + `2${this._delimiter}Gilberto Todd${this._delimiter}Director${this._eor}` + + `6${this._delimiter}Erma Walsh${this._delimiter}CEO${this._eor}` + + `8${this._delimiter}Erika Wells${this._delimiter}Software Development Team Lead${this._eor}` + + `10${this._delimiter}Eduardo Ramirez${this._delimiter}Manager${this._eor}` + + `7${this._delimiter}Debra Morton${this._delimiter}Associate Software Developer${this._eor}` + + `5${this._delimiter}Celia Martinez${this._delimiter}Senior Software Developer${this._eor}` + + `1${this._delimiter}Casey Houston${this._delimiter}Vice President${this._eor}`; } public get simpleGridRawData() { return `ID${this._delimiter}Name${this._delimiter}JobTitle${this._delimiter}${this._eor}` + - `1${this._delimiter}Casey Houston${this._delimiter}Vice President${this._delimiter}${this._eor}` + - `2${this._delimiter}Gilberto Todd${this._delimiter}Director${this._delimiter}${this._eor}` + - `3${this._delimiter}Tanya Bennett${this._delimiter}Director${this._delimiter}${this._eor}` + - `4${this._delimiter}Jack Simon${this._delimiter}Software Developer${this._delimiter}${this._eor}` + - `5${this._delimiter}Celia Martinez${this._delimiter}Senior Software Developer${this._delimiter}${this._eor}` + - `6${this._delimiter}Erma Walsh${this._delimiter}CEO${this._delimiter}${this._eor}` + - `7${this._delimiter}Debra Morton${this._delimiter}Associate Software Developer${this._delimiter}${this._eor}` + - `8${this._delimiter}Erika Wells${this._delimiter}Software Development Team Lead${this._delimiter}${this._eor}` + - `9${this._delimiter}Leslie Hansen${this._delimiter}Associate Software Developer${this._delimiter}${this._eor}` + - `10${this._delimiter}Eduardo Ramirez${this._delimiter}Manager${this._delimiter}${this._eor}`; + `1${this._delimiter}Casey Houston${this._delimiter}Vice President${this._delimiter}${this._eor}` + + `2${this._delimiter}Gilberto Todd${this._delimiter}Director${this._delimiter}${this._eor}` + + `3${this._delimiter}Tanya Bennett${this._delimiter}Director${this._delimiter}${this._eor}` + + `4${this._delimiter}Jack Simon${this._delimiter}Software Developer${this._delimiter}${this._eor}` + + `5${this._delimiter}Celia Martinez${this._delimiter}Senior Software Developer${this._delimiter}${this._eor}` + + `6${this._delimiter}Erma Walsh${this._delimiter}CEO${this._delimiter}${this._eor}` + + `7${this._delimiter}Debra Morton${this._delimiter}Associate Software Developer${this._delimiter}${this._eor}` + + `8${this._delimiter}Erika Wells${this._delimiter}Software Development Team Lead${this._delimiter}${this._eor}` + + `9${this._delimiter}Leslie Hansen${this._delimiter}Associate Software Developer${this._delimiter}${this._eor}` + + `10${this._delimiter}Eduardo Ramirez${this._delimiter}Manager${this._delimiter}${this._eor}`; } public get gridOneSeniorDev() { return `ID${this._delimiter}Name${this._delimiter}JobTitle${this._eor}` + - `5${this._delimiter}Celia Martinez${this._delimiter}Senior Software Developer${this._eor}`; + `5${this._delimiter}Celia Martinez${this._delimiter}Senior Software Developer${this._eor}`; } public get gridTwoDirectors() { return `ID${this._delimiter}Name${this._delimiter}JobTitle${this._eor}` + - `2${this._delimiter}Gilberto Todd${this._delimiter}Director${this._eor}` + - `3${this._delimiter}Tanya Bennett${this._delimiter}Director${this._eor}`; + `2${this._delimiter}Gilberto Todd${this._delimiter}Director${this._eor}` + + `3${this._delimiter}Tanya Bennett${this._delimiter}Director${this._eor}`; } public get gridNameJobTitle() { return `Name${this._delimiter}JobTitle${this._eor}` + - `Casey Houston${this._delimiter}Vice President${this._eor}` + - `Gilberto Todd${this._delimiter}Director${this._eor}` + - `Tanya Bennett${this._delimiter}Director${this._eor}` + - `Jack Simon${this._delimiter}Software Developer${this._eor}` + - `Celia Martinez${this._delimiter}Senior Software Developer${this._eor}` + - `Erma Walsh${this._delimiter}CEO${this._eor}` + - `Debra Morton${this._delimiter}Associate Software Developer${this._eor}` + - `Erika Wells${this._delimiter}Software Development Team Lead${this._eor}` + - `Leslie Hansen${this._delimiter}Associate Software Developer${this._eor}` + - `Eduardo Ramirez${this._delimiter}Manager${this._eor}`; + `Casey Houston${this._delimiter}Vice President${this._eor}` + + `Gilberto Todd${this._delimiter}Director${this._eor}` + + `Tanya Bennett${this._delimiter}Director${this._eor}` + + `Jack Simon${this._delimiter}Software Developer${this._eor}` + + `Celia Martinez${this._delimiter}Senior Software Developer${this._eor}` + + `Erma Walsh${this._delimiter}CEO${this._eor}` + + `Debra Morton${this._delimiter}Associate Software Developer${this._eor}` + + `Erika Wells${this._delimiter}Software Development Team Lead${this._eor}` + + `Leslie Hansen${this._delimiter}Associate Software Developer${this._eor}` + + `Eduardo Ramirez${this._delimiter}Manager${this._eor}`; } public get gridNameJobTitleID() { return `Name${this._delimiter}JobTitle${this._delimiter}ID${this._eor}` + - `Casey Houston${this._delimiter}Vice President${this._delimiter}1${this._eor}` + - `Gilberto Todd${this._delimiter}Director${this._delimiter}2${this._eor}` + - `Tanya Bennett${this._delimiter}Director${this._delimiter}3${this._eor}` + - `Jack Simon${this._delimiter}Software Developer${this._delimiter}4${this._eor}` + - `Celia Martinez${this._delimiter}Senior Software Developer${this._delimiter}5${this._eor}` + - `Erma Walsh${this._delimiter}CEO${this._delimiter}6${this._eor}` + - `Debra Morton${this._delimiter}Associate Software Developer${this._delimiter}7${this._eor}` + - `Erika Wells${this._delimiter}Software Development Team Lead${this._delimiter}8${this._eor}` + - `Leslie Hansen${this._delimiter}Associate Software Developer${this._delimiter}9${this._eor}` + - `Eduardo Ramirez${this._delimiter}Manager${this._delimiter}10${this._eor}`; + `Casey Houston${this._delimiter}Vice President${this._delimiter}1${this._eor}` + + `Gilberto Todd${this._delimiter}Director${this._delimiter}2${this._eor}` + + `Tanya Bennett${this._delimiter}Director${this._delimiter}3${this._eor}` + + `Jack Simon${this._delimiter}Software Developer${this._delimiter}4${this._eor}` + + `Celia Martinez${this._delimiter}Senior Software Developer${this._delimiter}5${this._eor}` + + `Erma Walsh${this._delimiter}CEO${this._delimiter}6${this._eor}` + + `Debra Morton${this._delimiter}Associate Software Developer${this._delimiter}7${this._eor}` + + `Erika Wells${this._delimiter}Software Development Team Lead${this._delimiter}8${this._eor}` + + `Leslie Hansen${this._delimiter}Associate Software Developer${this._delimiter}9${this._eor}` + + `Eduardo Ramirez${this._delimiter}Manager${this._delimiter}10${this._eor}`; } public get gridNameIDJobTitle() { return `Name${this._delimiter}ID${this._delimiter}JobTitle${this._eor}` + - `Casey Houston${this._delimiter}1${this._delimiter}Vice President${this._eor}` + - `Gilberto Todd${this._delimiter}2${this._delimiter}Director${this._eor}` + - `Tanya Bennett${this._delimiter}3${this._delimiter}Director${this._eor}` + - `Jack Simon${this._delimiter}4${this._delimiter}Software Developer${this._eor}` + - `Celia Martinez${this._delimiter}5${this._delimiter}Senior Software Developer${this._eor}` + - `Erma Walsh${this._delimiter}6${this._delimiter}CEO${this._eor}` + - `Debra Morton${this._delimiter}7${this._delimiter}Associate Software Developer${this._eor}` + - `Erika Wells${this._delimiter}8${this._delimiter}Software Development Team Lead${this._eor}` + - `Leslie Hansen${this._delimiter}9${this._delimiter}Associate Software Developer${this._eor}` + - `Eduardo Ramirez${this._delimiter}10${this._delimiter}Manager${this._eor}`; + `Casey Houston${this._delimiter}1${this._delimiter}Vice President${this._eor}` + + `Gilberto Todd${this._delimiter}2${this._delimiter}Director${this._eor}` + + `Tanya Bennett${this._delimiter}3${this._delimiter}Director${this._eor}` + + `Jack Simon${this._delimiter}4${this._delimiter}Software Developer${this._eor}` + + `Celia Martinez${this._delimiter}5${this._delimiter}Senior Software Developer${this._eor}` + + `Erma Walsh${this._delimiter}6${this._delimiter}CEO${this._eor}` + + `Debra Morton${this._delimiter}7${this._delimiter}Associate Software Developer${this._eor}` + + `Erika Wells${this._delimiter}8${this._delimiter}Software Development Team Lead${this._eor}` + + `Leslie Hansen${this._delimiter}9${this._delimiter}Associate Software Developer${this._eor}` + + `Eduardo Ramirez${this._delimiter}10${this._delimiter}Manager${this._eor}`; } public get gridWithAdvancedFilters() { return `ID${this._delimiter}Name${this._delimiter}JobTitle${this._eor}` + - `6${this._delimiter}Erma Walsh${this._delimiter}CEO${this._eor}` + - `7${this._delimiter}Debra Morton${this._delimiter}Associate Software Developer${this._eor}` + - `8${this._delimiter}Erika Wells${this._delimiter}Software Development Team Lead${this._eor}` + - `10${this._delimiter}Eduardo Ramirez${this._delimiter}Manager${this._eor}`; + `6${this._delimiter}Erma Walsh${this._delimiter}CEO${this._eor}` + + `7${this._delimiter}Debra Morton${this._delimiter}Associate Software Developer${this._eor}` + + `8${this._delimiter}Erika Wells${this._delimiter}Software Development Team Lead${this._eor}` + + `10${this._delimiter}Eduardo Ramirez${this._delimiter}Manager${this._eor}`; } public get treeGridData() { return `ID${this._delimiter}ParentID${this._delimiter}Name${this._delimiter}JobTitle${this._delimiter}Age${this._eor}` + -`1${this._delimiter}-1${this._delimiter}Casey Houston${this._delimiter}Vice President${this._delimiter}32${this._eor}` + -`2${this._delimiter}1${this._delimiter}Gilberto Todd${this._delimiter}Director${this._delimiter}41${this._eor}` + -`3${this._delimiter}2${this._delimiter}Tanya Bennett${this._delimiter}Director${this._delimiter}29${this._eor}` + -`7${this._delimiter}2${this._delimiter}Debra Morton${this._delimiter}Associate Software Developer${this._delimiter}35${this._eor}` + -`4${this._delimiter}1${this._delimiter}Jack Simon${this._delimiter}Software Developer${this._delimiter}33${this._eor}` + -`6${this._delimiter}-1${this._delimiter}Erma Walsh${this._delimiter}CEO${this._delimiter}52${this._eor}` + -`10${this._delimiter}-1${this._delimiter}Eduardo Ramirez${this._delimiter}Manager${this._delimiter}53${this._eor}` + -`9${this._delimiter}10${this._delimiter}Leslie Hansen${this._delimiter}Associate Software Developer${this._delimiter}44${this._eor}`; + `1${this._delimiter}-1${this._delimiter}Casey Houston${this._delimiter}Vice President${this._delimiter}32${this._eor}` + + `2${this._delimiter}1${this._delimiter}Gilberto Todd${this._delimiter}Director${this._delimiter}41${this._eor}` + + `3${this._delimiter}2${this._delimiter}Tanya Bennett${this._delimiter}Director${this._delimiter}29${this._eor}` + + `7${this._delimiter}2${this._delimiter}Debra Morton${this._delimiter}Associate Software Developer${this._delimiter}35${this._eor}` + + `4${this._delimiter}1${this._delimiter}Jack Simon${this._delimiter}Software Developer${this._delimiter}33${this._eor}` + + `6${this._delimiter}-1${this._delimiter}Erma Walsh${this._delimiter}CEO${this._delimiter}52${this._eor}` + + `10${this._delimiter}-1${this._delimiter}Eduardo Ramirez${this._delimiter}Manager${this._delimiter}53${this._eor}` + + `9${this._delimiter}10${this._delimiter}Leslie Hansen${this._delimiter}Associate Software Developer${this._delimiter}44${this._eor}`; } public get treeGridDataFormatted() { return `ID${this._delimiter}ParentID${this._delimiter}Name${this._delimiter}JobTitle${this._delimiter}Age${this._eor}` + -`1${this._delimiter}-1${this._delimiter}Casey Houston${this._delimiter}vice president${this._delimiter}384${this._eor}` + -`2${this._delimiter}1${this._delimiter}Gilberto Todd${this._delimiter}director${this._delimiter}492${this._eor}` + -`3${this._delimiter}2${this._delimiter}Tanya Bennett${this._delimiter}director${this._delimiter}348${this._eor}` + -`7${this._delimiter}2${this._delimiter}Debra Morton${this._delimiter}associate software developer${this._delimiter}420${this._eor}` + -`4${this._delimiter}1${this._delimiter}Jack Simon${this._delimiter}software developer${this._delimiter}396${this._eor}` + -`6${this._delimiter}-1${this._delimiter}Erma Walsh${this._delimiter}ceo${this._delimiter}624${this._eor}` + -`10${this._delimiter}-1${this._delimiter}Eduardo Ramirez${this._delimiter}manager${this._delimiter}636${this._eor}` + -`9${this._delimiter}10${this._delimiter}Leslie Hansen${this._delimiter}associate software developer${this._delimiter}528${this._eor}`; + `1${this._delimiter}-1${this._delimiter}Casey Houston${this._delimiter}vice president${this._delimiter}384${this._eor}` + + `2${this._delimiter}1${this._delimiter}Gilberto Todd${this._delimiter}director${this._delimiter}492${this._eor}` + + `3${this._delimiter}2${this._delimiter}Tanya Bennett${this._delimiter}director${this._delimiter}348${this._eor}` + + `7${this._delimiter}2${this._delimiter}Debra Morton${this._delimiter}associate software developer${this._delimiter}420${this._eor}` + + `4${this._delimiter}1${this._delimiter}Jack Simon${this._delimiter}software developer${this._delimiter}396${this._eor}` + + `6${this._delimiter}-1${this._delimiter}Erma Walsh${this._delimiter}ceo${this._delimiter}624${this._eor}` + + `10${this._delimiter}-1${this._delimiter}Eduardo Ramirez${this._delimiter}manager${this._delimiter}636${this._eor}` + + `9${this._delimiter}10${this._delimiter}Leslie Hansen${this._delimiter}associate software developer${this._delimiter}528${this._eor}`; } public get treeGridDataSorted() { return `ID${this._delimiter}ParentID${this._delimiter}Name${this._delimiter}JobTitle${this._delimiter}Age${this._eor}` + -`10${this._delimiter}-1${this._delimiter}Eduardo Ramirez${this._delimiter}Manager${this._delimiter}53${this._eor}` + -`9${this._delimiter}10${this._delimiter}Leslie Hansen${this._delimiter}Associate Software Developer${this._delimiter}44${this._eor}` + -`6${this._delimiter}-1${this._delimiter}Erma Walsh${this._delimiter}CEO${this._delimiter}52${this._eor}` + -`1${this._delimiter}-1${this._delimiter}Casey Houston${this._delimiter}Vice President${this._delimiter}32${this._eor}` + -`4${this._delimiter}1${this._delimiter}Jack Simon${this._delimiter}Software Developer${this._delimiter}33${this._eor}` + -`2${this._delimiter}1${this._delimiter}Gilberto Todd${this._delimiter}Director${this._delimiter}41${this._eor}` + -`7${this._delimiter}2${this._delimiter}Debra Morton${this._delimiter}Associate Software Developer${this._delimiter}35${this._eor}` + -`3${this._delimiter}2${this._delimiter}Tanya Bennett${this._delimiter}Director${this._delimiter}29${this._eor}`; + `10${this._delimiter}-1${this._delimiter}Eduardo Ramirez${this._delimiter}Manager${this._delimiter}53${this._eor}` + + `9${this._delimiter}10${this._delimiter}Leslie Hansen${this._delimiter}Associate Software Developer${this._delimiter}44${this._eor}` + + `6${this._delimiter}-1${this._delimiter}Erma Walsh${this._delimiter}CEO${this._delimiter}52${this._eor}` + + `1${this._delimiter}-1${this._delimiter}Casey Houston${this._delimiter}Vice President${this._delimiter}32${this._eor}` + + `4${this._delimiter}1${this._delimiter}Jack Simon${this._delimiter}Software Developer${this._delimiter}33${this._eor}` + + `2${this._delimiter}1${this._delimiter}Gilberto Todd${this._delimiter}Director${this._delimiter}41${this._eor}` + + `7${this._delimiter}2${this._delimiter}Debra Morton${this._delimiter}Associate Software Developer${this._delimiter}35${this._eor}` + + `3${this._delimiter}2${this._delimiter}Tanya Bennett${this._delimiter}Director${this._delimiter}29${this._eor}`; } public get treeGridDataFiltered() { return `ID${this._delimiter}ParentID${this._delimiter}Name${this._delimiter}JobTitle${this._delimiter}Age${this._eor}` + -`1${this._delimiter}-1${this._delimiter}Casey Houston${this._delimiter}Vice President${this._delimiter}32${this._eor}` + -`2${this._delimiter}1${this._delimiter}Gilberto Todd${this._delimiter}Director${this._delimiter}41${this._eor}` + -`7${this._delimiter}2${this._delimiter}Debra Morton${this._delimiter}Associate Software Developer${this._delimiter}35${this._eor}` + -`4${this._delimiter}1${this._delimiter}Jack Simon${this._delimiter}Software Developer${this._delimiter}33${this._eor}` + -`6${this._delimiter}-1${this._delimiter}Erma Walsh${this._delimiter}CEO${this._delimiter}52${this._eor}` + -`10${this._delimiter}-1${this._delimiter}Eduardo Ramirez${this._delimiter}Manager${this._delimiter}53${this._eor}` + -`9${this._delimiter}10${this._delimiter}Leslie Hansen${this._delimiter}Associate Software Developer${this._delimiter}44${this._eor}`; + `1${this._delimiter}-1${this._delimiter}Casey Houston${this._delimiter}Vice President${this._delimiter}32${this._eor}` + + `2${this._delimiter}1${this._delimiter}Gilberto Todd${this._delimiter}Director${this._delimiter}41${this._eor}` + + `7${this._delimiter}2${this._delimiter}Debra Morton${this._delimiter}Associate Software Developer${this._delimiter}35${this._eor}` + + `4${this._delimiter}1${this._delimiter}Jack Simon${this._delimiter}Software Developer${this._delimiter}33${this._eor}` + + `6${this._delimiter}-1${this._delimiter}Erma Walsh${this._delimiter}CEO${this._delimiter}52${this._eor}` + + `10${this._delimiter}-1${this._delimiter}Eduardo Ramirez${this._delimiter}Manager${this._delimiter}53${this._eor}` + + `9${this._delimiter}10${this._delimiter}Leslie Hansen${this._delimiter}Associate Software Developer${this._delimiter}44${this._eor}`; } public get treeGridDataFilterSorted() { return `ID${this._delimiter}ParentID${this._delimiter}Name${this._delimiter}JobTitle${this._delimiter}Age${this._eor}` + -`6${this._delimiter}-1${this._delimiter}Erma Walsh${this._delimiter}CEO${this._delimiter}52${this._eor}` + -`10${this._delimiter}-1${this._delimiter}Eduardo Ramirez${this._delimiter}Manager${this._delimiter}53${this._eor}` + -`9${this._delimiter}10${this._delimiter}Leslie Hansen${this._delimiter}Associate Software Developer${this._delimiter}44${this._eor}` + -`1${this._delimiter}-1${this._delimiter}Casey Houston${this._delimiter}Vice President${this._delimiter}32${this._eor}` + -`4${this._delimiter}1${this._delimiter}Jack Simon${this._delimiter}Software Developer${this._delimiter}33${this._eor}` + -`2${this._delimiter}1${this._delimiter}Gilberto Todd${this._delimiter}Director${this._delimiter}41${this._eor}` + -`7${this._delimiter}2${this._delimiter}Debra Morton${this._delimiter}Associate Software Developer${this._delimiter}35${this._eor}`; + `6${this._delimiter}-1${this._delimiter}Erma Walsh${this._delimiter}CEO${this._delimiter}52${this._eor}` + + `10${this._delimiter}-1${this._delimiter}Eduardo Ramirez${this._delimiter}Manager${this._delimiter}53${this._eor}` + + `9${this._delimiter}10${this._delimiter}Leslie Hansen${this._delimiter}Associate Software Developer${this._delimiter}44${this._eor}` + + `1${this._delimiter}-1${this._delimiter}Casey Houston${this._delimiter}Vice President${this._delimiter}32${this._eor}` + + `4${this._delimiter}1${this._delimiter}Jack Simon${this._delimiter}Software Developer${this._delimiter}33${this._eor}` + + `2${this._delimiter}1${this._delimiter}Gilberto Todd${this._delimiter}Director${this._delimiter}41${this._eor}` + + `7${this._delimiter}2${this._delimiter}Debra Morton${this._delimiter}Associate Software Developer${this._delimiter}35${this._eor}`; } public get treeGridWithAdvancedFilters() { return `ID${this._delimiter}ParentID${this._delimiter}Name${this._delimiter}JobTitle${this._delimiter}Age${this._eor}` + - `1${this._delimiter}-1${this._delimiter}Casey Houston${this._delimiter}Vice President${this._delimiter}32${this._eor}` + - `2${this._delimiter}1${this._delimiter}Gilberto Todd${this._delimiter}Director${this._delimiter}41${this._eor}` + - `7${this._delimiter}2${this._delimiter}Debra Morton${this._delimiter}Associate Software Developer${this._delimiter}35${this._eor}` + - `6${this._delimiter}-1${this._delimiter}Erma Walsh${this._delimiter}CEO${this._delimiter}52${this._eor}` + - `10${this._delimiter}-1${this._delimiter}Eduardo Ramirez${this._delimiter}Manager${this._delimiter}53${this._eor}`; + `1${this._delimiter}-1${this._delimiter}Casey Houston${this._delimiter}Vice President${this._delimiter}32${this._eor}` + + `2${this._delimiter}1${this._delimiter}Gilberto Todd${this._delimiter}Director${this._delimiter}41${this._eor}` + + `7${this._delimiter}2${this._delimiter}Debra Morton${this._delimiter}Associate Software Developer${this._delimiter}35${this._eor}` + + `6${this._delimiter}-1${this._delimiter}Erma Walsh${this._delimiter}CEO${this._delimiter}52${this._eor}` + + `10${this._delimiter}-1${this._delimiter}Eduardo Ramirez${this._delimiter}Manager${this._delimiter}53${this._eor}`; } public get gridColumnsAddedOnInit() { return `CompanyName${this._delimiter}ContactName${this._delimiter}Address${this._delimiter}0${this._delimiter}` + - `1${this._delimiter}2${this._eor}` + - `Alfreds Futterkiste${this._delimiter}Maria Anders${this._delimiter}Obere Str. 57${this._delimiter}0${this._delimiter}` + - `2500${this._delimiter}5000${this._eor}` + - `Ana Trujillo Emparedados y helados${this._delimiter}Ana Trujillo${this._delimiter}Avda. de la Constitución 2222` + - `${this._delimiter}0${this._delimiter}2500${this._delimiter}5000${this._eor}` + - `Antonio Moreno Taquería${this._delimiter}Antonio Moreno${this._delimiter}Mataderos 2312${this._delimiter}0` + - `${this._delimiter}2500${this._delimiter}5000${this._eor}` + - `Around the Horn${this._delimiter}Thomas Hardy${this._delimiter}120 Hanover Sq.${this._delimiter}0${this._delimiter}` + - `2500${this._delimiter}5000${this._eor}` + - `Berglunds snabbköp${this._delimiter}Christina Berglund${this._delimiter}Berguvsvägen 8${this._delimiter}0` + - `${this._delimiter}2500${this._delimiter}5000${this._eor}` + - `Blauer See Delikatessen${this._delimiter}Hanna Moos${this._delimiter}Forsterstr. 57${this._delimiter}0${this._delimiter}` + - `2500${this._delimiter}5000${this._eor}` + - `Blondesddsl père et fils${this._delimiter}Frédérique Citeaux${this._delimiter}"24${this._delimiter} place Kléber"` + - `${this._delimiter}0${this._delimiter}2500${this._delimiter}5000${this._eor}` + - `Bólido Comidas preparadas${this._delimiter}Martín Sommer${this._delimiter}"C/ Araquil${this._delimiter} 67"` + - `${this._delimiter}0${this._delimiter}2500${this._delimiter}5000${this._eor}` + - `Bon app'${this._delimiter}Laurence Lebihan${this._delimiter}"12${this._delimiter} rue des Bouchers"${this._delimiter}` + - `0${this._delimiter}2500${this._delimiter}5000${this._eor}` + - `Bottom-Dollar Markets${this._delimiter}Elizabeth Lincoln${this._delimiter}23 Tsawassen Blvd.${this._delimiter}0` + - `${this._delimiter}2500${this._delimiter}5000${this._eor}` + - `B's Beverages${this._delimiter}Victoria Ashworth${this._delimiter}Fauntleroy Circus${this._delimiter}0${this._delimiter}` + - `2500${this._delimiter}5000${this._eor}`; + `1${this._delimiter}2${this._eor}` + + `Alfreds Futterkiste${this._delimiter}Maria Anders${this._delimiter}Obere Str. 57${this._delimiter}0${this._delimiter}` + + `2500${this._delimiter}5000${this._eor}` + + `Ana Trujillo Emparedados y helados${this._delimiter}Ana Trujillo${this._delimiter}Avda. de la Constitución 2222` + + `${this._delimiter}0${this._delimiter}2500${this._delimiter}5000${this._eor}` + + `Antonio Moreno Taquería${this._delimiter}Antonio Moreno${this._delimiter}Mataderos 2312${this._delimiter}0` + + `${this._delimiter}2500${this._delimiter}5000${this._eor}` + + `Around the Horn${this._delimiter}Thomas Hardy${this._delimiter}120 Hanover Sq.${this._delimiter}0${this._delimiter}` + + `2500${this._delimiter}5000${this._eor}` + + `Berglunds snabbköp${this._delimiter}Christina Berglund${this._delimiter}Berguvsvägen 8${this._delimiter}0` + + `${this._delimiter}2500${this._delimiter}5000${this._eor}` + + `Blauer See Delikatessen${this._delimiter}Hanna Moos${this._delimiter}Forsterstr. 57${this._delimiter}0${this._delimiter}` + + `2500${this._delimiter}5000${this._eor}` + + `Blondesddsl père et fils${this._delimiter}Frédérique Citeaux${this._delimiter}"24${this._delimiter} place Kléber"` + + `${this._delimiter}0${this._delimiter}2500${this._delimiter}5000${this._eor}` + + `Bólido Comidas preparadas${this._delimiter}Martín Sommer${this._delimiter}"C/ Araquil${this._delimiter} 67"` + + `${this._delimiter}0${this._delimiter}2500${this._delimiter}5000${this._eor}` + + `Bon app'${this._delimiter}Laurence Lebihan${this._delimiter}"12${this._delimiter} rue des Bouchers"${this._delimiter}` + + `0${this._delimiter}2500${this._delimiter}5000${this._eor}` + + `Bottom-Dollar Markets${this._delimiter}Elizabeth Lincoln${this._delimiter}23 Tsawassen Blvd.${this._delimiter}0` + + `${this._delimiter}2500${this._delimiter}5000${this._eor}` + + `B's Beverages${this._delimiter}Victoria Ashworth${this._delimiter}Fauntleroy Circus${this._delimiter}0${this._delimiter}` + + `2500${this._delimiter}5000${this._eor}`; } public get pivotGridData() { return `ProductCategory${this._delimiter}Bulgaria${this._delimiter}USA${this._delimiter}Uruguay${this._eor}` + - `Clothing${this._delimiter}774${this._delimiter}296${this._delimiter}456${this._eor}` + - `Bikes${this._delimiter}${this._delimiter}${this._delimiter}68${this._eor}` + - `Accessories${this._delimiter}${this._delimiter}293${this._delimiter}${this._eor}` + - `Components${this._delimiter}${this._delimiter}240${this._delimiter}${this._eor}`; + `Clothing${this._delimiter}774${this._delimiter}296${this._delimiter}456${this._eor}` + + `Bikes${this._delimiter}${this._delimiter}${this._delimiter}68${this._eor}` + + `Accessories${this._delimiter}${this._delimiter}293${this._delimiter}${this._eor}` + + `Components${this._delimiter}${this._delimiter}240${this._delimiter}${this._eor}`; } } diff --git a/projects/igniteui-angular/grids/core/src/services/excel/excel-exporter-grid.spec.ts b/projects/igniteui-angular/grids/core/src/services/excel/excel-exporter-grid.spec.ts index 44f66555ff9..21900bdd2a9 100644 --- a/projects/igniteui-angular/grids/core/src/services/excel/excel-exporter-grid.spec.ts +++ b/projects/igniteui-angular/grids/core/src/services/excel/excel-exporter-grid.spec.ts @@ -4,40 +4,14 @@ import { ExportUtilities } from '../exporter-common/export-utilities'; import { TestMethods } from '../exporter-common/test-methods.spec'; import { IgxExcelExporterService } from './excel-exporter'; import { IgxExcelExporterOptions } from './excel-exporter-options'; -import { - ReorderedColumnsComponent, - GridIDNameJobTitleComponent, - ProductsComponent, - GridIDNameJobTitleHireDataPerformanceComponent, - GridHireDateComponent, - GridExportGroupedDataComponent, - MultiColumnHeadersExportComponent, - GridWithEmptyColumnsComponent, - ColumnsAddedOnInitComponent, - GridWithThreeLevelsOfMultiColumnHeadersAndTwoRowsExportComponent, - GroupedGridWithSummariesComponent, - GridCurrencySummariesComponent, - GridUserMeetingDataComponent, - GridCustomSummaryComponent, - GridCustomSummaryWithNullAndZeroComponent, - GridCustomSummaryWithUndefinedZeroAndValidNumberComponent, - GridCustomSummaryWithUndefinedAndNullComponent, - GridCustomSummaryWithDateComponent -} from '../../../../../test-utils/grid-samples.spec'; +import { ReorderedColumnsComponent, GridIDNameJobTitleComponent, ProductsComponent, GridIDNameJobTitleHireDataPerformanceComponent, GridHireDateComponent, GridExportGroupedDataComponent, MultiColumnHeadersExportComponent, GridWithEmptyColumnsComponent, ColumnsAddedOnInitComponent, GridWithThreeLevelsOfMultiColumnHeadersAndTwoRowsExportComponent, GroupedGridWithSummariesComponent, GridCurrencySummariesComponent, GridUserMeetingDataComponent, GridCustomSummaryComponent, GridCustomSummaryWithNullAndZeroComponent, GridCustomSummaryWithUndefinedZeroAndValidNumberComponent, GridCustomSummaryWithUndefinedAndNullComponent, GridCustomSummaryWithDateComponent } from '../../../../../test-utils/grid-samples.spec'; import { SampleTestData } from '../../../../../test-utils/sample-test-data.spec'; import { first } from 'rxjs/operators'; import { IgxTreeGridPrimaryForeignKeyComponent, IgxTreeGridSummariesKeyComponent } from '../../../../../test-utils/tree-grid-components.spec'; import { UIInteractions, wait } from '../../../../../test-utils/ui-interactions.spec'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { IgxHierarchicalGridExportComponent, - IgxHierarchicalGridMCHCollapsibleComponent, - IgxHierarchicalGridMultiColumnHeaderIslandsExportComponent, - IgxHierarchicalGridMultiColumnHeadersExportComponent, - IgxHierarchicalGridSummariesExportComponent, - IgxHierarchicalGridEmptyDataExportComponent, - IgxHierarchicalGridMissingChildDataExportComponent -} from '../../../../../test-utils/hierarchical-grid-components.spec'; +import { IgxHierarchicalGridExportComponent, IgxHierarchicalGridMCHCollapsibleComponent, IgxHierarchicalGridMultiColumnHeaderIslandsExportComponent, IgxHierarchicalGridMultiColumnHeadersExportComponent, IgxHierarchicalGridSummariesExportComponent, IgxHierarchicalGridEmptyDataExportComponent, IgxHierarchicalGridMissingChildDataExportComponent } from '../../../../../test-utils/hierarchical-grid-components.spec'; import { GridFunctions } from '../../../../../test-utils/grid-functions.spec'; import { IgxPivotGridMultipleRowComponent, IgxPivotGridTestComplexHierarchyComponent, SALES_DATA } from '../../../../../test-utils/pivot-grid-samples.spec'; import { IgxHierarchicalRowComponent } from 'igniteui-angular/grids/hierarchical-grid/src/hierarchical-row.component'; @@ -49,6 +23,7 @@ import { IgxGridComponent } from 'igniteui-angular/grids/grid'; import { FileContentData } from './test-data.service.spec'; import { ZipWrapper } from './zip-verification-wrapper.spec'; import { DefaultSortingStrategy, FilteringExpressionsTree, FilteringLogic, IgxNumberFilteringOperand, IgxStringFilteringOperand, SortingDirection } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; describe('Excel Exporter', () => { let exporter: IgxExcelExporterService; @@ -99,7 +74,7 @@ describe('Excel Exporter', () => { actualData = new FileContentData(); // Spy the saveBlobToFile method so the files are not really created - spyOn(ExportUtilities as any, 'saveBlobToFile'); + vi.spyOn(ExportUtilities as any, 'saveBlobToFile'); })); afterEach(waitForAsync(() => { @@ -150,7 +125,7 @@ describe('Excel Exporter', () => { grid.filter('JobTitle', 'Director', IgxStringFilteringOperand.instance().condition('equals'), true); fix.detectChanges(); - expect(grid.rowList.length).toEqual(2, 'Invalid number of rows after filtering!'); + expect(grid.rowList.length, 'Invalid number of rows after filtering!').toEqual(2); wrapper = await getExportedData(grid, options); await wrapper.verifyDataFilesContent(actualData.simpleGridDataDirectors, 'Two rows should have been exported!'); }); @@ -165,7 +140,7 @@ describe('Excel Exporter', () => { options.ignoreColumnsVisibility = false; fix.detectChanges(); - expect(grid.visibleColumns.length).toEqual(2, 'Invalid number of visible columns!'); + expect(grid.visibleColumns.length, 'Invalid number of visible columns!').toEqual(2); let wrapper = await getExportedData(grid, options); await wrapper.verifyDataFilesContent(actualData.simpleGridNameJobTitle, 'Two columns should have been exported!'); @@ -183,28 +158,28 @@ describe('Excel Exporter', () => { const grid = fix.componentInstance.grid; options.ignoreColumnsVisibility = false; - expect(grid.visibleColumns.length).toEqual(3, 'Invalid number of visible columns!'); + expect(grid.visibleColumns.length, 'Invalid number of visible columns!').toEqual(3); let wrapper = await getExportedData(grid, options); await wrapper.verifyDataFilesContent(actualData.simpleGridData, 'All columns should have been exported!'); grid.columnList.get(0).hidden = true; fix.detectChanges(); - expect(grid.visibleColumns.length).toEqual(2, 'Invalid number of visible columns!'); + expect(grid.visibleColumns.length, 'Invalid number of visible columns!').toEqual(2); wrapper = await getExportedData(grid, options); await wrapper.verifyDataFilesContent(actualData.simpleGridNameJobTitle, 'Two columns should have been exported!'); grid.columnList.get(0).hidden = false; fix.detectChanges(); - expect(grid.visibleColumns.length).toEqual(3, 'Invalid number of visible columns!'); + expect(grid.visibleColumns.length, 'Invalid number of visible columns!').toEqual(3); wrapper = await getExportedData(grid, options); await wrapper.verifyDataFilesContent(actualData.simpleGridData, 'All columns should have been exported!'); grid.columnList.get(0).hidden = undefined; fix.detectChanges(); - expect(grid.visibleColumns.length).toEqual(3, 'Invalid number of visible columns!'); + expect(grid.visibleColumns.length, 'Invalid number of visible columns!').toEqual(3); wrapper = await getExportedData(grid, options); await wrapper.verifyDataFilesContent(actualData.simpleGridData, 'All columns should have been exported!'); }); @@ -273,20 +248,17 @@ describe('Excel Exporter', () => { let wrapper = await getExportedData(grid, options); wrapper.verifyStructure(); - await wrapper.verifyDataFilesContent(actualData.gridNameFrozenHeaders, - 'One frozen column and frozen headers should have been exported!'); + await wrapper.verifyDataFilesContent(actualData.gridNameFrozenHeaders, 'One frozen column and frozen headers should have been exported!'); options.ignorePinning = true; fix.detectChanges(); wrapper = await getExportedData(grid, options); - await wrapper.verifyDataFilesContent(actualData.gridFrozenHeaders, - 'No frozen columns and frozen headers should have been exported!'); + await wrapper.verifyDataFilesContent(actualData.gridFrozenHeaders, 'No frozen columns and frozen headers should have been exported!'); options.freezeHeaders = false; fix.detectChanges(); wrapper = await getExportedData(grid, options); - await wrapper.verifyDataFilesContent(actualData.gridNameIDJobTitle, - 'No frozen columns and no frozen headers should have been exported!'); + await wrapper.verifyDataFilesContent(actualData.gridNameIDJobTitle, 'No frozen columns and no frozen headers should have been exported!'); }); it('should honor applied sorting.', async () => { @@ -322,8 +294,7 @@ describe('Excel Exporter', () => { fix.detectChanges(); wrapper = await getExportedData(grid, options); - await wrapper.verifyDataFilesContent( - actualData.simpleGridSortByNameDesc(), 'Descending sorted data should have been exported.'); + await wrapper.verifyDataFilesContent(actualData.simpleGridSortByNameDesc(), 'Descending sorted data should have been exported.'); grid.clearSort(); grid.sort({ fieldName: 'ID', dir: SortingDirection.Asc, ignoreCase: true, strategy: DefaultSortingStrategy.instance() }); @@ -943,7 +914,7 @@ describe('Excel Exporter', () => { hGrid = fix.componentInstance.hGrid; options = createExportOptions('HierarchicalGridEmptyDataExcelExport'); - await expectAsync(getExportedData(hGrid, options)).toBeResolved(); + await expect(getExportedData(hGrid, options)).resolves.not.toThrow(); }); it('should export hierarchical grid with empty data and summaries without throwing error', async () => { @@ -958,7 +929,7 @@ describe('Excel Exporter', () => { options = createExportOptions('HierarchicalGridEmptyDataWithSummariesExcelExport'); options.exportSummaries = true; - await expectAsync(getExportedData(hGrid, options)).toBeResolved(); + await expect(getExportedData(hGrid, options)).resolves.not.toThrow(); }); it('should export hierarchical grid with missing child data key without throwing error', async () => { @@ -968,7 +939,7 @@ describe('Excel Exporter', () => { hGrid = fix.componentInstance.hGrid; options = createExportOptions('HierarchicalGridMissingChildDataExcelExport'); - await expectAsync(getExportedData(hGrid, options)).toBeResolved(); + await expect(getExportedData(hGrid, options)).resolves.not.toThrow(); }); }); @@ -1075,7 +1046,7 @@ describe('Excel Exporter', () => { options = createExportOptions('HierarchicalGridCollapsibleMCHExcelExport'); await exportAndVerify(hGrid, options, actualData.exportHierarchicalDataWithCollapsibleMCH); - }) + }); }); describe('', () => { @@ -1619,18 +1590,18 @@ describe('Excel Exporter', () => { grid.pivotUI.showRowHeaders = true; grid.pivotUI.rowLayout = PivotRowLayoutType.Horizontal; grid.pivotConfiguration.rows = [{ - memberName: 'ProductCategory', - memberFunction: (data) => data.ProductCategory, - enabled: true, - childLevel: { - memberName: 'Country', + memberName: 'ProductCategory', + memberFunction: (data) => data.ProductCategory, enabled: true, childLevel: { - memberName: 'Date', - enabled: true + memberName: 'Country', + enabled: true, + childLevel: { + memberName: 'Date', + enabled: true + } } - } - }], + }], fix.detectChanges(); await wait(300); fix.detectChanges(); diff --git a/projects/igniteui-angular/grids/core/src/services/excel/excel-exporter.spec.ts b/projects/igniteui-angular/grids/core/src/services/excel/excel-exporter.spec.ts index 21cfad327dc..ea570d7b4d7 100644 --- a/projects/igniteui-angular/grids/core/src/services/excel/excel-exporter.spec.ts +++ b/projects/igniteui-angular/grids/core/src/services/excel/excel-exporter.spec.ts @@ -6,6 +6,7 @@ import { ZipWrapper } from './zip-verification-wrapper.spec'; import { FileContentData } from './test-data.service.spec'; import { SampleTestData } from '../../../../../test-utils/sample-test-data.spec'; import { first } from 'rxjs/operators'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('Excel Exporter', () => { let exporter: IgxExcelExporterService; @@ -18,7 +19,7 @@ describe('Excel Exporter', () => { options = new IgxExcelExporterOptions('ExcelExport'); // Spy the saveBlobToFile method so the files are not really created - spyOn(ExportUtilities, 'saveBlobToFile'); + vi.spyOn(ExportUtilities, 'saveBlobToFile'); }); /* ExportData() tests */ diff --git a/projects/igniteui-angular/grids/core/src/services/excel/test-data.service.spec.ts b/projects/igniteui-angular/grids/core/src/services/excel/test-data.service.spec.ts index 97ed95aeb96..8880d5f2d1a 100644 --- a/projects/igniteui-angular/grids/core/src/services/excel/test-data.service.spec.ts +++ b/projects/igniteui-angular/grids/core/src/services/excel/test-data.service.spec.ts @@ -12,41 +12,41 @@ export class ExportTestDataService { ]; private _contactsData = [{ - name: 'Terrance Orta', - phone: '770-504-2217' - }, { - name: 'Richard Mahoney LongerName', - phone: '' - }, { - name: 'Donna Price', - phone: '859-496-2817' - }, { - name: '', - phone: '901-747-3428' - }, { - name: 'Dorothy H. Spencer', - phone: '573-394-9254' - }]; + name: 'Terrance Orta', + phone: '770-504-2217' + }, { + name: 'Richard Mahoney LongerName', + phone: '' + }, { + name: 'Donna Price', + phone: '859-496-2817' + }, { + name: '', + phone: '901-747-3428' + }, { + name: 'Dorothy H. Spencer', + phone: '573-394-9254' + }]; private _contactsFunkyData = [{ - name: 'Terrance Mc\'Orta', - phone: '(+359)770-504-2217 | 2218' - }, { - name: 'Richard Mahoney /LongerName/', - phone: '' - }, { - name: 'Donna, \/; Price', - phone: '859 496 28**' - }, { - name: '\r\n', - phone: '901-747-3428' - }, { - name: 'Dorothy "H." Spencer', - phone: '573-394-9254[fax]' - }, { - name: 'Иван Иванов (1,2)', - phone: '№ 573-394-9254' - }]; + name: 'Terrance Mc\'Orta', + phone: '(+359)770-504-2217 | 2218' + }, { + name: 'Richard Mahoney /LongerName/', + phone: '' + }, { + name: 'Donna, \/; Price', + phone: '859 496 28**' + }, { + name: '\r\n', + phone: '901-747-3428' + }, { + name: 'Dorothy "H." Spencer', + phone: '573-394-9254[fax]' + }, { + name: 'Иван Иванов (1,2)', + phone: '№ 573-394-9254' + }]; private _contactsPartial = [ { @@ -119,28 +119,25 @@ export class ExportTestDataService { ]; private _personJobHoursDataPerformance = [ - { ID: 1, Name: 'Casey Houston', JobTitle: 'Vice President', WorkingHours: 4, HireDate: '2017-06-19T11:43:07.714Z', Performance: - [ - {Points: 3, Week: 1}, - {Points: 6, Week: 2}, - {Points: 1, Week: 3}, - {Points: 12, Week: 4}, + { ID: 1, Name: 'Casey Houston', JobTitle: 'Vice President', WorkingHours: 4, HireDate: '2017-06-19T11:43:07.714Z', Performance: [ + { Points: 3, Week: 1 }, + { Points: 6, Week: 2 }, + { Points: 1, Week: 3 }, + { Points: 12, Week: 4 }, ] }, - { ID: 2, Name: 'Gilberto Todd', JobTitle: 'Director', WorkingHours: 6, HireDate: '2015-12-18T11:23:17.714Z', Performance: - [ - {Points: 8, Week: 1}, - {Points: 7, Week: 2}, - {Points: 4, Week: 3}, - {Points: 9, Week: 4}, + { ID: 2, Name: 'Gilberto Todd', JobTitle: 'Director', WorkingHours: 6, HireDate: '2015-12-18T11:23:17.714Z', Performance: [ + { Points: 8, Week: 1 }, + { Points: 7, Week: 2 }, + { Points: 4, Week: 3 }, + { Points: 9, Week: 4 }, ] }, - { ID: 3, Name: 'Tanya Bennett', JobTitle: 'Director', WorkingHours: 8, HireDate: '2005-11-18T11:23:17.714Z', Performance: - [ - {Points: 1, Week: 1}, - {Points: 3, Week: 2}, - {Points: 14, Week: 3}, - {Points: 29, Week: 4}, + { ID: 3, Name: 'Tanya Bennett', JobTitle: 'Director', WorkingHours: 8, HireDate: '2005-11-18T11:23:17.714Z', Performance: [ + { Points: 1, Week: 1 }, + { Points: 3, Week: 2 }, + { Points: 14, Week: 3 }, + { Points: 29, Week: 4 }, ] } ]; @@ -191,24 +188,24 @@ export class ExportTestDataService { public getContactsFunkyData(delimiter) { return [{ - name: 'Terrance Mc\'Orta', - phone: '(+359)770-504-2217 | 2218' - }, { - name: 'Richard Mahoney /LongerName/', - phone: '' - }, { - name: 'Donna' + delimiter + ' \/; Price', - phone: '859 496 28**' - }, { - name: '\r\n', - phone: '901-747-3428' - }, { - name: 'Dorothy "H." Spencer', - phone: '573-394-9254[fax]' - }, { - name: 'Иван Иванов (1' + delimiter + '2)', - phone: '№ 573-394-9254' - }]; + name: 'Terrance Mc\'Orta', + phone: '(+359)770-504-2217 | 2218' + }, { + name: 'Richard Mahoney /LongerName/', + phone: '' + }, { + name: 'Donna' + delimiter + ' \/; Price', + phone: '859 496 28**' + }, { + name: '\r\n', + phone: '901-747-3428' + }, { + name: 'Dorothy "H." Spencer', + phone: '573-394-9254[fax]' + }, { + name: 'Иван Иванов (1' + delimiter + '2)', + phone: '№ 573-394-9254' + }]; } } @@ -228,28 +225,28 @@ export class FileContentData { private _worksheetData = ''; private _workbookData = ` `; + `officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x15" ` + + `xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main">`; private _appData = ` Microsoft Excel0falseWorksheets1Sheet1falsefalsefalse16.0300`; - constructor() {} + constructor() { } public create(worksheetData: string, tableData: string, sharedStringsData: string, workbookData: string, appData: string, isHGrid = false): IFileContent[] { this._fileContentCollection = [ - { fileName: ZipFiles.dataFiles[1].name, fileContent : worksheetData }, - { fileName: ZipFiles.dataFiles[3].name, fileContent : sharedStringsData }, - { fileName: ZipFiles.templateFiles[6].name, fileContent : workbookData }, - { fileName: ZipFiles.templateFiles[1].name, fileContent : appData }, + { fileName: ZipFiles.dataFiles[1].name, fileContent: worksheetData }, + { fileName: ZipFiles.dataFiles[3].name, fileContent: sharedStringsData }, + { fileName: ZipFiles.templateFiles[6].name, fileContent: workbookData }, + { fileName: ZipFiles.templateFiles[1].name, fileContent: appData }, ]; if (!isHGrid) { this._fileContentCollection.push({ - fileName: ZipFiles.dataFiles[2].name, fileContent : tableData + fileName: ZipFiles.dataFiles[2].name, fileContent: tableData }); } @@ -281,7 +278,7 @@ export class FileContentData { this._worksheetData = `` + - `${ wsDataColSettings }012345678910`; + `${wsDataColSettings}012345678910`; return this.createData(); } @@ -300,23 +297,23 @@ export class FileContentData { public simpleGridWorksheetName(name) { this._sharedStringsData = - `count="23" uniqueCount="21">IDNameJobTitleCasey HoustonVice PresidentGilberto ToddDirectorTanya BennettJack SimonSoftware DeveloperCelia MartinezSenior Software DeveloperErma WalshCEODebra MortonAssociate Software DeveloperErika WellsSoftware Development Team LeadLeslie HansenEduardo RamirezManager`; + `count="23" uniqueCount="21">IDNameJobTitleCasey HoustonVice PresidentGilberto ToddDirectorTanya BennettJack SimonSoftware DeveloperCelia MartinezSenior Software DeveloperErma WalshCEODebra MortonAssociate Software DeveloperErika WellsSoftware Development Team LeadLeslie HansenEduardo RamirezManager`; this._tableData = `ref="A1:C11" totalsRowShown="0"> ` + ``; this._worksheetData = - `0121342563764895101161213714158161791815101920`; + `0121342563764895101161213714158161791815101920`; - this._workbookData = ` + this._workbookData = ` `; + `officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x15" ` + + `xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main">`; this._appData = ` Microsoft Excel0falseWorksheets1${name}falsefalsefalse16.0300`; @@ -368,10 +365,10 @@ export class FileContentData { this._worksheetData = `` + - `` + - `01234` + - `5`; + `` + + `01234` + + `5`; return this.createData(); } @@ -387,12 +384,12 @@ export class FileContentData { this._worksheetData = `` + - `` + - `012` + - `345` + - `6758` + - `910`; + `` + + `012` + + `345` + + `6758` + + `910`; return this.createData(); } @@ -424,12 +421,12 @@ export class FileContentData { this._worksheetData = `` + - `0` + - `123` + - `4567` + - `8910` + - `111213`; + `0` + + `123` + + `4567` + + `8910` + + `111213`; return this.createData(); } @@ -444,12 +441,12 @@ export class FileContentData { this._worksheetData = `` + - `0` + - `1` + - `23` + - `45` + - ``; + `0` + + `1` + + `23` + + `45` + + ``; return this.createData(); } @@ -546,22 +543,22 @@ export class FileContentData { this._worksheetData = `` + - `` + - `0123` + - `4567` + - `891011` + - `121310` + - `14151617181920` + - `21222324` + - `252627` + - `28293031` + - `323334` + - `35362937` + - `38394041` + - ``; + `` + + `0123` + + `4567` + + `891011` + + `121310` + + `14151617181920` + + `21222324` + + `252627` + + `28293031` + + `323334` + + `35362937` + + `38394041` + + ``; return this.createData(); } @@ -578,13 +575,13 @@ export class FileContentData { this._worksheetData = `` + - `` + - `` + - `0` + - `1234` + - `5678` + - `91011` + - `12131014`; + `` + + `` + + `0` + + `1234` + + `5678` + + `91011` + + `12131014`; return this.createData(); } @@ -601,13 +598,13 @@ export class FileContentData { this._worksheetData = `` + - `` + - `01234` + - `567` + - `89101112131415`; + `` + + `01234` + + `567` + + `89101112131415`; return this.createData(); } @@ -626,16 +623,16 @@ export class FileContentData { this._worksheetData = `` + - `` + - `0123` + - `4567` + - `891011` + - `121310` + - `141516171819202122`; + `` + + `0123` + + `4567` + + `891011` + + `121310` + + `141516171819202122`; return this.createData(); } @@ -680,15 +677,15 @@ export class FileContentData { this._worksheetData = `` + - `` + - `0` + - `123` + - `4565` + - `789` + - `101112` + - `131415` + - `161714` + - `1819`; + `` + + `0` + + `123` + + `4565` + + `789` + + `101112` + + `131415` + + `161714` + + `1819`; return this.createData(); } @@ -774,8 +771,7 @@ export class FileContentData { } private updateRowHeight(height: number) { - let wsSettings = - `0121342563764895101161213714158161791815101920`; + let wsSettings = `0121342563764895101161213714158161791815101920`; switch (height) { case 20: @@ -973,7 +969,7 @@ export class FileContentData { public get treeGridWithAdvancedFilters() { this._sharedStringsData = - `count="15" uniqueCount="14">IDParentIDNameJobTitleAgeCasey HoustonVice PresidentGilberto ToddDirectorTanya BennettDebra MortonAssociate Software DeveloperJack SimonSoftware Developer`; + `count="15" uniqueCount="14">IDParentIDNameJobTitleAgeCasey HoustonVice PresidentGilberto ToddDirectorTanya BennettDebra MortonAssociate Software DeveloperJack SimonSoftware Developer`; this._tableData = `ref="A1:E6" totalsRowShown="0"> `; @@ -990,7 +986,7 @@ export class FileContentData { public get emptyTreeGridWithExportedHeaders() { this._sharedStringsData = - `count="5" uniqueCount="5">IDParentIDNameJobTitleAge`; + `count="5" uniqueCount="5">IDParentIDNameJobTitleAge`; this._tableData = `ref="A1:E2" totalsRowShown="0"> `; @@ -1058,7 +1054,7 @@ export class FileContentData { public get gridWithAdvancedFilters() { this._sharedStringsData = - `count="11" uniqueCount="11">IDNameJobTitleErma WalshCEODebra MortonAssociate Software DeveloperErika WellsSoftware Development Team LeadEduardo RamirezManager`; + `count="11" uniqueCount="11">IDNameJobTitleErma WalshCEODebra MortonAssociate Software DeveloperErika WellsSoftware Development Team LeadEduardo RamirezManager`; this._tableData = `ref="A1:C5" totalsRowShown="0"> `; @@ -1074,7 +1070,7 @@ export class FileContentData { public get personJobHoursDataPerformance() { this._sharedStringsData = - `count="18" uniqueCount="15">IDNameJobTitleWorkingHoursHireDatePerformanceCasey HoustonVice President2017-06-19T11:43:07.714Z[object Object],[object Object],[object Object],[object Object]Gilberto ToddDirector2015-12-18T11:23:17.714ZTanya Bennett2005-11-18T11:23:17.714Z`; + `count="18" uniqueCount="15">IDNameJobTitleWorkingHoursHireDatePerformanceCasey HoustonVice President2017-06-19T11:43:07.714Z[object Object],[object Object],[object Object],[object Object]Gilberto ToddDirector2015-12-18T11:23:17.714ZTanya Bennett2005-11-18T11:23:17.714Z`; this._tableData = `ref="A1:F4" totalsRowShown="0"> `; @@ -1090,7 +1086,7 @@ export class FileContentData { public get hireDate() { this._sharedStringsData = - `count="1" uniqueCount="1">HireDate`; + `count="1" uniqueCount="1">HireDate`; this._tableData = `ref="A1:A6" totalsRowShown="0"> `; @@ -1728,9 +1724,9 @@ export class FileContentData { 01232545511121733281.02999999993313253.3134158081.9535131745.1136127565.6437198731.6338140424.7539118538.6240116352.7341130413.8742130797.9343137109.544124370.7845110792.434617229.73471176455.664814418.1549118192.1650124663.1451113113.945212497.1153158532.8913113253.313313253.31141158081.9534158081.95151259310.7535131745.1136127565.64161198731.6337198731.63171140424.7538140424.75181234891.3539118538.6240116352.73191130413.8741130413.87201130797.9342130797.93211137109.543137109.5221124370.78` + - `44124370.78231110792.4345110792.4324117229.734617229.732511176455.66471176455.6626114418.154814418.15271118192.1649118192.16281124663.1450124663.14291113113.9451113113.9430112497.115212497.11311158532.8953158532.8921113253.313313253.3113113253.313313253.313113117392.734158081.9535131745.1136127565.64141158081.9534158081.95151259310.7535131745.1136127565.644112139156.3837198731.6338140424.75161198731.6337198731.63171140424.7538140424.75511234891.3539118538.6240116352.73181234891.35` + - `39118538.6240116352.73611130413.8741130413.87191130413.8741130413.87711392278.2099999999942130797.9343137109.544124370.78201130797.9342130797.93211137109.543137109.5221124370.7844124370.788113194477.8245110792.434617229.73471176455.66231110792.4345110792.4324117229.734617229.732511176455.66471176455.6691114418.154814418.1526114418.154814418.151011242855.349118192.1650124663.14271118192.1649118192.16281124663.1450124663.141111374143.9451113113.945212497.1153158532.89291113113.94` + - `51113113.9430112497.115212497.11311158532.8953158532.89 `; + `44124370.78231110792.4345110792.4324117229.734617229.732511176455.66471176455.6626114418.154814418.15271118192.1649118192.16281124663.1450124663.14291113113.9451113113.9430112497.115212497.11311158532.8953158532.8921113253.313313253.3113113253.313313253.313113117392.734158081.9535131745.1136127565.64141158081.9534158081.95151259310.7535131745.1136127565.644112139156.3837198731.6338140424.75161198731.6337198731.63171140424.7538140424.75511234891.3539118538.6240116352.73181234891.35` + + `39118538.6240116352.73611130413.8741130413.87191130413.8741130413.87711392278.2099999999942130797.9343137109.544124370.78201130797.9342130797.93211137109.543137109.5221124370.7844124370.788113194477.8245110792.434617229.73471176455.66231110792.4345110792.4324117229.734617229.732511176455.66471176455.6691114418.154814418.1526114418.154814418.151011242855.349118192.1650124663.14271118192.1649118192.16281124663.1450124663.141111374143.9451113113.945212497.1153158532.89291113113.94` + + `51113113.9430112497.115212497.11311158532.8953158532.89 `; return this.createData(); } @@ -1748,7 +1744,7 @@ export class FileContentData { - 01234567200869120869320106723011612150136717014615330166927017691101861960106700206210086152502269270236241701067202561260266916010621902762829023629001661920303132103331912034311524026311526035317180"Count: "&_xlfn.COUNTIF(F2:F28, 0)"Count: "&_xlfn.COUNTIF(F2:F28, 0)"Count: "&_xlfn.COUNTIF(F2:F28, 0)"Count: "&_xlfn.COUNTIF(F2:F28, 0)"""""""""Min: "&_xlfn.MIN(_xlfn.IF(F2:F28=0, D2:D28))"""""""""Max: "&_xlfn.MAX(_xlfn.IF(F2:F28=0, D2:D28))"""""""""Sum: "&_xlfn.SUMIF(F2:F28, 0, D2:D28)"""""""""Avg: "&_xlfn.AVERAGEIF(F2:F28, 0, D2:D28)""` + 01234567200869120869320106723011612150136717014615330166927017691101861960106700206210086152502269270236241701067202561260266916010621902762829023629001661920303132103331912034311524026311526035317180"Count: "&_xlfn.COUNTIF(F2:F28, 0)"Count: "&_xlfn.COUNTIF(F2:F28, 0)"Count: "&_xlfn.COUNTIF(F2:F28, 0)"Count: "&_xlfn.COUNTIF(F2:F28, 0)"""""""""Min: "&_xlfn.MIN(_xlfn.IF(F2:F28=0, D2:D28))"""""""""Max: "&_xlfn.MAX(_xlfn.IF(F2:F28=0, D2:D28))"""""""""Sum: "&_xlfn.SUMIF(F2:F28, 0, D2:D28)"""""""""Avg: "&_xlfn.AVERAGEIF(F2:F28, 0, D2:D28)""`; return this.createData(); } @@ -1767,7 +1763,7 @@ export class FileContentData { - 01234514762008-04-20T00:00:00557047582011-07-03T00:00:00437195792009-07-19T00:00:0029101317112014-09-18T00:00:003171711122015-10-17T00:00:0035102998132009-11-11T00:00:004472"""Count: "&_xlfn.COUNTIF(G6:G7, 2)"Count: "&_xlfn.COUNTIF(G6:G7, 2)"Count: "&_xlfn.COUNTIF(G6:G7, 2)"Count: "&_xlfn.COUNTIF(G6:G7, 2)"""""""Earliest: "&_xlfn.TEXT(_xlfn.MIN(_xlfn.IF(G6:G7=2, C6:C7)), "m/d/yyyy")"Min: "&_xlfn.MIN(_xlfn.IF(G6:G7=2, D6:D7))"""""""""Latest: "&_xlfn.TEXT(_xlfn.MAX(_xlfn.IF(G6:G7=2, C6:C7)), "m/d/yyyy")"Max: "&_xlfn.MAX(_xlfn.IF(G6:G7=2, D6:D7))"""""""""""Sum: "&_xlfn.SUMIF(G6:G7, 2, D6:D7)"""""""""""Avg: "&_xlfn.AVERAGEIF(G6:G7, 2, D6:D7)"""""""Count: "&_xlfn.COUNTIF(G3:G5, 1)"Count: "&_xlfn.COUNTIF(G3:G5, 1)"Count: "&_xlfn.COUNTIF(G3:G5, 1)"Count: "&_xlfn.COUNTIF(G3:G5, 1)"""""""Earliest: "&_xlfn.TEXT(_xlfn.MIN(_xlfn.IF(G3:G5=1, C3:C5)), "m/d/yyyy")"Min: "&_xlfn.MIN(_xlfn.IF(G3:G5=1, D3:D5))"""""""""Latest: "&_xlfn.TEXT(_xlfn.MAX(_xlfn.IF(G3:G5=1, C3:C5)), "m/d/yyyy")"Max: "&_xlfn.MAX(_xlfn.IF(G3:G5=1, D3:D5))"""""""""""Sum: "&_xlfn.SUMIF(G3:G5, 1, D3:D5)"""""""""""Avg: "&_xlfn.AVERAGEIF(G3:G5, 1, D3:D5)""""847142014-02-22T00:00:00427019182014-02-22T00:00:00497015192014-05-04T00:00:0044101"""Count: "&_xlfn.COUNTIF(G23:G23, 1)"Count: "&_xlfn.COUNTIF(G23:G23, 1)"Count: "&_xlfn.COUNTIF(G23:G23, 1)"Count: "&_xlfn.COUNTIF(G23:G23, 1)"""""""Earliest: "&_xlfn.TEXT(_xlfn.MIN(_xlfn.IF(G23:G23=1, C23:C23)), "m/d/yyyy")"Min: "&_xlfn.MIN(_xlfn.IF(G23:G23=1, D23:D23))"""""""""Latest: "&_xlfn.TEXT(_xlfn.MAX(_xlfn.IF(G23:G23=1, C23:C23)), "m/d/yyyy")"Max: "&_xlfn.MAX(_xlfn.IF(G23:G23=1, D23:D23))"""""""""""Sum: "&_xlfn.SUMIF(G23:G23, 1, D23:D23)"""""""""""Avg: "&_xlfn.AVERAGEIF(G23:G23, 1, D23:D23)""""17202010-02-01T00:00:006170"""Count: "&_xlfn.COUNTIF(G2:G34, 0)"Count: "&_xlfn.COUNTIF(G2:G34, 0)"Count: "&_xlfn.COUNTIF(G2:G34, 0)"Count: "&_xlfn.COUNTIF(G2:G34, 0)"""""""Earliest: "&_xlfn.TEXT(_xlfn.MIN(_xlfn.IF(G2:G34=0, C2:C34)), "m/d/yyyy")"Min: "&_xlfn.MIN(_xlfn.IF(G2:G34=0, D2:D34))"""""""""Latest: "&_xlfn.TEXT(_xlfn.MAX(_xlfn.IF(G2:G34=0, C2:C34)), "m/d/yyyy")"Max: "&_xlfn.MAX(_xlfn.IF(G2:G34=0, D2:D34))"""""""""""Sum: "&_xlfn.SUMIF(G2:G34, 0, D2:D34)"""""""""""Avg: "&_xlfn.AVERAGEIF(G2:G34, 0, D2:D34)""""` + 01234514762008-04-20T00:00:00557047582011-07-03T00:00:00437195792009-07-19T00:00:0029101317112014-09-18T00:00:003171711122015-10-17T00:00:0035102998132009-11-11T00:00:004472"""Count: "&_xlfn.COUNTIF(G6:G7, 2)"Count: "&_xlfn.COUNTIF(G6:G7, 2)"Count: "&_xlfn.COUNTIF(G6:G7, 2)"Count: "&_xlfn.COUNTIF(G6:G7, 2)"""""""Earliest: "&_xlfn.TEXT(_xlfn.MIN(_xlfn.IF(G6:G7=2, C6:C7)), "m/d/yyyy")"Min: "&_xlfn.MIN(_xlfn.IF(G6:G7=2, D6:D7))"""""""""Latest: "&_xlfn.TEXT(_xlfn.MAX(_xlfn.IF(G6:G7=2, C6:C7)), "m/d/yyyy")"Max: "&_xlfn.MAX(_xlfn.IF(G6:G7=2, D6:D7))"""""""""""Sum: "&_xlfn.SUMIF(G6:G7, 2, D6:D7)"""""""""""Avg: "&_xlfn.AVERAGEIF(G6:G7, 2, D6:D7)"""""""Count: "&_xlfn.COUNTIF(G3:G5, 1)"Count: "&_xlfn.COUNTIF(G3:G5, 1)"Count: "&_xlfn.COUNTIF(G3:G5, 1)"Count: "&_xlfn.COUNTIF(G3:G5, 1)"""""""Earliest: "&_xlfn.TEXT(_xlfn.MIN(_xlfn.IF(G3:G5=1, C3:C5)), "m/d/yyyy")"Min: "&_xlfn.MIN(_xlfn.IF(G3:G5=1, D3:D5))"""""""""Latest: "&_xlfn.TEXT(_xlfn.MAX(_xlfn.IF(G3:G5=1, C3:C5)), "m/d/yyyy")"Max: "&_xlfn.MAX(_xlfn.IF(G3:G5=1, D3:D5))"""""""""""Sum: "&_xlfn.SUMIF(G3:G5, 1, D3:D5)"""""""""""Avg: "&_xlfn.AVERAGEIF(G3:G5, 1, D3:D5)""""847142014-02-22T00:00:00427019182014-02-22T00:00:00497015192014-05-04T00:00:0044101"""Count: "&_xlfn.COUNTIF(G23:G23, 1)"Count: "&_xlfn.COUNTIF(G23:G23, 1)"Count: "&_xlfn.COUNTIF(G23:G23, 1)"Count: "&_xlfn.COUNTIF(G23:G23, 1)"""""""Earliest: "&_xlfn.TEXT(_xlfn.MIN(_xlfn.IF(G23:G23=1, C23:C23)), "m/d/yyyy")"Min: "&_xlfn.MIN(_xlfn.IF(G23:G23=1, D23:D23))"""""""""Latest: "&_xlfn.TEXT(_xlfn.MAX(_xlfn.IF(G23:G23=1, C23:C23)), "m/d/yyyy")"Max: "&_xlfn.MAX(_xlfn.IF(G23:G23=1, D23:D23))"""""""""""Sum: "&_xlfn.SUMIF(G23:G23, 1, D23:D23)"""""""""""Avg: "&_xlfn.AVERAGEIF(G23:G23, 1, D23:D23)""""17202010-02-01T00:00:006170"""Count: "&_xlfn.COUNTIF(G2:G34, 0)"Count: "&_xlfn.COUNTIF(G2:G34, 0)"Count: "&_xlfn.COUNTIF(G2:G34, 0)"Count: "&_xlfn.COUNTIF(G2:G34, 0)"""""""Earliest: "&_xlfn.TEXT(_xlfn.MIN(_xlfn.IF(G2:G34=0, C2:C34)), "m/d/yyyy")"Min: "&_xlfn.MIN(_xlfn.IF(G2:G34=0, D2:D34))"""""""""Latest: "&_xlfn.TEXT(_xlfn.MAX(_xlfn.IF(G2:G34=0, C2:C34)), "m/d/yyyy")"Max: "&_xlfn.MAX(_xlfn.IF(G2:G34=0, D2:D34))"""""""""""Sum: "&_xlfn.SUMIF(G2:G34, 0, D2:D34)"""""""""""Avg: "&_xlfn.AVERAGEIF(G2:G34, 0, D2:D34)""""`; return this.createData(); } @@ -1781,7 +1777,7 @@ export class FileContentData { - 012345201160067894102000-05-31T00:00:00864211112131441152019-06-09T00:00:001622172019-06-09T00:00:001823192019-06-09T00:00:002024212019-06-09T00:00:00222"""Count: "&_xlfn.COUNTIF(I6:I9, 2)""""""232001-05-31T00:00:001221262021-12-19T00:00:00111312020-07-17T00:00:00531"""""Count: "&_xlfn.COUNTIF(I4:I19, 1)"Count: "&_xlfn.COUNTIF(I4:I19, 1)"""""""Min: "&_xlfn.MIN(_xlfn.IF(I4:I19=1, D4:D19))"Min: "&_xlfn.MIN(_xlfn.IF(I4:I19=1, E4:E19))"""""""Max: "&_xlfn.MAX(_xlfn.IF(I4:I19=1, D4:D19))"Max: "&_xlfn.MAX(_xlfn.IF(I4:I19=1, E4:E19))"""""""Sum: "&_xlfn.SUMIF(I4:I19, 1, D4:D19)"Sum: "&_xlfn.SUMIF(I4:I19, 1, E4:E19)"""""""Avg: "&_xlfn.AVERAGEIF(I4:I19, 1, D4:D19)"Avg: "&_xlfn.AVERAGEIF(I4:I19, 1, E4:E19)""352009011067894362000-05-31T00:00:00864211112131441372020-07-17T00:00:002822382020-07-17T00:00:002823392020-07-17T00:00:00282"""Count: "&_xlfn.COUNTIF(I33:I35, 2)"""""""""""Count: "&_xlfn.COUNTIF(I31:I31, 1)"Count: "&_xlfn.COUNTIF(I31:I31, 1)"""""""Min: "&_xlfn.MIN(_xlfn.IF(I31:I31=1, D31:D31))"Min: "&_xlfn.MIN(_xlfn.IF(I31:I31=1, E31:E31))"""""""Max: "&_xlfn.MAX(_xlfn.IF(I31:I31=1, D31:D31))"Max: "&_xlfn.MAX(_xlfn.IF(I31:I31=1, E31:E31))"""""""Sum: "&_xlfn.SUMIF(I31:I31, 1, D31:D31)"Sum: "&_xlfn.SUMIF(I31:I31, 1, E31:E31)"""""""Avg: "&_xlfn.AVERAGEIF(I31:I31, 1, D31:D31)"Avg: "&_xlfn.AVERAGEIF(I31:I31, 1, E31:E31)""402015310"Count: "&_xlfn.COUNTIF(I2:I42, 0)"Count: "&_xlfn.COUNTIF(I2:I42, 0)"Min: "&_xlfn.MIN(_xlfn.IF(I2:I42=0, C2:C42))"Min: "&_xlfn.MIN(_xlfn.IF(I2:I42=0, D2:D42))"""""""Max: "&_xlfn.MAX(_xlfn.IF(I2:I42=0, C2:C42))"Max: "&_xlfn.MAX(_xlfn.IF(I2:I42=0, D2:D42))"""""""Avg: "&_xlfn.AVERAGEIF(I2:I42, 0, C2:C42)"Avg: "&_xlfn.AVERAGEIF(I2:I42, 0, D2:D42)""` + 012345201160067894102000-05-31T00:00:00864211112131441152019-06-09T00:00:001622172019-06-09T00:00:001823192019-06-09T00:00:002024212019-06-09T00:00:00222"""Count: "&_xlfn.COUNTIF(I6:I9, 2)""""""232001-05-31T00:00:001221262021-12-19T00:00:00111312020-07-17T00:00:00531"""""Count: "&_xlfn.COUNTIF(I4:I19, 1)"Count: "&_xlfn.COUNTIF(I4:I19, 1)"""""""Min: "&_xlfn.MIN(_xlfn.IF(I4:I19=1, D4:D19))"Min: "&_xlfn.MIN(_xlfn.IF(I4:I19=1, E4:E19))"""""""Max: "&_xlfn.MAX(_xlfn.IF(I4:I19=1, D4:D19))"Max: "&_xlfn.MAX(_xlfn.IF(I4:I19=1, E4:E19))"""""""Sum: "&_xlfn.SUMIF(I4:I19, 1, D4:D19)"Sum: "&_xlfn.SUMIF(I4:I19, 1, E4:E19)"""""""Avg: "&_xlfn.AVERAGEIF(I4:I19, 1, D4:D19)"Avg: "&_xlfn.AVERAGEIF(I4:I19, 1, E4:E19)""352009011067894362000-05-31T00:00:00864211112131441372020-07-17T00:00:002822382020-07-17T00:00:002823392020-07-17T00:00:00282"""Count: "&_xlfn.COUNTIF(I33:I35, 2)"""""""""""Count: "&_xlfn.COUNTIF(I31:I31, 1)"Count: "&_xlfn.COUNTIF(I31:I31, 1)"""""""Min: "&_xlfn.MIN(_xlfn.IF(I31:I31=1, D31:D31))"Min: "&_xlfn.MIN(_xlfn.IF(I31:I31=1, E31:E31))"""""""Max: "&_xlfn.MAX(_xlfn.IF(I31:I31=1, D31:D31))"Max: "&_xlfn.MAX(_xlfn.IF(I31:I31=1, E31:E31))"""""""Sum: "&_xlfn.SUMIF(I31:I31, 1, D31:D31)"Sum: "&_xlfn.SUMIF(I31:I31, 1, E31:E31)"""""""Avg: "&_xlfn.AVERAGEIF(I31:I31, 1, D31:D31)"Avg: "&_xlfn.AVERAGEIF(I31:I31, 1, E31:E31)""402015310"Count: "&_xlfn.COUNTIF(I2:I42, 0)"Count: "&_xlfn.COUNTIF(I2:I42, 0)"Min: "&_xlfn.MIN(_xlfn.IF(I2:I42=0, C2:C42))"Min: "&_xlfn.MIN(_xlfn.IF(I2:I42=0, D2:D42))"""""""Max: "&_xlfn.MAX(_xlfn.IF(I2:I42=0, C2:C42))"Max: "&_xlfn.MAX(_xlfn.IF(I2:I42=0, D2:D42))"""""""Avg: "&_xlfn.AVERAGEIF(I2:I42, 0, C2:C42)"Avg: "&_xlfn.AVERAGEIF(I2:I42, 0, D2:D42)""`; return this.createData(); } @@ -1800,7 +1796,7 @@ export class FileContentData { - 012343536363732038393273103113031231332931431139315323303231635315317318323932731937317320393113213223253233123323243931632532630327317328322333329318363303313931233233331334322324324322326335373183"Count: "&_xlfn.COUNTIF(C2:C74, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C2:C74=3, A2:A74))"""Max: "&_xlfn.MAX(_xlfn.IF(C2:C74=3, A2:A74))"""Sum: "&_xlfn.SUMIF(C2:C74, 3, A2:A74)"""Avg: "&_xlfn.AVERAGEIF(C2:C74, 3, A2:A74)""` + 012343536363732038393273103113031231332931431139315323303231635315317318323932731937317320393113213223253233123323243931632532630327317328322333329318363303313931233233331334322324324322326335373183"Count: "&_xlfn.COUNTIF(C2:C74, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C2:C74=3, A2:A74))"""Max: "&_xlfn.MAX(_xlfn.IF(C2:C74=3, A2:A74))"""Sum: "&_xlfn.SUMIF(C2:C74, 3, A2:A74)"""Avg: "&_xlfn.AVERAGEIF(C2:C74, 3, A2:A74)""`; return this.createData(); } @@ -1821,9 +1817,9 @@ export class FileContentData { 0123435363"Count: "&_xlfn.COUNTIF(C4:C5, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C4:C5=3, A4:A5))"""Max: "&_xlfn.MAX(_xlfn.IF(C4:C5=3, A4:A5))"""Sum: "&_xlfn.SUMIF(C4:C5, 3, A4:A5)"""Avg: "&_xlfn.AVERAGEIF(C4:C5, 3, A4:A5)"""Count: "&_xlfn.COUNTIF(C3:C5, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C3:C5=3, A3:A5))"""Max: "&_xlfn.MAX(_xlfn.IF(C3:C5=3, A3:A5))"""Sum: "&_xlfn.SUMIF(C3:C5, 3, A3:A5)"""Avg: "&_xlfn.AVERAGEIF(C3:C5, 3, A3:A5)""6373203"Count: "&_xlfn.COUNTIF(C17:C18, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C17:C18=3, A17:A18))"""Max: "&_xlfn.MAX(_xlfn.IF(C17:C18=3, A17:A18))"""Sum: "&_xlfn.SUMIF(C17:C18, 3, A17:A18)"""Avg: "&_xlfn.AVERAGEIF(C17:C18, 3, A17:A18)"""Count: "&_xlfn.COUNTIF(C16:C18, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C16:C18=3, A16:A18))"""Max: "&_xlfn.MAX(_xlfn.IF(C16:C18=3, A16:A18))"""Sum: "&_xlfn.SUMIF(C16:C18, 3, A16:A18)"""Avg: "&_xlfn.AVERAGEIF(C16:C18, 3, A16:A18)""8393273"Count: "&_xlfn.COUNTIF(C30:C31, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C30:C31=3, A30:A31))"""Max: "&_xlfn.MAX(_xlfn.IF(C30:C31=3, A30:A31))"""Sum: "&_xlfn.SUMIF(C30:C31, 3, A30:A31)"""Avg: "&_xlfn.AVERAGEIF(C30:C31, 3, A30:A31)"""Count: "&_xlfn.COUNTIF(C29:C31, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C29:C31=3, A29:A31))"""Max: "&_xlfn.MAX(_xlfn.IF(C29:C31=3, A29:A31))"""Sum: "&_xlfn.SUMIF(C29:C31, 3, A29:A31)"""Avg: "&_xlfn.AVERAGEIF(C29:C31, 3, A29:A31)""10311303"Count: "&_xlfn.COUNTIF(C43:C44, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C43:C44=3, A43:A44))"""Max: "&_xlfn.MAX(_xlfn.IF(C43:C44=3, A43:A44))"""Sum: "&_xlfn.SUMIF(C43:C44, 3, A43:A44)"""Avg: "&_xlfn.AVERAGEIF(C43:C44, 3, A43:A44)"""Count: "&_xlfn.COUNTIF(C42:C44, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C42:C44=3, A42:A44))"""Max: "&_xlfn.MAX(_xlfn.IF(C42:C44=3, A42:A44))"""Sum: "&_xlfn.SUMIF(C42:C44, 3, A42:A44)"""Avg: "&_xlfn.AVERAGEIF(C42:C44, 3, A42:A44)""123133293"Count: "&_xlfn.COUNTIF(C56:C57, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C56:C57=3, A56:A57))"""Max: "&_xlfn.MAX(_xlfn.IF(C56:C57=3, A56:A57))"""Sum: "&_xlfn.SUMIF(C56:C57, 3, A56:A57)"""Avg: "&_xlfn.AVERAGEIF(C56:C57, 3, A56:A57)"""Count: "&_xlfn.COUNTIF(C55:C57, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C55:C57=3, A55:A57))"""Max: "&_xlfn.MAX(_xlfn.IF(C55:C57=3, A55:A57))"""Sum: "&_xlfn.SUMIF(C55:C57, 3, A55:A57)"""Avg: "&_xlfn.AVERAGEIF(C55:C57, 3, A55:A57)""14311393"Count: "&_xlfn.COUNTIF(C69:C70, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C69:C70=3, A69:A70))"""Max: "&_xlfn.MAX(_xlfn.IF(C69:C70=3, A69:A70))"""Sum: "&_xlfn.SUMIF(C69:C70, 3, A69:A70)"""Avg: "&_xlfn.AVERAGEIF(C69:C70, 3, A69:A70)""1532330323"Count: "&_xlfn.COUNTIF(C76:C79, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C76:C79=3, A76:A79))"""Max: "&_xlfn.MAX(_xlfn.IF(C76:C79=3, A76:A79))"""Sum: "&_xlfn.SUMIF(C76:C79, 3, A76:A79)"""Avg: "&_xlfn.AVERAGEIF(C76:C79, 3, A76:A79)"""Count: "&_xlfn.COUNTIF(C68:C79, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C68:C79=3, A68:A79))"""Max: "&_xlfn.MAX(_xlfn.IF(C68:C79=3, A68:A79))"""Sum: "&_xlfn.SUMIF(C68:C79, 3, A68:A79)"""Avg: "&_xlfn.AVERAGEIF(C68:C79, 3, A68:A79)""16353153"Count: "&_xlfn.COUNTIF(C91:C92, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C91:C92=3, A91:A92))"""Max: "&_xlfn.MAX(_xlfn.IF(C91:C92=3, A91:A92))"""Sum: "&_xlfn.SUMIF(C91:C92, 3, A91:A92)"""Avg: "&_xlfn.AVERAGEIF(C91:C92, 3, A91:A92)"""Count: "&_xlfn.COUNTIF(C90:C92, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C90:C92=3, A90:A92))"""Max: "&_xlfn.MAX(_xlfn.IF(C90:C92=3, A90:A92))"""Sum: "&_xlfn.SUMIF(C90:C92, 3, A90:A92)"""Avg: "&_xlfn.AVERAGEIF(C90:C92, 3, A90:A92)""17318323"Count: "&_xlfn.COUNTIF(C104:C105, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C104:C105=3, A104:A105))"""Max: "&_xlfn.MAX(_xlfn.IF(C104:C105=3, A104:A105))"""Sum: "&_xlfn.SUMIF(C104:C105, 3, A104:A105)"""Avg: "&_xlfn.AVERAGEIF(C104:C105, 3, A104:A105)""93273"Count: "&_xlfn.COUNTIF(C111:C112, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C111:C112=3, A111:A112))"""Max: "&_xlfn.MAX(_xlfn.IF(C111:C112=3, A111:A112))"""Sum: "&_xlfn.SUMIF(C111:C112, 3, A111:A112)"""Avg: "&_xlfn.AVERAGEIF(C111:C112, 3, A111:A112)"""Count: "&_xlfn.COUNTIF(C103:C112, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C103:C112=3, A103:A112))"""Max: "&_xlfn.MAX(_xlfn.IF(C103:C112=3, A103:A112))"""Sum: "&_xlfn.SUMIF(C103:C112, 3, A103:A112)"""Avg: "&_xlfn.AVERAGEIF(C103:C112, 3, A103:A112)""19373173"Count: "&_xlfn.COUNTIF(C124:C125, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C124:C125=3, A124:A125))"""Max: "&_xlfn.MAX(_xlfn.IF(C124:C125=3, A124:A125))"""Sum: "&_xlfn.SUMIF(C124:C125, 3, A124:A125)"""Avg: "&_xlfn.AVERAGEIF(C124:C125, 3, A124:A125)"""Count: "&_xlfn.COUNTIF(C123:C125, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C123:C125=3, A123:A125))"""Max: "&_xlfn.MAX(_xlfn.IF(C123:C125=3, A123:A125))"""Sum: "&_xlfn.SUMIF(C123:C125, 3, A123:A125)"""Avg: "&_xlfn.AVERAGEIF(C123:C125, 3, A123:A125)""20393113"Count: "&_xlfn.COUNTIF(C137:C138, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C137:C138=3, A137:A138))"""Max: "&_xlfn.MAX(_xlfn.IF(C137:C138=3, A137:A138))"" "Sum: "&_xlfn.SUMIF(C137:C138, 3, A137:A138)"""Avg: "&_xlfn.AVERAGEIF(C137:C138, 3, A137:A138)"""Count: "&_xlfn.COUNTIF(C136:C138, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C136:C138=3, A136:A138))"""Max: "&_xlfn.MAX(_xlfn.IF(C136:C138=3, A136:A138))"""Sum: "&_xlfn.SUMIF(C136:C138, 3, A136:A138)"""Avg: "&_xlfn.AVERAGEIF(C136:C138, 3, A136:A138)""213223253"Count: "&_xlfn.COUNTIF(C150:C151, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C150:C151=3, A150:A151))"""Max: "&_xlfn.MAX(_xlfn.IF(C150:C151=3, A150:A151))"""Sum: "&_xlfn.SUMIF(C150:C151, 3, A150:A151)"""Avg: "&_xlfn.AVERAGEIF(C150:C151, 3, A150:A151)""233123323"Count: "&_xlfn.COUNTIF(C157:C159, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C157:C159=3, A157:A159))"""Max: "&_xlfn.MAX(_xlfn.IF(C157:C159=3, A157:A159))"""Sum: "&_xlfn.SUMIF(C157:C159, 3, A157:A159)"""Avg: "&_xlfn.AVERAGEIF(C157:C159, 3, A157:A159)"""Count: "&_xlfn.COUNTIF(C149:C159, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C149:C159=3, A149:A159))"""Max: "&_xlfn.MAX(_xlfn.IF(C149:C159=3, A149:A159))"""Sum: "&_xlfn.SUMIF(C149:C159, 3, A149:A159)"""Avg: "&_xlfn.AVERAGEIF(C149:C159, 3, A149:A159)""24393163"Count: "&_xlfn.COUNTIF(C171:C172, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C171:C172=3, A171:A172))"""Max: "&_xlfn.MAX(_xlfn.IF(C171:C172=3, A171:A172))"""Sum: "&_xlfn.SUMIF(C171:C172, 3, A171:A172)"""Avg: "&_xlfn.AVERAGEIF(C171:C172, 3, A171:A172)"""Count: "&_xlfn.COUNTIF(C170:C172, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C170:C172=3, A170:A172))"""Max: "&_xlfn.MAX(_xlfn.IF(C170:C172=3, A170:A172))"""Sum: "&_xlfn.SUMIF(C170:C172, 3, A170:A172)"""Avg: "&_xlfn.AVERAGEIF(C170:C172, 3, A170:A172)""25326303"Count: "&_xlfn.COUNTIF(C184:C185, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C184:C185=3, A184:A185))"""Max: "&_xlfn.MAX(_xlfn.IF(C184:C185=3, A184:A185))"""Sum: "&_xlfn.SUMIF(C184:C185, 3, A184:A185)"""Avg: "&_xlfn.AVERAGEIF(C184:C185, 3, A184:A185)""273173"Count: "&_xlfn.COUNTIF(C191:C192, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C191:C192=3, A191:A192))"""Max: "&_xlfn.MAX(_xlfn.IF(C191:C192=3, A191:A192))"""Sum: "&_xlfn.SUMIF(C191:C192, 3, A191:A192)"""Avg: "&_xlfn.AVERAGEIF(C191:C192, 3, A191:A192)"""Count: "&_xlfn.COUNTIF(C183:C192, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C183:C192=3, A183:A192))"""Max: "&_xlfn.MAX(_xlfn.IF(C183:C192=3, A183:A192))"""Sum: "&_xlfn.SUMIF(C183:C192, 3, A183:A192)"""Avg: "&_xlfn.AVERAGEIF(C183:C192, 3, A183:A192)""283223333"Count: "&_xlfn.COUNTIF(C204:C205, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C204:C205=3, A204:A205))"""Max: "&_xlfn.MAX(_xlfn.IF(C204:C205=3, A204:A205))"""Sum: "&_xlfn.SUMIF(C204:C205, 3, A204:A205)"""Avg: "&_xlfn.AVERAGEIF(C204:C205, 3, A204:A205)"""Count: "&_xlfn.COUNTIF(C203:C205, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C203:C205=3, A203:A205))"""Max: "&_xlfn.MAX(_xlfn.IF(C203:C205=3, A203:A205))"""Sum: "&_xlfn.SUMIF(C203:C205, 3, A203:A205)"""Avg: "&_xlfn.AVERAGEIF(C203:C205, 3, A203:A205)""29318363"Count: "&_xlfn.COUNTIF(C217:C218, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C217:C218=3, A217:A218))"""Max: "&_xlfn.MAX(_xlfn.IF(C217:C218=3, A217:A218))"""Sum: "&_xlfn.SUMIF(C217:C218, 3, A217:A218)"""Avg: "&_xlfn.AVERAGEIF(C217:C218, 3, A217:A218)"""Count: "&_xlfn.COUNTIF(C216:C218, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C216:C218=3, A216:A218))"""Max: "&_xlfn.MAX(_xlfn.IF(C216:C218=3, A216:A218))"""Sum: "&_xlfn.SUMIF(C216:C218, 3, A216:A218)"""Avg: "&_xlfn.AVERAGEIF(C216:C218, 3, A216:A218)"""Count: "&_xlfn.COUNTIF(C2:C218, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C2:C218=3, A2:A218))"""Max: "&_xlfn.MAX(_xlfn.IF(C2:C218=3, A2:A218))"""Sum: "&_xlfn.SUMIF(C2:C218, 3, A2:A218)"""Avg: "&_xlfn.AVERAGEIF(C2:C218, 3, A2:A218)""30331393123"Count: "&_xlfn.COUNTIF(C236:C237, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C236:C237=3, A236:A237))"""Max: "&_xlfn.MAX(_xlfn.IF(C236:C237=3, A236:A237))"""Sum: "&_xlfn.SUMIF(C236:C237, 3, A236:A237)"""Avg: "&_xlfn.AVERAGEIF(C236:C237, 3, A236:A237)"""Count: "&_xlfn.COUNTIF(C235:C237, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C235:C237=3, A235:A237))"""Max: "&_xlfn.MAX(_xlfn.IF(C235:C237=3, A235:A237))"""Sum: "&_xlfn.SUMIF(C235:C237, 3, A235:A237)"""Avg: "&_xlfn.AVERAGEIF(C235:C237, 3, A235:A237)""32333313"Count: "&_xlfn.COUNTIF(C249:C250, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C249:C250=3, A249:A250))"""Max: "&_xlfn.MAX(_xlfn.IF(C249:C250=3, A249:A250))"""Sum: "&_xlfn.SUMIF(C249:C250, 3, A249:A250)"""Avg: "&_xlfn.AVERAGEIF(C249:C250, 3, A249:A250)"""Count: "&_xlfn.COUNTIF(C248:C250, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C248:C250=3, A248:A250))"""Max: "&_xlfn.MAX(_xlfn.IF(C248:C250=3, A248:A250))"""Sum: "&_xlfn.SUMIF(C248:C250, 3, A248:A250)"""Avg: "&_xlfn.AVERAGEIF(C248:C250, 3, A248:A250)""343223243"Count: "&_xlfn.COUNTIF(C262:C263, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C262:C263=3, A262:A263))"""Max: "&_xlfn.MAX(_xlfn.IF(C262:C263=3, A262:A263))"""Sum: "&_xlfn.SUMIF(C262:C263, 3, A262:A263)"""Avg: "&_xlfn.AVERAGEIF(C262:C263, 3, A262:A263)"""Count: "&_xlfn.COUNTIF(C261:C263, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C261:C263=3, A261:A263))"""Max: "&_xlfn.MAX(_xlfn.IF(C261:C263=3, A261:A263))"""Sum: "&_xlfn.SUMIF(C261:C263, 3, A261:A263)"""Avg: "&_xlfn.AVERAGEIF(C261:C263, 3, A261:A263)""243223 - 263"Count: "&_xlfn.COUNTIF(C275:C276, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C275:C276=3, A275:A276))"""Max: "&_xlfn.MAX(_xlfn.IF(C275:C276=3, A275:A276))"""Sum: "&_xlfn.SUMIF(C275:C276, 3, A275:A276)"""Avg: "&_xlfn.AVERAGEIF(C275:C276, 3, A275:A276)"""Count: "&_xlfn.COUNTIF(C274:C276, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C274:C276=3, A274:A276))"""Max: "&_xlfn.MAX(_xlfn.IF(C274:C276=3, A274:A276))"""Sum: "&_xlfn.SUMIF(C274:C276, 3, A274:A276)"""Avg: "&_xlfn.AVERAGEIF(C274:C276, 3, A274:A276)""35373183"Count: "&_xlfn.COUNTIF(C288:C289, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C288:C289=3, A288:A289))"""Max: "&_xlfn.MAX(_xlfn.IF(C288:C289=3, A288:A289))"""Sum: "&_xlfn.SUMIF(C288:C289, 3, A288:A289)"""Avg: "&_xlfn.AVERAGEIF(C288:C289, 3, A288:A289)"""Count: "&_xlfn.COUNTIF(C287:C289, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C287:C289=3, A287:A289))"""Max: "&_xlfn.MAX(_xlfn.IF(C287:C289=3, A287:A289))"""Sum: "&_xlfn.SUMIF(C287:C289, 3, A287:A289)"""Avg: "&_xlfn.AVERAGEIF(C287:C289, 3, A287:A289)"""Count: "&_xlfn.COUNTIF(C234:C289, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C234:C289=3, A234:A289))"""Max: "&_xlfn.MAX(_xlfn.IF(C234:C289=3, A234:A289))"""Sum: "&_xlfn.SUMIF(C234:C289, 3, A234:A289)"""Avg: "&_xlfn.AVERAGEIF(C234:C289, 3, A234:A289)""` + 263"Count: "&_xlfn.COUNTIF(C275:C276, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C275:C276=3, A275:A276))"""Max: "&_xlfn.MAX(_xlfn.IF(C275:C276=3, A275:A276))"""Sum: "&_xlfn.SUMIF(C275:C276, 3, A275:A276)"""Avg: "&_xlfn.AVERAGEIF(C275:C276, 3, A275:A276)"""Count: "&_xlfn.COUNTIF(C274:C276, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C274:C276=3, A274:A276))"""Max: "&_xlfn.MAX(_xlfn.IF(C274:C276=3, A274:A276))"""Sum: "&_xlfn.SUMIF(C274:C276, 3, A274:A276)"""Avg: "&_xlfn.AVERAGEIF(C274:C276, 3, A274:A276)""35373183"Count: "&_xlfn.COUNTIF(C288:C289, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C288:C289=3, A288:A289))"""Max: "&_xlfn.MAX(_xlfn.IF(C288:C289=3, A288:A289))"""Sum: "&_xlfn.SUMIF(C288:C289, 3, A288:A289)"""Avg: "&_xlfn.AVERAGEIF(C288:C289, 3, A288:A289)"""Count: "&_xlfn.COUNTIF(C287:C289, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C287:C289=3, A287:A289))"""Max: "&_xlfn.MAX(_xlfn.IF(C287:C289=3, A287:A289))"""Sum: "&_xlfn.SUMIF(C287:C289, 3, A287:A289)"""Avg: "&_xlfn.AVERAGEIF(C287:C289, 3, A287:A289)"""Count: "&_xlfn.COUNTIF(C234:C289, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C234:C289=3, A234:A289))"""Max: "&_xlfn.MAX(_xlfn.IF(C234:C289=3, A234:A289))"""Sum: "&_xlfn.SUMIF(C234:C289, 3, A234:A289)"""Avg: "&_xlfn.AVERAGEIF(C234:C289, 3, A234:A289)""`; - return this.createData(); + return this.createData(); } public get exportGroupedGridWithSummariesRootAndChildLevels() { @@ -1842,9 +1838,9 @@ export class FileContentData { 0123435363"Count: "&_xlfn.COUNTIF(C4:C5, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C4:C5=3, A4:A5))"""Max: "&_xlfn.MAX(_xlfn.IF(C4:C5=3, A4:A5))"""Sum: "&_xlfn.SUMIF(C4:C5, 3, A4:A5)"""Avg: "&_xlfn.AVERAGEIF(C4:C5, 3, A4:A5)"""Count: "&_xlfn.COUNTIF(C3:C5, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C3:C5=3, A3:A5))"""Max: "&_xlfn.MAX(_xlfn.IF(C3:C5=3, A3:A5))"""Sum: "&_xlfn.SUMIF(C3:C5, 3, A3:A5)"""Avg: "&_xlfn.AVERAGEIF(C3:C5, 3, A3:A5)""6373203"Count: "&_xlfn.COUNTIF(C17:C18, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C17:C18=3, A17:A18))"""Max: "&_xlfn.MAX(_xlfn.IF(C17:C18=3, A17:A18))"""Sum: "&_xlfn.SUMIF(C17:C18, 3, A17:A18)"""Avg: "&_xlfn.AVERAGEIF(C17:C18, 3, A17:A18)"""Count: "&_xlfn.COUNTIF(C16:C18, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C16:C18=3, A16:A18))"""Max: "&_xlfn.MAX(_xlfn.IF(C16:C18=3, A16:A18))"""Sum: "&_xlfn.SUMIF(C16:C18, 3, A16:A18)"""Avg: "&_xlfn.AVERAGEIF(C16:C18, 3, A16:A18)""8393273"Count: "&_xlfn.COUNTIF(C30:C31, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C30:C31=3, A30:A31))"""Max: "&_xlfn.MAX(_xlfn.IF(C30:C31=3, A30:A31))"""Sum: "&_xlfn.SUMIF(C30:C31, 3, A30:A31)"""Avg: "&_xlfn.AVERAGEIF(C30:C31, 3, A30:A31)"""Count: "&_xlfn.COUNTIF(C29:C31, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C29:C31=3, A29:A31))"""Max: "&_xlfn.MAX(_xlfn.IF(C29:C31=3, A29:A31))"""Sum: "&_xlfn.SUMIF(C29:C31, 3, A29:A31)"""Avg: "&_xlfn.AVERAGEIF(C29:C31, 3, A29:A31)""10311303"Count: "&_xlfn.COUNTIF(C43:C44, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C43:C44=3, A43:A44))"""Max: "&_xlfn.MAX(_xlfn.IF(C43:C44=3, A43:A44))"""Sum: "&_xlfn.SUMIF(C43:C44, 3, A43:A44)"""Avg: "&_xlfn.AVERAGEIF(C43:C44, 3, A43:A44)"""Count: "&_xlfn.COUNTIF(C42:C44, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C42:C44=3, A42:A44))"""Max: "&_xlfn.MAX(_xlfn.IF(C42:C44=3, A42:A44))"""Sum: "&_xlfn.SUMIF(C42:C44, 3, A42:A44)"""Avg: "&_xlfn.AVERAGEIF(C42:C44, 3, A42:A44)""123133293"Count: "&_xlfn.COUNTIF(C56:C57, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C56:C57=3, A56:A57))"""Max: "&_xlfn.MAX(_xlfn.IF(C56:C57=3, A56:A57))"""Sum: "&_xlfn.SUMIF(C56:C57, 3, A56:A57)"""Avg: "&_xlfn.AVERAGEIF(C56:C57, 3, A56:A57)"""Count: "&_xlfn.COUNTIF(C55:C57, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C55:C57=3, A55:A57))"""Max: "&_xlfn.MAX(_xlfn.IF(C55:C57=3, A55:A57))"""Sum: "&_xlfn.SUMIF(C55:C57, 3, A55:A57)"""Avg: "&_xlfn.AVERAGEIF(C55:C57, 3, A55:A57)""14311393"Count: "&_xlfn.COUNTIF(C69:C70, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C69:C70=3, A69:A70))"""Max: "&_xlfn.MAX(_xlfn.IF(C69:C70=3, A69:A70))"""Sum: "&_xlfn.SUMIF(C69:C70, 3, A69:A70)"""Avg: "&_xlfn.AVERAGEIF(C69:C70, 3, A69:A70)""1532330323"Count: "&_xlfn.COUNTIF(C76:C79, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C76:C79=3, A76:A79))"""Max: "&_xlfn.MAX(_xlfn.IF(C76:C79=3, A76:A79))"""Sum: "&_xlfn.SUMIF(C76:C79, 3, A76:A79)"""Avg: "&_xlfn.AVERAGEIF(C76:C79, 3, A76:A79)"""Count: "&_xlfn.COUNTIF(C68:C79, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C68:C79=3, A68:A79))"""Max: "&_xlfn.MAX(_xlfn.IF(C68:C79=3, A68:A79))"""Sum: "&_xlfn.SUMIF(C68:C79, 3, A68:A79)"""Avg: "&_xlfn.AVERAGEIF(C68:C79, 3, A68:A79)""16353153"Count: "&_xlfn.COUNTIF(C91:C92, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C91:C92=3, A91:A92))"""Max: "&_xlfn.MAX(_xlfn.IF(C91:C92=3, A91:A92))"""Sum: "&_xlfn.SUMIF(C91:C92, 3, A91:A92)"""Avg: "&_xlfn.AVERAGEIF(C91:C92, 3, A91:A92)"""Count: "&_xlfn.COUNTIF(C90:C92, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C90:C92=3, A90:A92))"""Max: "&_xlfn.MAX(_xlfn.IF(C90:C92=3, A90:A92))"""Sum: "&_xlfn.SUMIF(C90:C92, 3, A90:A92)"""Avg: "&_xlfn.AVERAGEIF(C90:C92, 3, A90:A92)""17318323"Count: "&_xlfn.COUNTIF(C104:C105, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C104:C105=3, A104:A105))"""Max: "&_xlfn.MAX(_xlfn.IF(C104:C105=3, A104:A105))"""Sum: "&_xlfn.SUMIF(C104:C105, 3, A104:A105)"""Avg: "&_xlfn.AVERAGEIF(C104:C105, 3, A104:A105)""93273"Count: "&_xlfn.COUNTIF(C111:C112, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C111:C112=3, A111:A112))"""Max: "&_xlfn.MAX(_xlfn.IF(C111:C112=3, A111:A112))"""Sum: "&_xlfn.SUMIF(C111:C112, 3, A111:A112)"""Avg: "&_xlfn.AVERAGEIF(C111:C112, 3, A111:A112)"""Count: "&_xlfn.COUNTIF(C103:C112, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C103:C112=3, A103:A112))"""Max: "&_xlfn.MAX(_xlfn.IF(C103:C112=3, A103:A112))"""Sum: "&_xlfn.SUMIF(C103:C112, 3, A103:A112)"""Avg: "&_xlfn.AVERAGEIF(C103:C112, 3, A103:A112)""19373173"Count: "&_xlfn.COUNTIF(C124:C125, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C124:C125=3, A124:A125))"""Max: "&_xlfn.MAX(_xlfn.IF(C124:C125=3, A124:A125))"""Sum: "&_xlfn.SUMIF(C124:C125, 3, A124:A125)"""Avg: "&_xlfn.AVERAGEIF(C124:C125, 3, A124:A125)"""Count: "&_xlfn.COUNTIF(C123:C125, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C123:C125=3, A123:A125))"""Max: "&_xlfn.MAX(_xlfn.IF(C123:C125=3, A123:A125))"""Sum: "&_xlfn.SUMIF(C123:C125, 3, A123:A125)"""Avg: "&_xlfn.AVERAGEIF(C123:C125, 3, A123:A125)""20393113"Count: "&_xlfn.COUNTIF(C137:C138, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C137:C138=3, A137:A138))"""Max: "&_xlfn.MAX(_xlfn.IF(C137:C138=3, A137:A138))"" "Sum: "&_xlfn.SUMIF(C137:C138, 3, A137:A138)"""Avg: "&_xlfn.AVERAGEIF(C137:C138, 3, A137:A138)"""Count: "&_xlfn.COUNTIF(C136:C138, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C136:C138=3, A136:A138))"""Max: "&_xlfn.MAX(_xlfn.IF(C136:C138=3, A136:A138))"""Sum: "&_xlfn.SUMIF(C136:C138, 3, A136:A138)"""Avg: "&_xlfn.AVERAGEIF(C136:C138, 3, A136:A138)""213223253"Count: "&_xlfn.COUNTIF(C150:C151, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C150:C151=3, A150:A151))"""Max: "&_xlfn.MAX(_xlfn.IF(C150:C151=3, A150:A151))"""Sum: "&_xlfn.SUMIF(C150:C151, 3, A150:A151)"""Avg: "&_xlfn.AVERAGEIF(C150:C151, 3, A150:A151)""233123323"Count: "&_xlfn.COUNTIF(C157:C159, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C157:C159=3, A157:A159))"""Max: "&_xlfn.MAX(_xlfn.IF(C157:C159=3, A157:A159))"""Sum: "&_xlfn.SUMIF(C157:C159, 3, A157:A159)"""Avg: "&_xlfn.AVERAGEIF(C157:C159, 3, A157:A159)"""Count: "&_xlfn.COUNTIF(C149:C159, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C149:C159=3, A149:A159))"""Max: "&_xlfn.MAX(_xlfn.IF(C149:C159=3, A149:A159))"""Sum: "&_xlfn.SUMIF(C149:C159, 3, A149:A159)"""Avg: "&_xlfn.AVERAGEIF(C149:C159, 3, A149:A159)""24393163"Count: "&_xlfn.COUNTIF(C171:C172, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C171:C172=3, A171:A172))"""Max: "&_xlfn.MAX(_xlfn.IF(C171:C172=3, A171:A172))"""Sum: "&_xlfn.SUMIF(C171:C172, 3, A171:A172)"""Avg: "&_xlfn.AVERAGEIF(C171:C172, 3, A171:A172)"""Count: "&_xlfn.COUNTIF(C170:C172, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C170:C172=3, A170:A172))"""Max: "&_xlfn.MAX(_xlfn.IF(C170:C172=3, A170:A172))"""Sum: "&_xlfn.SUMIF(C170:C172, 3, A170:A172)"""Avg: "&_xlfn.AVERAGEIF(C170:C172, 3, A170:A172)""25326303"Count: "&_xlfn.COUNTIF(C184:C185, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C184:C185=3, A184:A185))"""Max: "&_xlfn.MAX(_xlfn.IF(C184:C185=3, A184:A185))"""Sum: "&_xlfn.SUMIF(C184:C185, 3, A184:A185)"""Avg: "&_xlfn.AVERAGEIF(C184:C185, 3, A184:A185)""273173"Count: "&_xlfn.COUNTIF(C191:C192, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C191:C192=3, A191:A192))"""Max: "&_xlfn.MAX(_xlfn.IF(C191:C192=3, A191:A192))"""Sum: "&_xlfn.SUMIF(C191:C192, 3, A191:A192)"""Avg: "&_xlfn.AVERAGEIF(C191:C192, 3, A191:A192)"""Count: "&_xlfn.COUNTIF(C183:C192, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C183:C192=3, A183:A192))"""Max: "&_xlfn.MAX(_xlfn.IF(C183:C192=3, A183:A192))"""Sum: "&_xlfn.SUMIF(C183:C192, 3, A183:A192)"""Avg: "&_xlfn.AVERAGEIF(C183:C192, 3, A183:A192)""283223333"Count: "&_xlfn.COUNTIF(C204:C205, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C204:C205=3, A204:A205))"""Max: "&_xlfn.MAX(_xlfn.IF(C204:C205=3, A204:A205))"""Sum: "&_xlfn.SUMIF(C204:C205, 3, A204:A205)"""Avg: "&_xlfn.AVERAGEIF(C204:C205, 3, A204:A205)"""Count: "&_xlfn.COUNTIF(C203:C205, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C203:C205=3, A203:A205))"""Max: "&_xlfn.MAX(_xlfn.IF(C203:C205=3, A203:A205))"""Sum: "&_xlfn.SUMIF(C203:C205, 3, A203:A205)"""Avg: "&_xlfn.AVERAGEIF(C203:C205, 3, A203:A205)""29318363"Count: "&_xlfn.COUNTIF(C217:C218, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C217:C218=3, A217:A218))"""Max: "&_xlfn.MAX(_xlfn.IF(C217:C218=3, A217:A218))"""Sum: "&_xlfn.SUMIF(C217:C218, 3, A217:A218)"""Avg: "&_xlfn.AVERAGEIF(C217:C218, 3, A217:A218)"""Count: "&_xlfn.COUNTIF(C216:C218, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C216:C218=3, A216:A218))"""Max: "&_xlfn.MAX(_xlfn.IF(C216:C218=3, A216:A218))"""Sum: "&_xlfn.SUMIF(C216:C218, 3, A216:A218)"""Avg: "&_xlfn.AVERAGEIF(C216:C218, 3, A216:A218)"""Count: "&_xlfn.COUNTIF(C2:C218, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C2:C218=3, A2:A218))"""Max: "&_xlfn.MAX(_xlfn.IF(C2:C218=3, A2:A218))"""Sum: "&_xlfn.SUMIF(C2:C218, 3, A2:A218)"""Avg: "&_xlfn.AVERAGEIF(C2:C218, 3, A2:A218)""30331393123"Count: "&_xlfn.COUNTIF(C236:C237, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C236:C237=3, A236:A237))"""Max: "&_xlfn.MAX(_xlfn.IF(C236:C237=3, A236:A237))"""Sum: "&_xlfn.SUMIF(C236:C237, 3, A236:A237)"""Avg: "&_xlfn.AVERAGEIF(C236:C237, 3, A236:A237)"""Count: "&_xlfn.COUNTIF(C235:C237, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C235:C237=3, A235:A237))"""Max: "&_xlfn.MAX(_xlfn.IF(C235:C237=3, A235:A237))"""Sum: "&_xlfn.SUMIF(C235:C237, 3, A235:A237)"""Avg: "&_xlfn.AVERAGEIF(C235:C237, 3, A235:A237)""32333313"Count: "&_xlfn.COUNTIF(C249:C250, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C249:C250=3, A249:A250))"""Max: "&_xlfn.MAX(_xlfn.IF(C249:C250=3, A249:A250))"""Sum: "&_xlfn.SUMIF(C249:C250, 3, A249:A250)"""Avg: "&_xlfn.AVERAGEIF(C249:C250, 3, A249:A250)"""Count: "&_xlfn.COUNTIF(C248:C250, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C248:C250=3, A248:A250))"""Max: "&_xlfn.MAX(_xlfn.IF(C248:C250=3, A248:A250))"""Sum: "&_xlfn.SUMIF(C248:C250, 3, A248:A250)"""Avg: "&_xlfn.AVERAGEIF(C248:C250, 3, A248:A250)""343223243"Count: "&_xlfn.COUNTIF(C262:C263, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C262:C263=3, A262:A263))"""Max: "&_xlfn.MAX(_xlfn.IF(C262:C263=3, A262:A263))"""Sum: "&_xlfn.SUMIF(C262:C263, 3, A262:A263)"""Avg: "&_xlfn.AVERAGEIF(C262:C263, 3, A262:A263)"""Count: "&_xlfn.COUNTIF(C261:C263, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C261:C263=3, A261:A263))"""Max: "&_xlfn.MAX(_xlfn.IF(C261:C263=3, A261:A263))"""Sum: "&_xlfn.SUMIF(C261:C263, 3, A261:A263)"""Avg: "&_xlfn.AVERAGEIF(C261:C263, 3, A261:A263)""243223 - 263"Count: "&_xlfn.COUNTIF(C275:C276, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C275:C276=3, A275:A276))"""Max: "&_xlfn.MAX(_xlfn.IF(C275:C276=3, A275:A276))"""Sum: "&_xlfn.SUMIF(C275:C276, 3, A275:A276)"""Avg: "&_xlfn.AVERAGEIF(C275:C276, 3, A275:A276)"""Count: "&_xlfn.COUNTIF(C274:C276, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C274:C276=3, A274:A276))"""Max: "&_xlfn.MAX(_xlfn.IF(C274:C276=3, A274:A276))"""Sum: "&_xlfn.SUMIF(C274:C276, 3, A274:A276)"""Avg: "&_xlfn.AVERAGEIF(C274:C276, 3, A274:A276)""35373183"Count: "&_xlfn.COUNTIF(C288:C289, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C288:C289=3, A288:A289))"""Max: "&_xlfn.MAX(_xlfn.IF(C288:C289=3, A288:A289))"""Sum: "&_xlfn.SUMIF(C288:C289, 3, A288:A289)"""Avg: "&_xlfn.AVERAGEIF(C288:C289, 3, A288:A289)"""Count: "&_xlfn.COUNTIF(C287:C289, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C287:C289=3, A287:A289))"""Max: "&_xlfn.MAX(_xlfn.IF(C287:C289=3, A287:A289))"""Sum: "&_xlfn.SUMIF(C287:C289, 3, A287:A289)"""Avg: "&_xlfn.AVERAGEIF(C287:C289, 3, A287:A289)"""Count: "&_xlfn.COUNTIF(C234:C289, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C234:C289=3, A234:A289))"""Max: "&_xlfn.MAX(_xlfn.IF(C234:C289=3, A234:A289))"""Sum: "&_xlfn.SUMIF(C234:C289, 3, A234:A289)"""Avg: "&_xlfn.AVERAGEIF(C234:C289, 3, A234:A289)"""Count: "&_xlfn.COUNTIF(C2:C289, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C2:C289=3, A2:A289))"""Max: "&_xlfn.MAX(_xlfn.IF(C2:C289=3, A2:A289))"""Sum: "&_xlfn.SUMIF(C2:C289, 3, A2:A289)"""Avg: "&_xlfn.AVERAGEIF(C2:C289, 3, A2:A289)""` + 263"Count: "&_xlfn.COUNTIF(C275:C276, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C275:C276=3, A275:A276))"""Max: "&_xlfn.MAX(_xlfn.IF(C275:C276=3, A275:A276))"""Sum: "&_xlfn.SUMIF(C275:C276, 3, A275:A276)"""Avg: "&_xlfn.AVERAGEIF(C275:C276, 3, A275:A276)"""Count: "&_xlfn.COUNTIF(C274:C276, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C274:C276=3, A274:A276))"""Max: "&_xlfn.MAX(_xlfn.IF(C274:C276=3, A274:A276))"""Sum: "&_xlfn.SUMIF(C274:C276, 3, A274:A276)"""Avg: "&_xlfn.AVERAGEIF(C274:C276, 3, A274:A276)""35373183"Count: "&_xlfn.COUNTIF(C288:C289, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C288:C289=3, A288:A289))"""Max: "&_xlfn.MAX(_xlfn.IF(C288:C289=3, A288:A289))"""Sum: "&_xlfn.SUMIF(C288:C289, 3, A288:A289)"""Avg: "&_xlfn.AVERAGEIF(C288:C289, 3, A288:A289)"""Count: "&_xlfn.COUNTIF(C287:C289, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C287:C289=3, A287:A289))"""Max: "&_xlfn.MAX(_xlfn.IF(C287:C289=3, A287:A289))"""Sum: "&_xlfn.SUMIF(C287:C289, 3, A287:A289)"""Avg: "&_xlfn.AVERAGEIF(C287:C289, 3, A287:A289)"""Count: "&_xlfn.COUNTIF(C234:C289, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C234:C289=3, A234:A289))"""Max: "&_xlfn.MAX(_xlfn.IF(C234:C289=3, A234:A289))"""Sum: "&_xlfn.SUMIF(C234:C289, 3, A234:A289)"""Avg: "&_xlfn.AVERAGEIF(C234:C289, 3, A234:A289)"""Count: "&_xlfn.COUNTIF(C2:C289, 3)"""Min: "&_xlfn.MIN(_xlfn.IF(C2:C289=3, A2:A289))"""Max: "&_xlfn.MAX(_xlfn.IF(C2:C289=3, A2:A289))"""Sum: "&_xlfn.SUMIF(C2:C289, 3, A2:A289)"""Avg: "&_xlfn.AVERAGEIF(C2:C289, 3, A2:A289)""`; - return this.createData(); + return this.createData(); } public get exportGridWithSummariesFrLocale() { @@ -1860,7 +1856,7 @@ export class FileContentData { - 012345617183982012-02-12T02:00:000291917102003-03-17T02:00:000311101382006-03-17T02:00:000412225382016-03-17T02:00:00051321.350102011-11-11T02:00:00061425082017-12-17T02:00:0007153015082016-07-17T03:00:00081640682018-01-17T02:00:0009179729102010-02-17T02:00:0001018313182008-05-17T03:00:0001119212282009-01-17T02:00:0001220388682015-11-17T02:00:000132162482015-03-17T02:00:000142223.253582017-06-17T03:00:000152315.53982014-03-17T02:00:000162417.452982018-03-28T03:00:0001725390102015-08-17T03:00:000182662.54282005-09-27T03:00:00019279.22582001-03-17T02:00:00020284.54082005-03-17T02:00:000"""Count: "&_xlfn.COUNTIF(H2:H21, 0)"Count: "&_xlfn.COUNTIF(H2:H21, 0)"""Count: "&_xlfn.COUNTIF(H2:H21, 0)"Count: "&_xlfn.COUNTIF(H2:H21, 0)"""""""Min: "&_xlfn.TEXT(_xlfn.MIN(_xlfn.IF(H2:H21=0, C2:C21)), "€#,##0.00")"""""Earliest: "&_xlfn.TEXT(_xlfn.MIN(_xlfn.IF(H2:H21=0, F2:F21)), "m/d/yyyy")"""""""Max: "&_xlfn.TEXT(_xlfn.MAX(_xlfn.IF(H2:H21=0, C2:C21)), "€#,##0.00")"""""Latest: "&_xlfn.TEXT(_xlfn.MAX(_xlfn.IF(H2:H21=0, F2:F21)), "m/d/yyyy")"""""""Sum: "&_xlfn.TEXT(_xlfn.SUMIF(H2:H21, 0, C2:C21), "€#,##0.00")"""""""""""""Avg: "&_xlfn.TEXT(_xlfn.AVERAGEIF(H2:H21, 0, C2:C21), "€#,##0.00")""""""""` + 012345617183982012-02-12T02:00:000291917102003-03-17T02:00:000311101382006-03-17T02:00:000412225382016-03-17T02:00:00051321.350102011-11-11T02:00:00061425082017-12-17T02:00:0007153015082016-07-17T03:00:00081640682018-01-17T02:00:0009179729102010-02-17T02:00:0001018313182008-05-17T03:00:0001119212282009-01-17T02:00:0001220388682015-11-17T02:00:000132162482015-03-17T02:00:000142223.253582017-06-17T03:00:000152315.53982014-03-17T02:00:000162417.452982018-03-28T03:00:0001725390102015-08-17T03:00:000182662.54282005-09-27T03:00:00019279.22582001-03-17T02:00:00020284.54082005-03-17T02:00:000"""Count: "&_xlfn.COUNTIF(H2:H21, 0)"Count: "&_xlfn.COUNTIF(H2:H21, 0)"""Count: "&_xlfn.COUNTIF(H2:H21, 0)"Count: "&_xlfn.COUNTIF(H2:H21, 0)"""""""Min: "&_xlfn.TEXT(_xlfn.MIN(_xlfn.IF(H2:H21=0, C2:C21)), "€#,##0.00")"""""Earliest: "&_xlfn.TEXT(_xlfn.MIN(_xlfn.IF(H2:H21=0, F2:F21)), "m/d/yyyy")"""""""Max: "&_xlfn.TEXT(_xlfn.MAX(_xlfn.IF(H2:H21=0, C2:C21)), "€#,##0.00")"""""Latest: "&_xlfn.TEXT(_xlfn.MAX(_xlfn.IF(H2:H21=0, F2:F21)), "m/d/yyyy")"""""""Sum: "&_xlfn.TEXT(_xlfn.SUMIF(H2:H21, 0, C2:C21), "€#,##0.00")"""""""""""""Avg: "&_xlfn.TEXT(_xlfn.AVERAGEIF(H2:H21, 0, C2:C21), "€#,##0.00")""""""""`; return this.createData(); } @@ -1878,7 +1874,7 @@ export class FileContentData { - 012345617183982012-02-12T02:00:000291917102003-03-17T02:00:000311101382006-03-17T02:00:000412225382016-03-17T02:00:00051321.350102011-11-11T02:00:00061425082017-12-17T02:00:0007153015082016-07-17T03:00:00081640682018-01-17T02:00:0009179729102010-02-17T02:00:0001018313182008-05-17T03:00:0001119212282009-01-17T02:00:0001220388682015-11-17T02:00:000132162482015-03-17T02:00:000142223.253582017-06-17T03:00:000152315.53982014-03-17T02:00:000162417.452982018-03-28T03:00:0001725390102015-08-17T03:00:000182662.54282005-09-27T03:00:00019279.22582001-03-17T02:00:00020284.54082005-03-17T02:00:000"""Count: "&_xlfn.COUNTIF(H2:H21, 0)"Count: "&_xlfn.COUNTIF(H2:H21, 0)"""Count: "&_xlfn.COUNTIF(H2:H21, 0)"Count: "&_xlfn.COUNTIF(H2:H21, 0)"""""""Min: "&_xlfn.TEXT(_xlfn.MIN(_xlfn.IF(H2:H21=0, C2:C21)), "¥#,##0.00")"""""Earliest: "&_xlfn.TEXT(_xlfn.MIN(_xlfn.IF(H2:H21=0, F2:F21)), "m/d/yyyy")"""""""Max: "&_xlfn.TEXT(_xlfn.MAX(_xlfn.IF(H2:H21=0, C2:C21)), "¥#,##0.00")"""""Latest: "&_xlfn.TEXT(_xlfn.MAX(_xlfn.IF(H2:H21=0, F2:F21)), "m/d/yyyy")"""""""Sum: "&_xlfn.TEXT(_xlfn.SUMIF(H2:H21, 0, C2:C21), "¥#,##0.00")"""""""""""""Avg: "&_xlfn.TEXT(_xlfn.AVERAGEIF(H2:H21, 0, C2:C21), "¥#,##0.00")""""""""` + 012345617183982012-02-12T02:00:000291917102003-03-17T02:00:000311101382006-03-17T02:00:000412225382016-03-17T02:00:00051321.350102011-11-11T02:00:00061425082017-12-17T02:00:0007153015082016-07-17T03:00:00081640682018-01-17T02:00:0009179729102010-02-17T02:00:0001018313182008-05-17T03:00:0001119212282009-01-17T02:00:0001220388682015-11-17T02:00:000132162482015-03-17T02:00:000142223.253582017-06-17T03:00:000152315.53982014-03-17T02:00:000162417.452982018-03-28T03:00:0001725390102015-08-17T03:00:000182662.54282005-09-27T03:00:00019279.22582001-03-17T02:00:00020284.54082005-03-17T02:00:000"""Count: "&_xlfn.COUNTIF(H2:H21, 0)"Count: "&_xlfn.COUNTIF(H2:H21, 0)"""Count: "&_xlfn.COUNTIF(H2:H21, 0)"Count: "&_xlfn.COUNTIF(H2:H21, 0)"""""""Min: "&_xlfn.TEXT(_xlfn.MIN(_xlfn.IF(H2:H21=0, C2:C21)), "¥#,##0.00")"""""Earliest: "&_xlfn.TEXT(_xlfn.MIN(_xlfn.IF(H2:H21=0, F2:F21)), "m/d/yyyy")"""""""Max: "&_xlfn.TEXT(_xlfn.MAX(_xlfn.IF(H2:H21=0, C2:C21)), "¥#,##0.00")"""""Latest: "&_xlfn.TEXT(_xlfn.MAX(_xlfn.IF(H2:H21=0, F2:F21)), "m/d/yyyy")"""""""Sum: "&_xlfn.TEXT(_xlfn.SUMIF(H2:H21, 0, C2:C21), "¥#,##0.00")"""""""""""""Avg: "&_xlfn.TEXT(_xlfn.AVERAGEIF(H2:H21, 0, C2:C21), "¥#,##0.00")""""""""`; return this.createData(); } @@ -1896,7 +1892,7 @@ export class FileContentData { - 0123118390219170310130422530521.3500625007301500840609972901031310112122012388601362401423.253501515.53901617.452901739001862.5420199.2250204.5400456""789""` + 0123118390219170310130422530521.3500625007301500840609972901031310112122012388601362401423.253501515.53901617.452901739001862.5420199.2250204.5400456""789""`; return this.createData(); } @@ -1914,7 +1910,7 @@ export class FileContentData { - 0123118390219170310130422530521.3500625007301500840609972901031310112122012388601362401423.253501515.53901617.452901739001862.5420199.2250204.5400000""000""` + 0123118390219170310130422530521.3500625007301500840609972901031310112122012388601362401423.253501515.53901617.452901739001862.5420199.2250204.5400000""000""`; return this.createData(); } @@ -1932,7 +1928,7 @@ export class FileContentData { - 0123118390219170310130422530521.3500625007301500840609972901031310112122012388601362401423.253501515.53901617.452901739001862.5420199.2250204.5400000""232323""` + 0123118390219170310130422530521.3500625007301500840609972901031310112122012388601362401423.253501515.53901617.452901739001862.5420199.2250204.5400000""232323""`; return this.createData(); } @@ -1950,7 +1946,7 @@ export class FileContentData { - 0123118390219170310130422530521.3500625007301500840609972901031310112122012388601362401423.253501515.53901617.452901739001862.5420199.2250204.5400444""444""` + 0123118390219170310130422530521.3500625007301500840609972901031310112122012388601362401423.253501515.53901617.452901739001862.5420199.2250204.5400444""444""`; return this.createData(); } @@ -1968,7 +1964,7 @@ export class FileContentData { - 0123118390219170310130422530521.3500625007301500840609972901031310112122012388601362401423.253501515.53901617.452901739001862.5420199.2250204.54002015-12-08T00:00:002015-12-08T00:00:002015-12-08T00:00:00""2020-05-12T00:00:002020-05-12T00:00:002020-05-12T00:00:00""` + 0123118390219170310130422530521.3500625007301500840609972901031310112122012388601362401423.253501515.53901617.452901739001862.5420199.2250204.54002015-12-08T00:00:002015-12-08T00:00:002015-12-08T00:00:00""2020-05-12T00:00:002020-05-12T00:00:002020-05-12T00:00:00""`; return this.createData(); } @@ -1989,5 +1985,4 @@ export class FileContentData { return this.createData(); } - } diff --git a/projects/igniteui-angular/grids/core/src/services/excel/zip-helper.spec.ts b/projects/igniteui-angular/grids/core/src/services/excel/zip-helper.spec.ts index 70a305206ca..3a0e5b3c60a 100644 --- a/projects/igniteui-angular/grids/core/src/services/excel/zip-helper.spec.ts +++ b/projects/igniteui-angular/grids/core/src/services/excel/zip-helper.spec.ts @@ -24,7 +24,7 @@ export class ZipFiles { 'xl/sharedStrings.xml' ]; - public static dataFilesAndFoldersNames = [ + public static dataFilesAndFoldersNames = [ 'xl/worksheets/_rels/', 'xl/worksheets/_rels/sheet1.xml.rels', 'xl/worksheets/sheet1.xml', @@ -33,7 +33,7 @@ export class ZipFiles { 'xl/sharedStrings.xml' ]; - public static hGridDataFilesAndFoldersNames = [ + public static hGridDataFilesAndFoldersNames = [ 'xl/worksheets/sheet1.xml', 'xl/sharedStrings.xml' ]; @@ -70,7 +70,7 @@ export class ZipFiles { public static dataFiles = [ { name: 'xl/worksheets/_rels/sheet1.xml.rels', type: ExcelFileTypes.WorksheetRelsFile }, - { name: 'xl/worksheets/sheet1.xml', type: ExcelFileTypes.WorksheetFile }, + { name: 'xl/worksheets/sheet1.xml', type: ExcelFileTypes.WorksheetFile }, { name: 'xl/tables/table1.xml', type: ExcelFileTypes.TablesFile }, { name: 'xl/sharedStrings.xml', type: ExcelFileTypes.SharedStringsFile } ]; @@ -120,7 +120,7 @@ export class ZipFiles { public static getTablesXML(tableData: string) { return `\r\n + `${tableData}
`; } @@ -130,12 +130,12 @@ export class ZipFiles { public static getSharedStringsXML(stringsData: string) { return ` -`; +`; } public static getContentTypesXML(hasData = true) { const typesData = (hasData) ? `` : ``; + `ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>` : ``; return ` @@ -157,21 +157,21 @@ export class ZipFiles { return ` ${ sheetData }` + - `${tablePart}`; + `xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" ` + + `xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" ` + + `xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">${sheetData}` + + `${tablePart}`; } else { const dimensionsPart = isHGrid ? '' : ''; return ` ${dimensionsPart}` + - ``; + `xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" ` + + `xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x14ac" ` + + `xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac">${dimensionsPart}` + + ``; } } @@ -181,50 +181,50 @@ export class ZipFiles { case ExcelFileTypes.RootRelsFile: resultXml = { name: ZipFiles.templatesNames[1], - content : ` + content: ` ` + -`` + `Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>` + + `` }; break; case ExcelFileTypes.AppFile: resultXml = { name: ZipFiles.templatesNames[3], - content : ` + content: ` Microsoft Excel0` + -`falseWorksheets` + -`1Sheet1false` + -`falsefalse16.0300` + `schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">Microsoft Excel0` + + `falseWorksheets` + + `1Sheet1false` + + `falsefalse16.0300` }; break; case ExcelFileTypes.CoreFile: resultXml = { name: ZipFiles.templatesNames[4], - content : ` + content: ` ` + -`2015-06-05T18:17:20Z` + -`2015-06-05T18:17:26Z` + `xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" ` + + `xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">` + + `2015-06-05T18:17:20Z` + + `2015-06-05T18:17:26Z` }; break; case ExcelFileTypes.WorkbookRelsFile: const typesData = (hasValues) ? - `` : ''; + `` : ''; resultXml = { name: ZipFiles.templatesNames[7], - content : ` + content: ` ${typesData}` + -`` + `Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>${typesData}` + + `` }; break; case ExcelFileTypes.ThemeFile: @@ -232,59 +232,59 @@ export class ZipFiles { const actualTheme = ``; resultXml = { name: ZipFiles.templatesNames[9], - content : ` + content: ` ${actualTheme}` }; break; case ExcelFileTypes.StyleFile: resultXml = { name: ZipFiles.templatesNames[12], - content : this.getStylesheetXML() + content: this.getStylesheetXML() }; break; case ExcelFileTypes.WorkbookFile: resultXml = { name: ZipFiles.templatesNames[13], - content : ` + content: ` ` + `officeDocument/2006/relationships" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x15" ` + + `xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main">` }; break; case ExcelFileTypes.WorksheetRelsFile: resultXml = { name: ZipFiles.dataFilesAndFoldersNames[1], - content : ` + content: ` ` + `Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/table" Target="../tables/table1.xml"/>` }; break; case ExcelFileTypes.WorksheetFile: resultXml = { name: ZipFiles.templatesNames[11], - content : ZipFiles.getSheetDataFile(currentData, hasValues, isHGrid) + content: ZipFiles.getSheetDataFile(currentData, hasValues, isHGrid) }; break; case ExcelFileTypes.ContentTypesFile: resultXml = { name: ZipFiles.templatesNames[14], - content : this.getContentTypesXML(hasValues) + content: this.getContentTypesXML(hasValues) }; break; case ExcelFileTypes.SharedStringsFile: resultXml = { name: ZipFiles.dataFilesAndFoldersNames[4], - content : ZipFiles.getSharedStringsXML(currentData) + content: ZipFiles.getSharedStringsXML(currentData) }; break; case ExcelFileTypes.TablesFile: resultXml = { name: ZipFiles.dataFilesAndFoldersNames[3], - content : ZipFiles.getTablesXML(currentData) + content: ZipFiles.getTablesXML(currentData) }; break; default: @@ -293,6 +293,4 @@ export class ZipFiles { return resultXml; } - - } diff --git a/projects/igniteui-angular/grids/core/src/services/excel/zip-verification-wrapper.spec.ts b/projects/igniteui-angular/grids/core/src/services/excel/zip-verification-wrapper.spec.ts index f80e209444c..de52c2abc0b 100644 --- a/projects/igniteui-angular/grids/core/src/services/excel/zip-verification-wrapper.spec.ts +++ b/projects/igniteui-angular/grids/core/src/services/excel/zip-verification-wrapper.spec.ts @@ -1,6 +1,7 @@ import { strFromU8 } from 'fflate'; import { ExcelFileTypes } from './excel-enums'; import { ZipFiles } from './zip-helper.spec'; +import { expect } from 'vitest'; export class ZipWrapper { private _zip: Object; @@ -111,14 +112,12 @@ export class ZipWrapper { } private async readTemplateFiles() { - const actualTemplates = (this.hasValues) ? this.templateFilesOnly.filter((f) => - f !== ZipFiles.templatesNames[11]) : this.templateFilesOnly; + const actualTemplates = (this.hasValues) ? this.templateFilesOnly.filter((f) => f !== ZipFiles.templatesNames[11]) : this.templateFilesOnly; await this.readFiles(actualTemplates); } public get templateFilesContent(): IFileContent[] { - const actualTemplates = (this.hasValues) ? this.templateFilesOnly.filter((f) => - f !== ZipFiles.templatesNames[11]) : this.templateFilesOnly; + const actualTemplates = (this.hasValues) ? this.templateFilesOnly.filter((f) => f !== ZipFiles.templatesNames[11]) : this.templateFilesOnly; return this._filesContent.filter((c) => actualTemplates.indexOf(c.fileName) > -1); } diff --git a/projects/igniteui-angular/grids/core/src/services/exporter-common/test-methods.spec.ts b/projects/igniteui-angular/grids/core/src/services/exporter-common/test-methods.spec.ts index 9ec3323543d..ec2454f8231 100644 --- a/projects/igniteui-angular/grids/core/src/services/exporter-common/test-methods.spec.ts +++ b/projects/igniteui-angular/grids/core/src/services/exporter-common/test-methods.spec.ts @@ -4,6 +4,7 @@ import { GridIDNameJobTitleComponent } from '../../../../../test-utils/grid-samp import { wait } from '../../../../../test-utils/ui-interactions.spec'; import { IgxGridComponent } from 'igniteui-angular/grids/grid'; import { IgxStringFilteringOperand } from 'igniteui-angular/core'; +import { expect } from 'vitest'; export class TestMethods { @@ -13,7 +14,7 @@ export class TestMethods { await wait(16); myGrid = fix.componentInstance.grid; - expect(myGrid.rowList.length).toEqual(10, 'Invalid number of rows initialized!'); + expect(myGrid.rowList.length, 'Invalid number of rows initialized!').toEqual(10); await action(myGrid); } @@ -26,7 +27,7 @@ export class TestMethods { const myGrid = fix.componentInstance.grid; filterParams = (filterParams.length === 0) ? - ['JobTitle', 'Senior', IgxStringFilteringOperand.instance().condition('contains'), true] : filterParams; + ['JobTitle', 'Senior', IgxStringFilteringOperand.instance().condition('contains'), true] : filterParams; myGrid.filter(filterParams[0], filterParams[1], filterParams[2], filterParams[3]); fix.detectChanges(); @@ -50,5 +51,4 @@ export class TestMethods { return { fixture: fix, grid: myGrid }; } - } diff --git a/projects/igniteui-angular/grids/core/src/services/pdf/pdf-exporter-grid.spec.ts b/projects/igniteui-angular/grids/core/src/services/pdf/pdf-exporter-grid.spec.ts index 50488f19ee5..5904014e6d2 100644 --- a/projects/igniteui-angular/grids/core/src/services/pdf/pdf-exporter-grid.spec.ts +++ b/projects/igniteui-angular/grids/core/src/services/pdf/pdf-exporter-grid.spec.ts @@ -1,3 +1,4 @@ +import type { Mock } from "vitest"; import { TestBed, waitForAsync } from '@angular/core/testing'; import { ExportUtilities } from '../exporter-common/export-utilities'; import { IgxPdfExporterService } from './pdf-exporter'; @@ -14,6 +15,7 @@ import { IgxPivotGridMultipleRowComponent, IgxPivotGridTestComplexHierarchyCompo import { IgxPivotGridComponent } from 'igniteui-angular/grids/pivot-grid'; import { PivotRowLayoutType } from 'igniteui-angular/grids/core'; import { UIInteractions, wait } from 'igniteui-angular/test-utils/ui-interactions.spec'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('PDF Grid Exporter', () => { let exporter: IgxPdfExporterService; @@ -35,10 +37,10 @@ describe('PDF Grid Exporter', () => { options = new IgxPdfExporterOptions('PdfGridExport'); // Spy the saveBlobToFile method so the files are not really created - spyOn(ExportUtilities as any, 'saveBlobToFile'); + vi.spyOn(ExportUtilities as any, 'saveBlobToFile'); }); - it('should export grid as displayed.', (done) => { + it('should export grid as displayed.', async () => { const fix = TestBed.createComponent(GridIDNameJobTitleComponent); fix.detectChanges(); @@ -46,13 +48,13 @@ describe('PDF Grid Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(grid, options); }); - it('should export grid with custom page orientation', (done) => { + it('should export grid with custom page orientation', async () => { const fix = TestBed.createComponent(GridIDNameJobTitleComponent); fix.detectChanges(); @@ -61,13 +63,13 @@ describe('PDF Grid Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(grid, options); }); - it('should honor ignoreColumnsVisibility option', (done) => { + it('should honor ignoreColumnsVisibility option', async () => { const fix = TestBed.createComponent(GridIDNameJobTitleComponent); fix.detectChanges(); @@ -79,13 +81,13 @@ describe('PDF Grid Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(grid, options); }); - it('should handle empty grid', (done) => { + it('should handle empty grid', async () => { const fix = TestBed.createComponent(GridIDNameJobTitleComponent); fix.detectChanges(); @@ -95,13 +97,13 @@ describe('PDF Grid Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(grid, options); }); - it('should export grid with landscape orientation', (done) => { + it('should export grid with landscape orientation', async () => { const fix = TestBed.createComponent(GridIDNameJobTitleComponent); fix.detectChanges(); @@ -110,13 +112,13 @@ describe('PDF Grid Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(grid, options); }); - it('should export with table borders disabled', (done) => { + it('should export with table borders disabled', async () => { const fix = TestBed.createComponent(GridIDNameJobTitleComponent); fix.detectChanges(); @@ -125,13 +127,13 @@ describe('PDF Grid Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(grid, options); }); - it('should export with custom font size', (done) => { + it('should export with custom font size', async () => { const fix = TestBed.createComponent(GridIDNameJobTitleComponent); fix.detectChanges(); @@ -140,13 +142,13 @@ describe('PDF Grid Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(grid, options); }); - it('should export with different page sizes', (done) => { + it('should export with different page sizes', async () => { const fix = TestBed.createComponent(GridIDNameJobTitleComponent); fix.detectChanges(); @@ -155,13 +157,13 @@ describe('PDF Grid Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(grid, options); }); - it('should honor ignoreColumnsOrder option', (done) => { + it('should honor ignoreColumnsOrder option', async () => { const fix = TestBed.createComponent(GridIDNameJobTitleComponent); fix.detectChanges(); @@ -170,13 +172,13 @@ describe('PDF Grid Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(grid, options); }); - it('should honor ignoreFiltering option', (done) => { + it('should honor ignoreFiltering option', async () => { const fix = TestBed.createComponent(GridIDNameJobTitleComponent); fix.detectChanges(); @@ -185,13 +187,13 @@ describe('PDF Grid Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(grid, options); }); - it('should honor ignoreSorting option', (done) => { + it('should honor ignoreSorting option', async () => { const fix = TestBed.createComponent(GridIDNameJobTitleComponent); fix.detectChanges(); @@ -200,7 +202,7 @@ describe('PDF Grid Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(grid, options); @@ -208,7 +210,7 @@ describe('PDF Grid Exporter', () => { - it('should handle grid with multiple columns', (done) => { + it('should handle grid with multiple columns', async () => { const fix = TestBed.createComponent(GridIDNameJobTitleComponent); fix.detectChanges(); @@ -216,13 +218,13 @@ describe('PDF Grid Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(grid, options); }); - it('should export with custom filename from options', (done) => { + it('should export with custom filename from options', async () => { const fix = TestBed.createComponent(GridIDNameJobTitleComponent); fix.detectChanges(); @@ -231,15 +233,15 @@ describe('PDF Grid Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - const callArgs = (ExportUtilities.saveBlobToFile as jasmine.Spy).calls.mostRecent().args; + const callArgs = vi.mocked((ExportUtilities.saveBlobToFile as Mock)).mock.lastCall; expect(callArgs[1]).toBe('MyCustomGrid.pdf'); - done(); + ; }); exporter.export(grid, customOptions); }); - it('should export grid with multi-column headers', (done) => { + it('should export grid with multi-column headers', async () => { TestBed.configureTestingModule({ imports: [ NoopAnimationsModule, @@ -254,13 +256,13 @@ describe('PDF Grid Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(grid, options); }); - it('should export grid with nested multi-column headers', (done) => { + it('should export grid with nested multi-column headers', async () => { TestBed.configureTestingModule({ imports: [ NoopAnimationsModule, @@ -275,13 +277,13 @@ describe('PDF Grid Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(grid, options); }); - it('should export grid with summaries', (done) => { + it('should export grid with summaries', async () => { TestBed.configureTestingModule({ imports: [ NoopAnimationsModule, @@ -296,13 +298,13 @@ describe('PDF Grid Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(grid, options); }); - it('should export hierarchical grid', (done) => { + it('should export hierarchical grid', async () => { TestBed.configureTestingModule({ imports: [ NoopAnimationsModule, @@ -322,13 +324,13 @@ describe('PDF Grid Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(grid, options); }); - it('should export the correct number of child data rows from a hierarchical grid', (done) => { + it('should export the correct number of child data rows from a hierarchical grid', async () => { const fix = TestBed.createComponent(IgxHierarchicalGridExportComponent); fix.detectChanges(); @@ -362,17 +364,17 @@ describe('PDF Grid Exporter', () => { const expectedRows = allGrids.reduce((acc, g) => acc + g.data.length, 0); // Spy PDF row drawing to count exported rows - const drawDataRowSpy = spyOn(exporter as any, 'drawDataRow').and.callThrough(); + const drawDataRowSpy = vi.spyOn(exporter as any, 'drawDataRow'); exporter.exportEnded.pipe(first()).subscribe(() => { - expect(drawDataRowSpy.calls.count()).toBe(expectedRows); - done(); + expect(vi.mocked(drawDataRowSpy).mock.calls.length).toBe(expectedRows); + ; }); exporter.export(hGrid, options); }); - it('should export tree grid with hierarchical data', (done) => { + it('should export tree grid with hierarchical data', async () => { TestBed.configureTestingModule({ imports: [ NoopAnimationsModule, @@ -387,13 +389,13 @@ describe('PDF Grid Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(grid, options); }); - it('should export tree grid with flat self-referencing data', (done) => { + it('should export tree grid with flat self-referencing data', async () => { TestBed.configureTestingModule({ imports: [ NoopAnimationsModule, @@ -408,13 +410,13 @@ describe('PDF Grid Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(grid, options); }); - it('should truncate long header text with ellipsis in multi-column headers', (done) => { + it('should truncate long header text with ellipsis in multi-column headers', async () => { TestBed.configureTestingModule({ imports: [ NoopAnimationsModule, @@ -431,7 +433,7 @@ describe('PDF Grid Exporter', () => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); // The PDF should be created successfully even with long header text expect(args.pdf).toBeDefined(); - done(); + ; }); // Use smaller page size to force truncation @@ -450,97 +452,97 @@ describe('PDF Grid Exporter', () => { pivotGrid = fix.componentInstance.pivotGrid; }); - it('should export basic pivot grid', (done) => { + it('should export basic pivot grid', async () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(pivotGrid, options); }); - it('should export pivot grid with row headers', (done) => { + it('should export pivot grid with row headers', async () => { pivotGrid.pivotUI.showRowHeaders = true; exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(pivotGrid, options); }); - it('should export pivot grid with horizontal row layout', (done) => { + it('should export pivot grid with horizontal row layout', async () => { pivotGrid.pivotUI.showRowHeaders = true; pivotGrid.pivotUI.rowLayout = PivotRowLayoutType.Horizontal; pivotGrid.pivotConfiguration.rows = [{ - memberName: 'ProductCategory', - memberFunction: (data) => data.ProductCategory, - enabled: true, - childLevel: { - memberName: 'Country', + memberName: 'ProductCategory', + memberFunction: (data) => data.ProductCategory, enabled: true, childLevel: { - memberName: 'Date', - enabled: true + memberName: 'Country', + enabled: true, + childLevel: { + memberName: 'Date', + enabled: true + } } - } - }]; + }]; fix.detectChanges(); exporter.exportEnded.pipe(first()).subscribe(() => { - expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); + ; }); exporter.export(pivotGrid, options); }); - it('should export pivot grid with custom page size', (done) => { + it('should export pivot grid with custom page size', async () => { options.pageSize = 'letter'; exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(pivotGrid, options); }); - it('should export pivot grid with landscape orientation', (done) => { + it('should export pivot grid with landscape orientation', async () => { options.pageOrientation = 'landscape'; exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(pivotGrid, options); }); - it('should export pivot grid without table borders', (done) => { + it('should export pivot grid without table borders', async () => { options.showTableBorders = false; exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(pivotGrid, options); }); - it('should export pivot grid with custom font size', (done) => { + it('should export pivot grid with custom font size', async () => { options.fontSize = 14; exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(pivotGrid, options); }); - it('should export hierarchical pivot grid', (done) => { + it('should export hierarchical pivot grid', async () => { fix = TestBed.createComponent(IgxPivotGridTestComplexHierarchyComponent); fix.detectChanges(); fix.whenStable().then(() => { @@ -548,7 +550,7 @@ describe('PDF Grid Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.export(pivotGrid, options); diff --git a/projects/igniteui-angular/grids/core/src/services/pdf/pdf-exporter.spec.ts b/projects/igniteui-angular/grids/core/src/services/pdf/pdf-exporter.spec.ts index 2dbde14d859..876e6b4cb20 100644 --- a/projects/igniteui-angular/grids/core/src/services/pdf/pdf-exporter.spec.ts +++ b/projects/igniteui-angular/grids/core/src/services/pdf/pdf-exporter.spec.ts @@ -1,9 +1,11 @@ +import type { Mock } from "vitest"; import { ExportUtilities } from '../exporter-common/export-utilities'; import { IgxPdfExporterService } from './pdf-exporter'; import { IgxPdfExporterOptions } from './pdf-exporter-options'; import { SampleTestData } from '../../../../../test-utils/sample-test-data.spec'; import { first } from 'rxjs/operators'; import { ExportRecordType, ExportHeaderType, DEFAULT_OWNER, IExportRecord, IColumnInfo, IColumnList, GRID_LEVEL_COL } from '../exporter-common/base-export-service'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('PDF Exporter', () => { let exporter: IgxPdfExporterService; @@ -17,23 +19,23 @@ describe('PDF Exporter', () => { (exporter as any)._ownersMap.clear(); // Spy the saveBlobToFile method so the files are not really created - spyOn(ExportUtilities, 'saveBlobToFile'); + vi.spyOn(ExportUtilities, 'saveBlobToFile'); }); it('should be created', () => { expect(exporter).toBeTruthy(); }); - it('should export empty data without errors', (done) => { + it('should export empty data without errors', async () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData([], options); }); - it('should export simple data successfully', (done) => { + it('should export simple data successfully', async () => { const simpleData = [ { Name: 'John', Age: 30 }, { Name: 'Jane', Age: 25 } @@ -41,66 +43,66 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(simpleData, options); }); - it('should export contacts data successfully', (done) => { + it('should export contacts data successfully', async () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(SampleTestData.contactsData(), options); }); - it('should export with custom page orientation', (done) => { + it('should export with custom page orientation', async () => { options.pageOrientation = 'landscape'; exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(SampleTestData.contactsData(), options); }); - it('should export with custom page size', (done) => { + it('should export with custom page size', async () => { options.pageSize = 'letter'; exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(SampleTestData.contactsData(), options); }); - it('should export without table borders', (done) => { + it('should export without table borders', async () => { options.showTableBorders = false; exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(SampleTestData.contactsData(), options); }); - it('should export with custom font size', (done) => { + it('should export with custom font size', async () => { options.fontSize = 12; exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(SampleTestData.contactsData(), options); }); - it('should handle null and undefined values', (done) => { + it('should handle null and undefined values', async () => { const dataWithNulls = [ { Name: 'John', Age: null }, { Name: undefined, Age: 25 } @@ -108,13 +110,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(dataWithNulls, options); }); - it('should handle date values', (done) => { + it('should handle date values', async () => { const dataWithDates = [ { Name: 'John', BirthDate: new Date('1990-01-01') }, { Name: 'Jane', BirthDate: new Date('1995-06-15') } @@ -122,31 +124,31 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(dataWithDates, options); }); - it('should export with portrait orientation', (done) => { + it('should export with portrait orientation', async () => { options.pageOrientation = 'portrait'; exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(SampleTestData.contactsData(), options); }); - it('should export with various page sizes', (done) => { + it('should export with various page sizes', async () => { const pageSizes = ['a3', 'a5', 'legal']; let completed = 0; const exportNext = (index: number) => { if (index >= pageSizes.length) { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(pageSizes.length); - done(); + ; return; } @@ -164,18 +166,18 @@ describe('PDF Exporter', () => { exportNext(0); }); - it('should export with different font sizes', (done) => { + it('should export with different font sizes', async () => { options.fontSize = 14; exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(SampleTestData.contactsData(), options); }); - it('should export large dataset requiring pagination', (done) => { + it('should export large dataset requiring pagination', async () => { const largeData = []; for (let i = 0; i < 100; i++) { largeData.push({ Name: `Person ${i}`, Age: 20 + (i % 50), City: `City ${i % 10}` }); @@ -183,13 +185,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(largeData, options); }); - it('should handle long text values with truncation', (done) => { + it('should handle long text values with truncation', async () => { const dataWithLongText = [ { Name: 'John', Description: 'This is a very long description that should be truncated with ellipsis in the PDF export to fit within the cell width' }, { Name: 'Jane', Description: 'Another extremely long text that needs to be handled properly in the PDF export without breaking the layout' } @@ -197,13 +199,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(dataWithLongText, options); }); - it('should export data with mixed data types', (done) => { + it('should export data with mixed data types', async () => { const mixedData = [ { String: 'Text', Number: 42, Boolean: true, Date: new Date('2023-01-01'), Null: null, Undefined: undefined }, { String: 'More text', Number: 3.14, Boolean: false, Date: new Date('2023-12-31'), Null: null, Undefined: undefined } @@ -211,26 +213,26 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(mixedData, options); }); - it('should export with custom filename', (done) => { + it('should export with custom filename', async () => { const customOptions = new IgxPdfExporterOptions('CustomFileName'); exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - const callArgs = (ExportUtilities.saveBlobToFile as jasmine.Spy).calls.mostRecent().args; + const callArgs = vi.mocked((ExportUtilities.saveBlobToFile as Mock)).mock.lastCall; expect(callArgs[1]).toBe('CustomFileName.pdf'); - done(); + ; }); exporter.exportData(SampleTestData.contactsData(), customOptions); }); - it('should handle empty rows in data', (done) => { + it('should handle empty rows in data', async () => { const dataWithEmptyRows = [ { Name: 'John', Age: 30 }, {}, @@ -239,24 +241,24 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(dataWithEmptyRows, options); }); - it('should emit exportEnded event with pdf object', (done) => { + it('should emit exportEnded event with pdf object', async () => { exporter.exportEnded.pipe(first()).subscribe((args) => { expect(args).toBeDefined(); expect(args.pdf).toBeDefined(); - done(); + ; }); exporter.exportData(SampleTestData.contactsData(), options); }); describe('Pivot Grid Export', () => { - it('should export pivot grid with single dimension', (done) => { + it('should export pivot grid with single dimension', async () => { const pivotData: IExportRecord[] = [ { data: { Product: 'Product A', 'City-London-Sum': 100, 'City-Paris-Sum': 200 }, @@ -335,13 +337,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should export multi-dimensional pivot grid with multiple row dimensions', (done) => { + it('should export multi-dimensional pivot grid with multiple row dimensions', async () => { const pivotData: IExportRecord[] = [ { data: { Product: 'Product A', Category: 'Category 1', 'City-London-Sum': 100, 'City-Paris-Sum': 200 }, @@ -450,13 +452,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should export pivot grid with row dimension headers and multi-level column headers', (done) => { + it('should export pivot grid with row dimension headers and multi-level column headers', async () => { const pivotData: IExportRecord[] = [ { data: { Product: 'Product A', 'City-London-Sum': 100, 'City-London-Avg': 50, 'City-Paris-Sum': 200 }, @@ -539,13 +541,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should export pivot grid with PivotMergedHeader columns', (done) => { + it('should export pivot grid with PivotMergedHeader columns', async () => { const pivotData: IExportRecord[] = [ { data: { Product: 'Product A', 'City-London-Sum': 100 }, @@ -595,13 +597,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should export pivot grid when dimensionKeys are inferred from record data', (done) => { + it('should export pivot grid when dimensionKeys are inferred from record data', async () => { const pivotData: IExportRecord[] = [ { data: { Product: 'Product A', Category: 'Category 1', 'City-London-Sum': 100 }, @@ -651,13 +653,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should export pivot grid with MultiRowHeader columns', (done) => { + it('should export pivot grid with MultiRowHeader columns', async () => { const pivotData: IExportRecord[] = [ { data: { Product: 'Product A', Category: 'Category 1', 'City-London-Sum': 100 }, @@ -738,13 +740,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should export pivot grid with row dimension columns by level', (done) => { + it('should export pivot grid with row dimension columns by level', async () => { const pivotData: IExportRecord[] = [ { data: { Product: 'Product A', Category: 'Category 1', 'City-London-Sum': 100 }, @@ -824,7 +826,7 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); @@ -832,7 +834,7 @@ describe('PDF Exporter', () => { }); describe('Hierarchical Grid Export', () => { - it('should export hierarchical grid with child records', (done) => { + it('should export hierarchical grid with child records', async () => { const childOwner = 'child1'; const childColumns: IColumnInfo[] = [ { @@ -923,13 +925,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(hierarchicalData, options); }); - it('should export hierarchical grid with multiple child levels', (done) => { + it('should export hierarchical grid with multiple child levels', async () => { const grandChildOwner = 'grandchild1'; const childOwner = 'child1'; @@ -1025,13 +1027,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(hierarchicalData, options); }); - it('should export hierarchical grid with multi-level headers in child grid', (done) => { + it('should export hierarchical grid with multi-level headers in child grid', async () => { const childOwner = 'child1'; const childColumns: IColumnInfo[] = [ @@ -1111,7 +1113,7 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(hierarchicalData, options); @@ -1119,7 +1121,7 @@ describe('PDF Exporter', () => { }); describe('Tree Grid Export', () => { - it('should export tree grid with hierarchical levels', (done) => { + it('should export tree grid with hierarchical levels', async () => { const treeData: IExportRecord[] = [ { data: { name: 'Root 1', value: 100 }, @@ -1175,7 +1177,7 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(treeData, options); @@ -1183,7 +1185,7 @@ describe('PDF Exporter', () => { }); describe('Summary Records Export', () => { - it('should export summary records with label and value', (done) => { + it('should export summary records with label and value', async () => { const summaryData: IExportRecord[] = [ { data: { name: 'Total', value: { label: 'Sum', value: 500 } }, @@ -1224,13 +1226,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(summaryData, options); }); - it('should export summary records with summaryResult property', (done) => { + it('should export summary records with summaryResult property', async () => { const summaryData: IExportRecord[] = [ { data: { name: 'Total', value: { summaryResult: 1000 } }, @@ -1271,7 +1273,7 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(summaryData, options); @@ -1279,7 +1281,7 @@ describe('PDF Exporter', () => { }); describe('Edge Cases and Special Scenarios', () => { - it('should skip hidden records', (done) => { + it('should skip hidden records', async () => { const dataWithHidden: IExportRecord[] = [ { data: { Name: 'Visible', Age: 30 }, @@ -1301,13 +1303,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(dataWithHidden, options); }); - it('should handle pagination when data exceeds page height', (done) => { + it('should handle pagination when data exceeds page height', async () => { const largeData: IExportRecord[] = []; for (let i = 0; i < 50; i++) { largeData.push({ @@ -1319,13 +1321,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(largeData, options); }); - it('should handle pivot grid with empty row dimension fields', (done) => { + it('should handle pivot grid with empty row dimension fields', async () => { const pivotData: IExportRecord[] = [ { data: { 'City-London-Sum': 100 }, @@ -1359,13 +1361,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should handle pivot grid when no columns are defined', (done) => { + it('should handle pivot grid when no columns are defined', async () => { const pivotData: IExportRecord[] = [ { data: { Product: 'Product A', Value: 100 }, @@ -1385,13 +1387,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should handle pivot grid with row dimension headers longer than fields', (done) => { + it('should handle pivot grid with row dimension headers longer than fields', async () => { const pivotData: IExportRecord[] = [ { data: { Product: 'Product A', 'City-London-Sum': 100 }, @@ -1441,13 +1443,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should handle pivot grid with date values in row dimensions', (done) => { + it('should handle pivot grid with date values in row dimensions', async () => { const pivotData: IExportRecord[] = [ { data: { Date: new Date('2023-01-01'), 'City-London-Sum': 100 }, @@ -1489,13 +1491,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should handle hierarchical grid with HeaderRecord type', (done) => { + it('should handle hierarchical grid with HeaderRecord type', async () => { const childOwner = 'child1'; const childColumns: IColumnInfo[] = [ { @@ -1562,13 +1564,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(hierarchicalData, options); }); - it('should handle hierarchical grid with empty child columns', (done) => { + it('should handle hierarchical grid with empty child columns', async () => { const childOwner = 'child1'; const childOwnerList: IColumnList = { columns: [], @@ -1617,13 +1619,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(hierarchicalData, options); }); - it('should handle pagination with hierarchical grid', (done) => { + it('should handle pagination with hierarchical grid', async () => { const childOwner = 'child1'; const childColumns: IColumnInfo[] = [ { @@ -1686,7 +1688,7 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(hierarchicalData, options); @@ -1694,7 +1696,7 @@ describe('PDF Exporter', () => { }); describe('Additional Edge Cases and Error Paths', () => { - it('should handle pivot grid with no defaultOwner', (done) => { + it('should handle pivot grid with no defaultOwner', async () => { const pivotData: IExportRecord[] = [ { data: { Product: 'Product A', 'City-London-Sum': 100 }, @@ -1709,13 +1711,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should handle pivot grid dimension inference from columnGroup', (done) => { + it('should handle pivot grid dimension inference from columnGroup', async () => { const pivotData: IExportRecord[] = [ { data: { Product: 'Product A', Category: 'Category 1', 'City-London-Sum': 100 }, @@ -1767,13 +1769,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should handle pivot grid with simple keys inference', (done) => { + it('should handle pivot grid with simple keys inference', async () => { const pivotData: IExportRecord[] = [ { data: { SimpleKey: 'Value1', 'Complex-Key-With-Separators': 100, 'Another_Complex_Key': 200 }, @@ -1807,13 +1809,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should handle pivot grid with row dimension headers longer than fields and trim them', (done) => { + it('should handle pivot grid with row dimension headers longer than fields and trim them', async () => { const pivotData: IExportRecord[] = [ { data: { Product: 'Product A', 'City-London-Sum': 100 }, @@ -1871,13 +1873,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should handle multi-level headers with empty headersForLevel', (done) => { + it('should handle multi-level headers with empty headersForLevel', async () => { const columns: IColumnInfo[] = [ { header: 'Name', @@ -1929,13 +1931,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(data, options); }); - it('should handle columns with skip: true', (done) => { + it('should handle columns with skip: true', async () => { const columns: IColumnInfo[] = [ { header: 'Name', @@ -1976,13 +1978,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(data, options); }); - it('should handle GRID_LEVEL_COL column', (done) => { + it('should handle GRID_LEVEL_COL column', async () => { const columns: IColumnInfo[] = [ { header: 'Name', @@ -2023,13 +2025,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(data, options); }); - it('should handle records with missing data property', (done) => { + it('should handle records with missing data property', async () => { const data: IExportRecord[] = [ { data: { Name: 'John', Age: 30 }, @@ -2045,13 +2047,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(data, options); }); - it('should handle pivot grid with fuzzy key matching', (done) => { + it('should handle pivot grid with fuzzy key matching', async () => { const pivotData: IExportRecord[] = [ { data: { 'ProductName': 'Product A', 'City-London-Sum': 100 }, @@ -2093,13 +2095,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should handle pivot grid with possible dimension keys by index fallback', (done) => { + it('should handle pivot grid with possible dimension keys by index fallback', async () => { const pivotData: IExportRecord[] = [ { data: { SimpleKey1: 'Value1', SimpleKey2: 'Value2', 'Complex-Key': 100 }, @@ -2141,13 +2143,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should handle summary records with only label', (done) => { + it('should handle summary records with only label', async () => { const summaryData: IExportRecord[] = [ { data: { name: 'Total', value: { label: 'Sum' } }, @@ -2188,13 +2190,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(summaryData, options); }); - it('should handle summary records with only value', (done) => { + it('should handle summary records with only value', async () => { const summaryData: IExportRecord[] = [ { data: { name: 'Total', value: { value: 500 } }, @@ -2235,13 +2237,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(summaryData, options); }); - it('should handle pivot grid with empty PivotRowHeader columns', (done) => { + it('should handle pivot grid with empty PivotRowHeader columns', async () => { const pivotData: IExportRecord[] = [ { data: { Product: 'Product A', 'City-London-Sum': 100 }, @@ -2283,13 +2285,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should handle hierarchical grid with owner not in map', (done) => { + it('should handle hierarchical grid with owner not in map', async () => { const childOwner = 'nonexistent-owner'; const parentColumns: IColumnInfo[] = [ { @@ -2330,13 +2332,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(hierarchicalData, options); }); - it('should handle tree grid with undefined level', (done) => { + it('should handle tree grid with undefined level', async () => { const treeData: IExportRecord[] = [ { data: { name: 'Root 1', value: 100 }, @@ -2377,13 +2379,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(treeData, options); }); - it('should handle pivot grid with columnGroupParent as non-string', (done) => { + it('should handle pivot grid with columnGroupParent as non-string', async () => { const pivotData: IExportRecord[] = [ { data: { Product: 'Product A', Category: 'Category 1', 'City-London-Sum': 100 }, @@ -2434,13 +2436,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should handle pivot grid with column header matching record values', (done) => { + it('should handle pivot grid with column header matching record values', async () => { const pivotData: IExportRecord[] = [ { data: { Product: 'Product A', 'City-London-Sum': 100 }, @@ -2482,13 +2484,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should handle pivot grid with record index-based column selection', (done) => { + it('should handle pivot grid with record index-based column selection', async () => { const pivotData: IExportRecord[] = [ { data: { Product: 'Product A', 'City-London-Sum': 100 }, @@ -2552,13 +2554,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should handle pivot grid with empty allColumns in drawDataRow', (done) => { + it('should handle pivot grid with empty allColumns in drawDataRow', async () => { const pivotData: IExportRecord[] = [ { data: { Product: 'Product A', 'City-London-Sum': 100 }, @@ -2592,13 +2594,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should handle very long header text truncation', (done) => { + it('should handle very long header text truncation', async () => { const longHeaderText = 'This is a very long header text that should be truncated because it exceeds the maximum width of the column header cell in the PDF export'; const columns: IColumnInfo[] = [ { @@ -2631,13 +2633,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(data, options); }); - it('should handle pivot grid with row dimension columns but no matching data', (done) => { + it('should handle pivot grid with row dimension columns but no matching data', async () => { const pivotData: IExportRecord[] = [ { data: { 'City-London-Sum': 100 }, // No dimension fields in data @@ -2679,13 +2681,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should handle column field as non-string gracefully', (done) => { + it('should handle column field as non-string gracefully', async () => { // This test verifies that non-string fields are handled without crashing // The base exporter may filter these out, so we test with valid data structure const columns: IColumnInfo[] = [ @@ -2728,13 +2730,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(data, options); }); - it('should handle empty rowDimensionHeaders fallback path', (done) => { + it('should handle empty rowDimensionHeaders fallback path', async () => { const pivotData: IExportRecord[] = [ { data: { Product: 'Product A', 'City-London-Sum': 100 }, @@ -2768,13 +2770,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should handle PivotMergedHeader with empty header text', (done) => { + it('should handle PivotMergedHeader with empty header text', async () => { const pivotData: IExportRecord[] = [ { data: { Product: 'Product A', 'City-London-Sum': 100 }, @@ -2816,13 +2818,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(pivotData, options); }); - it('should handle resolveLayoutStartIndex with no child columns', (done) => { + it('should handle resolveLayoutStartIndex with no child columns', async () => { const columns: IColumnInfo[] = [ { header: 'Parent', @@ -2856,13 +2858,13 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(data, options); }); - it('should handle data with zero total columns', (done) => { + it('should handle data with zero total columns', async () => { const data: IExportRecord[] = [ { data: {}, @@ -2882,7 +2884,7 @@ describe('PDF Exporter', () => { exporter.exportEnded.pipe(first()).subscribe(() => { expect(ExportUtilities.saveBlobToFile).toHaveBeenCalledTimes(1); - done(); + ; }); exporter.exportData(data, options); diff --git a/projects/igniteui-angular/grids/core/src/state.directive.spec.ts b/projects/igniteui-angular/grids/core/src/state.directive.spec.ts index a999f47eb9a..372b6c29ce3 100644 --- a/projects/igniteui-angular/grids/core/src/state.directive.spec.ts +++ b/projects/igniteui-angular/grids/core/src/state.directive.spec.ts @@ -18,6 +18,7 @@ import { IgxPaginatorComponent } from 'igniteui-angular/paginator'; import { IgxColumnComponent, IgxColumnGroupComponent, IgxColumnLayoutComponent, IgxGridDetailTemplateDirective, IgxGridMRLNavigationService } from './public_api'; import { IColumnState, IGridState } from './state-base.directive'; import { IgxGridComponent } from 'igniteui-angular/grids/grid'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxGridState - input properties #grid', () => { beforeEach(waitForAsync(() => { @@ -55,8 +56,8 @@ describe('IgxGridState - input properties #grid', () => { const state = fix.componentInstance.state; - expect(state).toBeDefined('IgxGridState directive is initialized'); - expect(state.options).toEqual(jasmine.objectContaining(defaultOptions)); + expect(state, 'IgxGridState directive is initialized').toBeDefined(); + expect(state.options).toEqual(expect.objectContaining(defaultOptions)); }); it('should initialize an IgxGridState with correct options input', () => { @@ -79,7 +80,7 @@ describe('IgxGridState - input properties #grid', () => { fix.detectChanges(); const state = fix.componentInstance.state; - expect(state.options).toEqual(jasmine.objectContaining(optionsInput)); + expect(state.options).toEqual(expect.objectContaining(optionsInput)); }); it('getState should return correct JSON string', () => { @@ -90,13 +91,13 @@ describe('IgxGridState - input properties #grid', () => { const state = fix.componentInstance.state; const gridState = state.getState(); - expect(gridState).toBe(initialGridState, 'JSON string representation of the initial grid state is not correct'); + expect(gridState, 'JSON string representation of the initial grid state is not correct').toBe(initialGridState); }); it('getState should return correct IGridState object when using default options', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); @@ -112,9 +113,9 @@ describe('IgxGridState - input properties #grid', () => { const groupingExpressions = [ { dir: SortingDirection.Asc, fieldName: 'ProductID', ignoreCase: false, - strategy: DefaultSortingStrategy.instance() }, + strategy: DefaultSortingStrategy.instance() }, { dir: SortingDirection.Asc, fieldName: 'OrderDate', ignoreCase: false, - strategy: DefaultSortingStrategy.instance() } + strategy: DefaultSortingStrategy.instance() } ]; grid.filteringExpressionsTree = gridFilteringExpressionsTree; @@ -159,12 +160,12 @@ describe('IgxGridState - input properties #grid', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; const filtering = grid.filteringExpressionsTree; let gridState = state.getState(true, 'filtering'); - expect(gridState).toBe('{"filtering":{"filteringOperands":[],"operator":0}}', 'JSON string'); + expect(gridState, 'JSON string').toBe('{"filtering":{"filteringOperands":[],"operator":0}}'); gridState = state.getState(false, ['filtering']) as IGridState; HelperFunctions.verifyFilteringExpressions(filtering, gridState); @@ -173,7 +174,7 @@ describe('IgxGridState - input properties #grid', () => { it('setState should correctly restore grid filtering state from string', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; const filteringState = '{"filtering":{"filteringOperands":[{"filteringOperands":[{"condition":{"name":"true","isUnary":true,"iconName":"filter_true"},"fieldName":"InStock","ignoreCase":true,"conditionName":"true"}],"operator":0,"fieldName":"InStock"}],"operator":0,"type":0}}'; const initialState = '{"filtering":{"filteringOperands":[],"operator":0}}'; @@ -195,7 +196,7 @@ describe('IgxGridState - input properties #grid', () => { hidden: false, maxWidth: '300px', searchable: true, sortingIgnoreCase: true, filteringIgnoreCase: true, editable: true, headerClasses: '', headerGroupClasses: '', resizable: false }; fix.componentInstance.columns.push(lastDateCol); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; grid.getCellByColumn(0, 'LastDate').value = new Date('2021-06-05T23:59'); fix.detectChanges(); const state = fix.componentInstance.state; @@ -216,7 +217,7 @@ describe('IgxGridState - input properties #grid', () => { it('setState should correctly restore grid filtering state from with null date values', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; grid.getCellByColumn(0, 'OrderDate').value = null; fix.detectChanges(); const state = fix.componentInstance.state; @@ -237,7 +238,7 @@ describe('IgxGridState - input properties #grid', () => { it('setState should correctly restore grid filtering state from object', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; const filteringState = '{"filtering":{"filteringOperands":[{"filteringOperands":[{"condition":{"name":"true","isUnary":true,"iconName":"filter_true"},"fieldName":"InStock","ignoreCase":true,"conditionName":"true"}],"operator":0,"fieldName":"InStock"}],"operator":0,"type":0}}'; const filteringStateObject = JSON.parse(filteringState) as IGridState; @@ -262,10 +263,8 @@ describe('IgxGridState - input properties #grid', () => { const state = fix.componentInstance.state; - const initialState = - '{"filtering":{"filteringOperands":[],"operator":0}}'; - const filteringState = - '{"filtering":{"filteringOperands":[{"filteringOperands":[{"fieldName":"ProductID","condition":{"name":"custom","isUnary":false,"iconName":"custom"},"searchVal":"custom","ignoreCase":true,"conditionName":"custom"}],"operator":1,"fieldName":"FirstName"}],"operator":0,"type":0}}'; + const initialState = '{"filtering":{"filteringOperands":[],"operator":0}}'; + const filteringState = '{"filtering":{"filteringOperands":[{"filteringOperands":[{"fieldName":"ProductID","condition":{"name":"custom","isUnary":false,"iconName":"custom"},"searchVal":"custom","ignoreCase":true,"conditionName":"custom"}],"operator":1,"fieldName":"FirstName"}],"operator":0,"type":0}}'; const filteringStateObject = JSON.parse(filteringState) as IGridState; let gridState = state.getState(true, "filtering"); @@ -275,10 +274,7 @@ describe('IgxGridState - input properties #grid', () => { fix.detectChanges(); gridState = state.getState(false, "filtering"); - HelperFunctions.verifyFilteringExpressions( - grid.filteringExpressionsTree, - gridState as IGridState - ); + HelperFunctions.verifyFilteringExpressions(grid.filteringExpressionsTree, gridState as IGridState); gridState = state.getState(true, "filtering"); expect(gridState).toBe(filteringState); }); @@ -286,7 +282,7 @@ describe('IgxGridState - input properties #grid', () => { it('setState should correctly restore grid sorting state from string', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; const sortingState = '{"sorting":[{"fieldName":"OrderDate","dir":1,"ignoreCase":true}]}'; const initialState = '{"sorting":[]}'; @@ -304,7 +300,7 @@ describe('IgxGridState - input properties #grid', () => { it('setState should correctly restore grid sorting state from object', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; const sortingState = '{"sorting":[{"fieldName":"OrderDate","dir":1,"ignoreCase":true}]}'; const sortingStateObject = JSON.parse(sortingState) as IGridState; @@ -323,7 +319,7 @@ describe('IgxGridState - input properties #grid', () => { it('setState should correctly restore grid groupBy state from string', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; const groupingState = '{"groupBy":{"expressions":[{"dir":1,"fieldName":"ProductID","ignoreCase":false},{"dir":1,"fieldName":"OrderDate","ignoreCase":false}],"expansion":[],"defaultExpanded":true}}'; const initialState = '{"groupBy":{"expressions":[],"expansion":[],"defaultExpanded":true}}'; @@ -341,7 +337,7 @@ describe('IgxGridState - input properties #grid', () => { it('setState should correctly restore grid groupBy state from object', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; const groupingState = '{"groupBy":{"expressions":[{"dir":1,"fieldName":"ProductID","ignoreCase":false},{"dir":1,"fieldName":"OrderDate","ignoreCase":false}],"expansion":[],"defaultExpanded":true}}'; const initialState = '{"groupBy":{"expressions":[],"expansion":[],"defaultExpanded":true}}'; @@ -380,7 +376,7 @@ describe('IgxGridState - input properties #grid', () => { fix.detectChanges(); const state = fix.componentInstance.state; const grid = fix.componentInstance.grid; - spyOn(grid.columnInit, 'emit').and.callThrough(); + vi.spyOn(grid.columnInit, 'emit'); const columnsState = '{"columns":[{"pinned":true,"sortable":true,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"testCss","headerGroupClasses":"","maxWidth":"300px","groupable":false,"hidden":false,"dataType":"number","hasSummary":false,"field":"ProductID","width":"150px","header":"Product ID","resizable":true,"searchable":false,"selectable":false,"key":"ProductID","columnGroup":false,"disableHiding":false,"disablePinning":false},{"pinned":true,"sortable":true,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,"hidden":false,"dataType":"string","hasSummary":false,"field":"ProductName","width":"200px","header":"Product Name","resizable":true,"searchable":true,"selectable":true,"key":"ProductName","columnGroup":false,"disableHiding":false,"disablePinning":false},{"pinned":false,"sortable":false,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":false,"hidden":false,"dataType":"boolean","hasSummary":true,"field":"InStock","width":"140px","header":"In Stock","resizable":true,"searchable":true,"selectable":true,"key":"InStock","columnGroup":false,"disableHiding":false,"disablePinning":true},{"pinned":false,"sortable":true,"filterable":false,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,"hidden":false,"dataType":"date","hasSummary":false,"field":"OrderDate","width":"110px","header":"Date ordered","resizable":false,"searchable":true,"selectable":true,"key":"OrderDate","columnGroup":false,"disableHiding":false,"disablePinning":false}]}'; const initialState = '{"columns":[{"pinned":true,"sortable":true,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"testCss","headerGroupClasses":"","maxWidth":"300px","groupable":false,"hidden":false,"dataType":"number","hasSummary":false,"field":"ProductID","width":"150px","header":"Product ID","resizable":true,"searchable":false,"key":"ProductID","columnGroup":false,"disableHiding":false,"disablePinning":false},{"pinned":false,"sortable":true,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,"hidden":false,"dataType":"string","hasSummary":false,"field":"ProductName","width":"150px","header":"Product Name","resizable":true,"searchable":true,"selectable":false,"key":"ProductName","columnGroup":false,"disableHiding":false,"disablePinning":false},{"pinned":false,"sortable":false,"filterable":true,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":false,"hidden":false,"dataType":"boolean","hasSummary":true,"field":"InStock","width":"140px","header":"In Stock","resizable":true,"searchable":true,"key":"InStock","columnGroup":false,"disableHiding":false,"disablePinning":true},{"pinned":false,"sortable":true,"filterable":false,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,"hidden":false,"dataType":"date","hasSummary":false,"field":"OrderDate","width":"110px","header":"Date ordered","resizable":false,"searchable":true,"key":"OrderDate","columnGroup":false,"disableHiding":false,"disablePinning":false}]}'; const columnsStateObject = JSON.parse(columnsState); @@ -489,13 +485,13 @@ describe('IgxGridState - input properties #grid', () => { expect(grid.columns.indexOf(x)).not.toBe(-1); expect(x.bodyTemplate).toBe(fix.componentInstance.template); }); - expect(grid.columns[grid.columns.length - 1 ].field).toBe("AnotherColumn"); + expect(grid.columns[grid.columns.length - 1].field).toBe("AnotherColumn"); }); it('setState should correctly restore grid paging state from string', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; const pagingState = '{"paging":{"index":0,"recordsPerPage":5,"metadata":{"countPages":2,"countRecords":10,"error":0}}}'; const initialState = '{"paging":{"index":0,"recordsPerPage":15,"metadata":{"countPages":1,"countRecords":10,"error":0}}}'; @@ -513,7 +509,7 @@ describe('IgxGridState - input properties #grid', () => { it('setState should correctly restore grid paging state from object', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; const pagingState = '{"paging":{"index":0,"recordsPerPage":5,"metadata":{"countPages":2,"countRecords":10,"error":0}}}'; const pagingStateObject = JSON.parse(pagingState) as IGridState; @@ -532,7 +528,7 @@ describe('IgxGridState - input properties #grid', () => { it('setState should correctly restore grid row selection state from string', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; const rowSelectionState = '{"rowSelection":[1,3,5,6]}'; const initialState = '{"rowSelection":[]}'; @@ -550,7 +546,7 @@ describe('IgxGridState - input properties #grid', () => { it('setState should correctly restore grid row selection state from object', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; const rowSelectionState = '{"rowSelection":[1,3,5,6]}'; const initialState = '{"rowSelection":[]}'; @@ -569,7 +565,7 @@ describe('IgxGridState - input properties #grid', () => { it('setState should correctly restore grid row pinning state from object', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; grid.primaryKey = 'ProductID'; fix.detectChanges(); const state = fix.componentInstance.state; @@ -603,7 +599,7 @@ describe('IgxGridState - input properties #grid', () => { it('setState should correctly restore grid moving state from string', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; const movingState = '{"moving":false}'; @@ -622,7 +618,7 @@ describe('IgxGridState - input properties #grid', () => { it('setState should correctly restore grid moving state from object', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; const movingState = '{"moving":false}'; const initialState = '{"moving":true}'; @@ -652,7 +648,7 @@ describe('IgxGridState - input properties #grid', () => { it('setState should correctly restore grid cell selection state from string', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; grid.rowSelection = GridSelectionMode.none; const state = fix.componentInstance.state; const cellSelectionState = '{"cellSelection":[{"rowStart":0,"rowEnd":2,"columnStart":1,"columnEnd":3}]}'; @@ -671,7 +667,7 @@ describe('IgxGridState - input properties #grid', () => { it('setState should correctly restore grid cell selection state from object', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; grid.rowSelection = GridSelectionMode.none; const state = fix.componentInstance.state; const cellSelectionState = '{"cellSelection":[{"rowStart":0,"rowEnd":2,"columnStart":1,"columnEnd":3}]}'; @@ -691,7 +687,7 @@ describe('IgxGridState - input properties #grid', () => { it('setState should correctly restore grid advanced filtering state from string', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; const advFilteringState = '{"advancedFiltering":{"filteringOperands":[{"fieldName":"InStock","condition":{"name":"true","isUnary":true,"iconName":"filter_true"},"searchVal":null,"ignoreCase":true,"conditionName":"true"},{"fieldName":"ProductID","condition":{"name":"greaterThan","isUnary":false,"iconName":"filter_greater_than"},"searchVal":"3","ignoreCase":true,"conditionName":"greaterThan"}],"operator":0,"type":1}}'; const initialState = '{"advancedFiltering":{}}'; @@ -709,7 +705,7 @@ describe('IgxGridState - input properties #grid', () => { it('setState should correctly restore grid advanced filtering state from object', () => { const fix = TestBed.createComponent(IgxGridStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; const advFilteringState = '{"advancedFiltering":{"filteringOperands":[{"fieldName":"InStock","condition":{"name":"true","isUnary":true,"iconName":"filter_true"},"searchVal":null,"ignoreCase":true,"conditionName":"true"},{"fieldName":"ProductID","condition":{"name":"greaterThan","isUnary":false,"iconName":"filter_greater_than"},"searchVal":"3","ignoreCase":true,"conditionName":"greaterThan"}],"operator":0,"type":1}}'; const initialState = '{"advancedFiltering":{}}'; @@ -749,7 +745,7 @@ describe('IgxGridState - input properties #grid', () => { it('should correctly restore expansion state from string', () => { const fix = TestBed.createComponent(IgxGridStateWithDetailsComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; const expansionState = '{"expansion":[[1,true],[2,true],[3,true]]}'; @@ -769,12 +765,12 @@ describe('IgxGridState - input properties #grid', () => { it('should correctly restore mrl column states.', () => { const fix = TestBed.createComponent(IgxGridMRLStateComponent); fix.detectChanges(); - const grid = fix.componentInstance.grid; + const grid = fix.componentInstance.grid; const state = fix.componentInstance.state; const gridColumnState = state.getState(false, 'columns') as IGridState; const group1 = gridColumnState.columns.find(x => x.field === 'group1'); - expect(group1.columnLayout).toBeTrue(); + expect(group1.columnLayout).toBe(true); const prodId = gridColumnState.columns.find(x => x.field === 'ProductID'); expect(prodId.columnLayout).toBeFalsy(); @@ -792,10 +788,10 @@ describe('IgxGridState - input properties #grid', () => { const group1Column = grid.getColumnByName("group1"); const prodIdColumn = grid.getColumnByName("ProductID"); - expect(group1Column.columnLayout).toBeTrue(); - expect(group1Column.pinned).toBeTrue(); - expect(prodIdColumn.pinned).toBeTrue(); - expect(prodIdColumn.columnLayoutChild).toBeTrue(); + expect(group1Column.columnLayout).toBe(true); + expect(group1Column.pinned).toBe(true); + expect(prodIdColumn.pinned).toBe(true); + expect(prodIdColumn.columnLayoutChild).toBe(true); expect(prodIdColumn.parent).toBe(group1Column); expect(prodIdColumn.rowStart).toBe(1); expect(prodIdColumn.rowEnd).toBe(4); @@ -807,42 +803,42 @@ describe('IgxGridState - input properties #grid', () => { class HelperFunctions { public static verifyColumns(columns: IColumnState[], gridState: IGridState) { columns.forEach((c, index) => { - expect(gridState.columns[index]).toEqual(jasmine.objectContaining(c)); + expect(gridState.columns[index]).toEqual(expect.objectContaining(c)); }); } public static verifySortingExpressions(sortingExpressions: ISortingExpression[], gridState: IGridState) { sortingExpressions.forEach((expr, i) => { - expect(expr).toEqual(jasmine.objectContaining(gridState.sorting[i])); + expect(expr).toEqual(expect.objectContaining(gridState.sorting[i])); }); } public static verifyGroupingExpressions(groupingExpressions: IGroupingExpression[], gridState: IGridState) { groupingExpressions.forEach((expr, i) => { - expect(expr).toEqual(jasmine.objectContaining(gridState.groupBy.expressions[i])); + expect(expr).toEqual(expect.objectContaining(gridState.groupBy.expressions[i])); }); } public static verifyGroupingExpansion(groupingExpansion: IGroupByExpandState[], groupBy: IGroupingState) { groupingExpansion.forEach((exp, i) => { - expect(exp).toEqual(jasmine.objectContaining(groupBy.expansion[i])); + expect(exp).toEqual(expect.objectContaining(groupBy.expansion[i])); }); } public static verifyFilteringExpressions(expressions: IFilteringExpressionsTree, gridState: IGridState) { - expect(expressions.fieldName).toBe(gridState.filtering.fieldName, 'Filtering expression field name is not correct'); - expect(expressions.operator).toBe(gridState.filtering.operator, 'Filtering expression operator value is not correct'); + expect(expressions.fieldName, 'Filtering expression field name is not correct').toBe(gridState.filtering.fieldName); + expect(expressions.operator, 'Filtering expression operator value is not correct').toBe(gridState.filtering.operator); expressions.filteringOperands.forEach((expr, i) => { - expect(expr).toEqual(jasmine.objectContaining(gridState.filtering.filteringOperands[i])); + expect(expr).toEqual(expect.objectContaining(gridState.filtering.filteringOperands[i])); }); } public static verifyAdvancedFilteringExpressions(expressions: IFilteringExpressionsTree, gridState: IGridState) { if (gridState.advancedFiltering) { - expect(expressions.fieldName).toBe(gridState.advancedFiltering.fieldName, 'Filtering expression field name is not correct'); - expect(expressions.operator).toBe(gridState.advancedFiltering.operator, 'Filtering expression operator value is not correct'); + expect(expressions.fieldName, 'Filtering expression field name is not correct').toBe(gridState.advancedFiltering.fieldName); + expect(expressions.operator, 'Filtering expression operator value is not correct').toBe(gridState.advancedFiltering.operator); expressions.filteringOperands.forEach((expr, i) => { - expect(expr).toEqual(jasmine.objectContaining(gridState.advancedFiltering.filteringOperands[i])); + expect(expr).toEqual(expect.objectContaining(gridState.advancedFiltering.filteringOperands[i])); }); } else { expect(expressions).toBeFalsy(); @@ -850,10 +846,10 @@ class HelperFunctions { } public static verifyPaging(paging: IPagingState, gridState: IGridState) { - expect(paging).toEqual(jasmine.objectContaining(gridState.paging)); + expect(paging).toEqual(expect.objectContaining(gridState.paging)); } - public static verifyMoving(moving: boolean, gridState: IGridState){ + public static verifyMoving(moving: boolean, gridState: IGridState) { expect(moving).toEqual(gridState.moving); } @@ -865,7 +861,7 @@ class HelperFunctions { public static verifyCellSelection(selectedCells: GridSelectionRange[], gridState: IGridState) { selectedCells.forEach((expr, i) => { - expect(expr).toEqual(jasmine.objectContaining(gridState.cellSelection[i])); + expect(expr).toEqual(expect.objectContaining(gridState.cellSelection[i])); }); } @@ -930,7 +926,7 @@ export class IgxGridStateComponent { { field: 'ProductName', header: 'Product Name', width: '150px', dataType: 'string', pinned: false, selectable: false, sortable: true, filterable: true, groupable: true, hasSummary: false, hidden: false, maxWidth: '300px', searchable: true, sortingIgnoreCase: true, filteringIgnoreCase: true, editable: false, headerClasses: '', headerGroupClasses: '', resizable: true, disablePinning: false }, { field: 'InStock', header: 'In Stock', width: '140px', dataType: 'boolean', pinned: false, sortable: false, filterable: true, groupable: false, hasSummary: true, hidden: false, maxWidth: '300px', searchable: true, sortingIgnoreCase: true, filteringIgnoreCase: true, editable: true, headerClasses: '', headerGroupClasses: '', resizable: true, disablePinning: true }, { field: 'OrderDate', header: 'Date ordered', width: '110px', dataType: 'date', pinned: false, sortable: true, filterable: false, groupable: true, hasSummary: false, hidden: false, maxWidth: '300px', searchable: true, sortingIgnoreCase: true, filteringIgnoreCase: true, editable: true, headerClasses: '', headerGroupClasses: '', resizable: false, disablePinning: false }, - ]; + ]; } @Component({ diff --git a/projects/igniteui-angular/grids/core/src/state.hierarchicalgrid.spec.ts b/projects/igniteui-angular/grids/core/src/state.hierarchicalgrid.spec.ts index d103ac20d2e..e4fd327fc09 100644 --- a/projects/igniteui-angular/grids/core/src/state.hierarchicalgrid.spec.ts +++ b/projects/igniteui-angular/grids/core/src/state.hierarchicalgrid.spec.ts @@ -10,6 +10,7 @@ import { IColumnState, IGridState } from './state-base.directive'; import { FilteringExpressionsTree, FilteringLogic, IFilteringExpressionsTree, IGroupingExpression, IgxStringFilteringOperand, IPagingState, ISortingExpression, SortingDirection } from 'igniteui-angular/core'; import { IgxHierarchicalGridComponent, IgxRowIslandComponent } from 'igniteui-angular/grids/hierarchical-grid'; import { IgxGridNavigationService } from './grid-navigation.service'; +import { describe, it, test, expect, beforeEach, vi } from 'vitest'; describe('IgxHierarchicalGridState - input properties #hGrid', () => { let fix; @@ -22,7 +23,7 @@ describe('IgxHierarchicalGridState - input properties #hGrid', () => { IgxGridNavigationService ] }).compileComponents(); - })) + })); beforeEach(() => { fix = TestBed.createComponent(IgxHierarchicalGridTestExpandedBaseComponent); @@ -32,9 +33,9 @@ describe('IgxHierarchicalGridState - input properties #hGrid', () => { it('should initialize an igxGridState with default options object', () => { fix.componentInstance.data = [ - {ID: 0, ProductName: 'Product: A0'}, - {ID: 1, ProductName: 'Product: A1', childData: generateDataUneven(1, 1)}, - {ID: 2, ProductName: 'Product: A2', childData: generateDataUneven(1, 1)} + { ID: 0, ProductName: 'Product: A0' }, + { ID: 1, ProductName: 'Product: A1', childData: generateDataUneven(1, 1) }, + { ID: 2, ProductName: 'Product: A2', childData: generateDataUneven(1, 1) } ]; fix.detectChanges(); @@ -52,15 +53,15 @@ describe('IgxHierarchicalGridState - input properties #hGrid', () => { }; const state = fix.componentInstance.state; - expect(state).toBeDefined('IgxGridState directive is initialized'); - expect(state.options).toEqual(jasmine.objectContaining(defaultOptions)); + expect(state, 'IgxGridState directive is initialized').toBeDefined(); + expect(state.options).toEqual(expect.objectContaining(defaultOptions)); }); it('should initialize an igxGridState with correct options input', () => { fix.componentInstance.data = [ - {ID: 0, ProductName: 'Product: A0'}, - {ID: 1, ProductName: 'Product: A1', childData: generateDataUneven(1, 1)}, - {ID: 2, ProductName: 'Product: A2', childData: generateDataUneven(1, 1)} + { ID: 0, ProductName: 'Product: A0' }, + { ID: 1, ProductName: 'Product: A1', childData: generateDataUneven(1, 1) }, + { ID: 2, ProductName: 'Product: A2', childData: generateDataUneven(1, 1) } ]; fix.detectChanges(); @@ -76,27 +77,29 @@ describe('IgxHierarchicalGridState - input properties #hGrid', () => { columnSelection: true, expansion: true, rowIslands: false, - moving:true + moving: true }; const state = fix.componentInstance.state; state.options = optionsInput; - expect(state.options).toEqual(jasmine.objectContaining(optionsInput)); + expect(state.options).toEqual(expect.objectContaining(optionsInput)); }); - it('getState should return corect JSON string', () => { - pending(); + it.skip('getState should return corect JSON string', () => { + // TODO: vitest-migration: The pending() function was converted to a skipped test (`it.skip`). See: https://vitest.dev/api/vi.html#it-skip + // pending(); + ; const initialGridState = '{"columns":[{"pinned":true,"sortable":true,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"testCss","headerGroupClasses":"","maxWidth":"300px","groupable":false,,"hidden":false,"dataType":"number","hasSummary":false,"field":"ID","width":"150px","header":"ID","resizable":true,"searchable":false,"selectable":true,"parent":null,"columnGroup":false,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":true,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,,"hidden":false,"dataType":"string","hasSummary":false,"field":"ProductName","width":"150px","header":"Product Name","resizable":true,"searchable":true,"selectable":true,"parent":null,"columnGroup":false,"disableHiding":true,"disablePinning":false}],"filtering":{"filteringOperands":[],"operator":0},"advancedFiltering":{},"sorting":[],"paging":{"index":0,"recordsPerPage":5,"metadata":{"countPages":4,"countRecords":20,"error":0}},"cellSelection":[],"rowSelection":[],"columnSelection":[],"rowPinning":[],"expansion":[],"rowIslands":[{"id":"igx-row-island-childData","parentRowID":"0","state":{"columns":[{"pinned":true,"sortable":true,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"testCss","headerGroupClasses":"","maxWidth":"300px","groupable":false,,"hidden":false,"dataType":"number","hasSummary":false,"field":"ID","width":"150px","header":"Product ID","resizable":true,"searchable":false,"selectable":true,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":true,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,,"hidden":false,"dataType":"string","hasSummary":false,"field":"ProductName","width":"150px","header":"Product Name","resizable":true,"searchable":true,"selectable":true,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":false,"filterable":true,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":false,,"hidden":false,"dataType":"boolean","hasSummary":true,"field":"Col1","width":"140px","header":"Col 1","resizable":true,"searchable":true,"selectable":true,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":true,"filterable":false,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,,"hidden":false,"dataType":"date","hasSummary":false,"field":"Col2","width":"110px","header":"Col 2","resizable":false,"searchable":true,"selectable":true,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":true,"filterable":false,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,,"hidden":false,"dataType":"date","hasSummary":false,"field":"Col3","width":"110px","header":"Col 3","resizable":false,"searchable":true,"selectable":true,"disableHiding":true,"disablePinning":false}],"filtering":{"filteringOperands":[],"operator":0},"advancedFiltering":{},"sorting":[],"paging":{"index":0,"recordsPerPage":5,"metadata":{"countPages":2,"countRecords":7,"error":0}},"cellSelection":[],"rowSelection":[],"columnSelection":[],"rowPinning":[],"expansion":[],"rowIslands":[]}},{"id":"igx-row-island-childData","parentRowID":"1","state":{"columns":[{"pinned":true,"sortable":true,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"testCss","headerGroupClasses":"","maxWidth":"300px","groupable":false,,"hidden":false,"dataType":"number","hasSummary":false,"field":"ID","width":"150px","header":"Product ID","resizable":true,"searchable":false,"selectable":true,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":true,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,,"hidden":false,"dataType":"string","hasSummary":false,"field":"ProductName","width":"150px","header":"Product Name","resizable":true,"searchable":true,"selectable":true,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":false,"filterable":true,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":false,,"hidden":false,"dataType":"boolean","hasSummary":true,"field":"Col1","width":"140px","header":"Col 1","resizable":true,"searchable":true,"selectable":true,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":true,"filterable":false,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,,"hidden":false,"dataType":"date","hasSummary":false,"field":"Col2","width":"110px","header":"Col 2","resizable":false,"searchable":true,"selectable":true,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":true,"filterable":false,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,,"hidden":false,"dataType":"date","hasSummary":false,"field":"Col3","width":"110px","header":"Col 3","resizable":false,"searchable":true,"selectable":true,"disableHiding":true,"disablePinning":false}],"filtering":{"filteringOperands":[],"operator":0},"advancedFiltering":{},"sorting":[],"paging":{"index":0,"recordsPerPage":5,"metadata":{"countPages":3,"countRecords":14,"error":0}},"cellSelection":[],"rowSelection":[],"columnSelection":[],"rowPinning":[],"expansion":[],"rowIslands":[]}},{"id":"igx-row-island-childData","parentRowID":"2","state":{"columns":[{"pinned":true,"sortable":true,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"testCss","headerGroupClasses":"","maxWidth":"300px","groupable":false,,"hidden":false,"dataType":"number","hasSummary":false,"field":"ID","width":"150px","header":"Product ID","resizable":true,"searchable":false,"selectable":true,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":true,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,,"hidden":false,"dataType":"string","hasSummary":false,"field":"ProductName","width":"150px","header":"Product Name","resizable":true,"searchable":true,"selectable":true,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":false,"filterable":true,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":false,,"hidden":false,"dataType":"boolean","hasSummary":true,"field":"Col1","width":"140px","header":"Col 1","resizable":true,"searchable":true,"selectable":true,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":true,"filterable":false,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,,"hidden":false,"dataType":"date","hasSummary":false,"field":"Col2","width":"110px","header":"Col 2","resizable":false,"searchable":true,"selectable":true,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":true,"filterable":false,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,,"hidden":false,"dataType":"date","hasSummary":false,"field":"Col3","width":"110px","header":"Col 3","resizable":false,"searchable":true,"selectable":true,"disableHiding":true,"disablePinning":false}],"filtering":{"filteringOperands":[],"operator":0},"advancedFiltering":{},"sorting":[],"paging":{"index":0,"recordsPerPage":5,"metadata":{"countPages":2,"countRecords":7,"error":0}},"cellSelection":[],"rowSelection":[],"columnSelection":[],"rowPinning":[],"expansion":[],"rowIslands":[]}},{"id":"igx-row-island-childData","parentRowID":"3","state":{"columns":[{"pinned":true,"sortable":true,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"testCss","headerGroupClasses":"","maxWidth":"300px","groupable":false,,"hidden":false,"dataType":"number","hasSummary":false,"field":"ID","width":"150px","header":"Product ID","resizable":true,"searchable":false,"selectable":true,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":true,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,,"hidden":false,"dataType":"string","hasSummary":false,"field":"ProductName","width":"150px","header":"Product Name","resizable":true,"searchable":true,"selectable":true,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":false,"filterable":true,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":false,,"hidden":false,"dataType":"boolean","hasSummary":true,"field":"Col1","width":"140px","header":"Col 1","resizable":true,"searchable":true,"selectable":true,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":true,"filterable":false,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,,"hidden":false,"dataType":"date","hasSummary":false,"field":"Col2","width":"110px","header":"Col 2","resizable":false,"searchable":true,"selectable":true,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":true,"filterable":false,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,,"hidden":false,"dataType":"date","hasSummary":false,"field":"Col3","width":"110px","header":"Col 3","resizable":false,"searchable":true,"selectable":true,"disableHiding":true,"disablePinning":false}],"filtering":{"filteringOperands":[],"operator":0},"advancedFiltering":{},"sorting":[],"paging":{"index":0,"recordsPerPage":5,"metadata":{"countPages":3,"countRecords":14,"error":0}},"cellSelection":[],"rowSelection":[],"columnSelection":[],"rowPinning":[],"expansion":[],"rowIslands":[]}},{"id":"igx-row-island-childData","parentRowID":"4","state":{"columns":[{"pinned":true,"sortable":true,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"testCss","headerGroupClasses":"","maxWidth":"300px","groupable":false,,"hidden":false,"dataType":"number","hasSummary":false,"field":"ID","width":"150px","header":"Product ID","resizable":true,"searchable":false,"selectable":true,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":true,"filterable":true,"editable":false,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,,"hidden":false,"dataType":"string","hasSummary":false,"field":"ProductName","width":"150px","header":"Product Name","resizable":true,"searchable":true,"selectable":true,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":false,"filterable":true,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":false,,"hidden":false,"dataType":"boolean","hasSummary":true,"field":"Col1","width":"140px","header":"Col 1","resizable":true,"searchable":true,"selectable":true,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":true,"filterable":false,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,,"hidden":false,"dataType":"date","hasSummary":false,"field":"Col2","width":"110px","header":"Col 2","resizable":false,"searchable":true,"selectable":true,"disableHiding":true,"disablePinning":false},{"pinned":false,"sortable":true,"filterable":false,"editable":true,"sortingIgnoreCase":true,"filteringIgnoreCase":true,"headerClasses":"","headerGroupClasses":"","maxWidth":"300px","groupable":true,,"hidden":false,"dataType":"date","hasSummary":false,"field":"Col3","width":"110px","header":"Col 3","resizable":false,"searchable":true,"selectable":true,"disableHiding":true,"disablePinning":false}],"filtering":{"filteringOperands":[],"operator":0},"advancedFiltering":{},"sorting":[],"paging":{"index":0,"recordsPerPage":5,"metadata":{"countPages":2,"countRecords":7,"error":0}},"cellSelection":[],"rowSelection":[],"columnSelection":[],"rowPinning":[],"expansion":[],"rowIslands":[]}}]}'; fix.detectChanges(); const state = fix.componentInstance.state; const gridState = state.getState(); - expect(gridState).toBe(initialGridState, 'JSON string representation of the initial grid state is not correct'); + expect(gridState, 'JSON string representation of the initial grid state is not correct').toBe(initialGridState); }); it('getState should return corect IGridState object when using default options', () => { fix.detectChanges(); - grid = fix.componentInstance.hgrid; + grid = fix.componentInstance.hgrid; const state = fix.componentInstance.state; const gridFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); @@ -319,8 +322,10 @@ describe('IgxHierarchicalGridState - input properties #hGrid', () => { expect(gridState).toBe(sortingState); }); - it('setState should correctly restore grid paging state from string', () => { - pending(); + it.skip('setState should correctly restore grid paging state from string', () => { + // TODO: vitest-migration: The pending() function was converted to a skipped test (`it.skip`). See: https://vitest.dev/api/vi.html#it-skip + // pending(); + ; const state = fix.componentInstance.state; const initialState = '{"paging":{"index":0,"recordsPerPage":5,"metadata":{"countPages":4,"countRecords":20,"error":0}},"rowIslands":[{"id":"igx-row-island-childData","parentRowID":"0","state":{"paging":{"index":0,"recordsPerPage":5,"metadata":{"countPages":2,"countRecords":7,"error":0}},"rowIslands":[]}},{"id":"igx-row-island-childData","parentRowID":"1","state":{"paging":{"index":0,"recordsPerPage":5,"metadata":{"countPages":3,"countRecords":14,"error":0}},"rowIslands":[]}},{"id":"igx-row-island-childData","parentRowID":"2","state":{"paging":{"index":0,"recordsPerPage":5,"metadata":{"countPages":2,"countRecords":7,"error":0}},"rowIslands":[]}},{"id":"igx-row-island-childData","parentRowID":"3","state":{"paging":{"index":0,"recordsPerPage":5,"metadata":{"countPages":3,"countRecords":14,"error":0}},"rowIslands":[]}},{"id":"igx-row-island-childData","parentRowID":"4","state":{"paging":{"index":0,"recordsPerPage":5,"metadata":{"countPages":2,"countRecords":7,"error":0}},"rowIslands":[]}}]}'; @@ -494,36 +499,36 @@ describe('IgxHierarchicalGridState - input properties #hGrid', () => { class HelperFunctions { public static verifyColumns(columns: IColumnState[], gridState: IGridState) { columns.forEach((c, index) => { - expect(gridState.columns[index]).toEqual(jasmine.objectContaining(c)); + expect(gridState.columns[index]).toEqual(expect.objectContaining(c)); }); } public static verifySortingExpressions(sortingExpressions: ISortingExpression[], gridState: IGridState) { sortingExpressions.forEach((expr, i) => { - expect(expr).toEqual(jasmine.objectContaining(gridState.sorting[i])); + expect(expr).toEqual(expect.objectContaining(gridState.sorting[i])); }); } public static verifyGroupingExpressions(groupingExpressions: IGroupingExpression[], gridState: IGridState) { groupingExpressions.forEach((expr, i) => { - expect(expr).toEqual(jasmine.objectContaining(gridState.groupBy.expressions[i])); + expect(expr).toEqual(expect.objectContaining(gridState.groupBy.expressions[i])); }); } public static verifyFilteringExpressions(expressions: IFilteringExpressionsTree, gridState: IGridState) { - expect(expressions.fieldName).toBe(gridState.filtering.fieldName, 'Filtering expression field name is not correct'); - expect(expressions.operator).toBe(gridState.filtering.operator, 'Filtering expression operator value is not correct'); + expect(expressions.fieldName, 'Filtering expression field name is not correct').toBe(gridState.filtering.fieldName); + expect(expressions.operator, 'Filtering expression operator value is not correct').toBe(gridState.filtering.operator); expressions.filteringOperands.forEach((expr, i) => { - expect(expr).toEqual(jasmine.objectContaining(gridState.filtering.filteringOperands[i])); + expect(expr).toEqual(expect.objectContaining(gridState.filtering.filteringOperands[i])); }); } public static verifyAdvancedFilteringExpressions(expressions: IFilteringExpressionsTree, gridState: IGridState) { if (gridState.advancedFiltering) { - expect(expressions.fieldName).toBe(gridState.advancedFiltering.fieldName, 'Filtering expression field name is not correct'); - expect(expressions.operator).toBe(gridState.advancedFiltering.operator, 'Filtering expression operator value is not correct'); + expect(expressions.fieldName, 'Filtering expression field name is not correct').toBe(gridState.advancedFiltering.fieldName); + expect(expressions.operator, 'Filtering expression operator value is not correct').toBe(gridState.advancedFiltering.operator); expressions.filteringOperands.forEach((expr, i) => { - expect(expr).toEqual(jasmine.objectContaining(gridState.advancedFiltering.filteringOperands[i])); + expect(expr).toEqual(expect.objectContaining(gridState.advancedFiltering.filteringOperands[i])); }); } else { expect(expressions).toBeFalsy(); @@ -548,7 +553,7 @@ class HelperFunctions { const parentRowId = this.getParentRowID(chGrid); const rowIslandState = state.rowIslands.find(st => st.id === rowIslandComponent.id && st.parentRowID === parentRowId); if (rowIslandState) { - const childGridState = { grid: chGrid, state: rowIslandState.state, rowIslandID: rowIslandState.id, parentRowID: parentRowId}; + const childGridState = { grid: chGrid, state: rowIslandState.state, rowIslandID: rowIslandState.id, parentRowID: parentRowId }; gridStatesCollection.push(childGridState); } }); @@ -558,17 +563,15 @@ class HelperFunctions { } public static getChildGridState(state, rowIslandID, parentRowID): any { - const childGridState = state.rowIslands?.find( - st => st.id === rowIslandID && st.parentRowID === parentRowID - ); + const childGridState = state.rowIslands?.find(st => st.id === rowIslandID && st.parentRowID === parentRowID); return childGridState?.state; } public static verifyPaging(paging: IPagingState, gridState: IGridState) { - expect(paging).toEqual(jasmine.objectContaining(gridState.paging)); + expect(paging).toEqual(expect.objectContaining(gridState.paging)); } - public static verifyMoving(moving: boolean, gridState: IGridState){ + public static verifyMoving(moving: boolean, gridState: IGridState) { expect(moving).toEqual(gridState.moving); } @@ -580,7 +583,7 @@ class HelperFunctions { public static verifyCellSelection(selectedCells: GridSelectionRange[], gridState: IGridState) { selectedCells.forEach((expr, i) => { - expect(expr).toEqual(jasmine.objectContaining(gridState.cellSelection[i])); + expect(expr).toEqual(expect.objectContaining(gridState.cellSelection[i])); }); } @@ -688,10 +691,14 @@ class HelperFunctions { imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxPaginatorComponent, IgxRowIslandComponent, IgxGridStateDirective] }) export class IgxHierarchicalGridTestExpandedBaseComponent { - @ViewChild('hGrid', { read: IgxHierarchicalGridComponent, static: true }) public hgrid: IgxHierarchicalGridComponent; - @ViewChild('rowIsland', { read: IgxRowIslandComponent, static: true }) public rowIsland: IgxRowIslandComponent; - @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) public rowIsland2: IgxRowIslandComponent; - @ViewChild(IgxGridStateDirective, { static: true }) public state: IgxGridStateDirective; + @ViewChild('hGrid', { read: IgxHierarchicalGridComponent, static: true }) + public hgrid: IgxHierarchicalGridComponent; + @ViewChild('rowIsland', { read: IgxRowIslandComponent, static: true }) + public rowIsland: IgxRowIslandComponent; + @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) + public rowIsland2: IgxRowIslandComponent; + @ViewChild(IgxGridStateDirective, { static: true }) + public state: IgxGridStateDirective; public data; public options = { @@ -727,13 +734,14 @@ export const generateDataUneven = (count: number, level: number, parentID: strin let children; for (let i = 0; i < count; i++) { const rowID = parentID ? parentID + i : i.toString(); - if (level > 0 ) { - // Have child grids for row with even id less rows by not multiplying by 2 - children = generateDataUneven((i % 2 + 1) * Math.round(count / 3) , currLevel - 1, rowID); + if (level > 0) { + // Have child grids for row with even id less rows by not multiplying by 2 + children = generateDataUneven((i % 2 + 1) * Math.round(count / 3), currLevel - 1, rowID); } prods.push({ - ID: rowID, ChildLevels: currLevel, ProductName: 'Product: A' + i, Col1: i, - Col2: i, Col3: i, childData: children, childData2: children }); + ID: rowID, ChildLevels: currLevel, ProductName: 'Product: A' + i, Col1: i, + Col2: i, Col3: i, childData: children, childData2: children + }); } return prods; }; diff --git a/projects/igniteui-angular/grids/core/src/state.pivotgrid.spec.ts b/projects/igniteui-angular/grids/core/src/state.pivotgrid.spec.ts index 0d399eb6624..31faa470533 100644 --- a/projects/igniteui-angular/grids/core/src/state.pivotgrid.spec.ts +++ b/projects/igniteui-angular/grids/core/src/state.pivotgrid.spec.ts @@ -9,6 +9,7 @@ import { IPivotDimension, IPivotGridRecord } from './pivot-grid.interface'; import { IgxPivotRowDimensionHeaderComponent } from 'igniteui-angular/grids/pivot-grid/src/pivot-row-dimension-header.component'; import { IgxPivotDateDimension } from './pivot-grid-dimensions'; import { IgxGridNavigationService } from './grid-navigation.service'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('IgxPivotGridState #pivotGrid :', () => { let fixture; @@ -48,12 +49,13 @@ describe('IgxPivotGridState #pivotGrid :', () => { { "memberName": "Country", "enabled": true, "level": 0 } ], "rows": [ { "memberName": "City", "enabled": true, "level": 0 }, - { "memberName": "ProductCategory", "enabled": true, "level": 0 }], + { "memberName": "ProductCategory", "enabled": true, "level": 0 } + ], "values": [{ - "member": "UnitsSold", "aggregate": { "key": "SUM", "label": "Sum" }, - "enabled": true - }], - "filters" : [] + "member": "UnitsSold", "aggregate": { "key": "SUM", "label": "Sum" }, + "enabled": true + }], + "filters": [] } }; @@ -146,8 +148,7 @@ describe('IgxPivotGridState #pivotGrid :', () => { // rows const expectedOrder = ['Yokohama', 'Sofia', 'Plovdiv', 'New York', 'London', 'Ciudad de la Costa']; - const rowHeaders = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + const rowHeaders = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); const rowDimensionHeaders = rowHeaders.map(x => x.componentInstance.column.header); expect(rowDimensionHeaders).toEqual(expectedOrder); @@ -192,8 +193,7 @@ describe('IgxPivotGridState #pivotGrid :', () => { state.setState(stateToRestore, 'pivotConfiguration'); fixture.detectChanges(); - const rowHeaders = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + const rowHeaders = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); const rowDimensionHeaders = rowHeaders.map(x => x.componentInstance.column.header); expect(rowDimensionHeaders).toEqual(['Sofia']); }); @@ -201,17 +201,14 @@ describe('IgxPivotGridState #pivotGrid :', () => { it('should successfully restore the IgxPivotDateDimension.', () => { const state = fixture.componentInstance.state; pivotGrid.pivotConfiguration.rows = [ - new IgxPivotDateDimension( - { - memberName: 'Date', - enabled: true - }, - { - months: true, - quarters: false, - years: true - } - ) + new IgxPivotDateDimension({ + memberName: 'Date', + enabled: true + }, { + months: true, + quarters: false, + years: true + }) ]; pivotGrid.pipeTrigger++; fixture.detectChanges(); @@ -222,8 +219,7 @@ describe('IgxPivotGridState #pivotGrid :', () => { const rows = pivotGrid.rowList.toArray(); expect(rows.length).toBe(1); const expectedHeaders = ['All Periods']; - const rowHeaders = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + const rowHeaders = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); const rowDimensionHeaders = rowHeaders.map(x => x.componentInstance.column.header); expect(rowDimensionHeaders).toEqual(expectedHeaders); }); @@ -239,7 +235,7 @@ describe('IgxPivotGridState #pivotGrid :', () => { expect(pivotGrid.selectedRows.length).toBe(2); const jsonString = state.getState(true); // clear - pivotGrid. selectionService.rowSelection.clear(); + pivotGrid.selectionService.rowSelection.clear(); expect(pivotGrid.selectedRows.length).toBe(0); // set old state state.setState(jsonString); @@ -247,7 +243,7 @@ describe('IgxPivotGridState #pivotGrid :', () => { expect(pivotGrid.selectedRows.length).toBe(2); }); - it('should allow setting back custom functions on init.', async() => { + it('should allow setting back custom functions on init.', async () => { const state = fixture.componentInstance.state; const customFunc = () => 'All'; pivotGrid.pivotConfiguration.rows = [ @@ -271,8 +267,7 @@ describe('IgxPivotGridState #pivotGrid :', () => { const rows = pivotGrid.rowList.toArray(); expect(rows.length).toBe(1); const expectedHeaders = ['All']; - const rowHeaders = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + const rowHeaders = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); const rowDimensionHeaders = rowHeaders.map(x => x.componentInstance.column.header); expect(rowDimensionHeaders).toEqual(expectedHeaders); }); diff --git a/projects/igniteui-angular/grids/core/src/state.treegrid.spec.ts b/projects/igniteui-angular/grids/core/src/state.treegrid.spec.ts index d18e972ab3d..b1f104ab821 100644 --- a/projects/igniteui-angular/grids/core/src/state.treegrid.spec.ts +++ b/projects/igniteui-angular/grids/core/src/state.treegrid.spec.ts @@ -17,6 +17,7 @@ import { IgxPaginatorComponent } from 'igniteui-angular/paginator'; import { IgxColumnComponent } from './public_api'; import { IColumnState, IGridState } from './state-base.directive'; import { IgxTreeGridComponent } from 'igniteui-angular/grids/tree-grid'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('IgxTreeGridState - input properties #tGrid', () => { let fix; @@ -53,8 +54,8 @@ describe('IgxTreeGridState - input properties #tGrid', () => { const state = fix.componentInstance.state; - expect(state).toBeDefined('IgxGridState directive is initialized'); - expect(state.options).toEqual(jasmine.objectContaining(defaultOptions)); + expect(state, 'IgxGridState directive is initialized').toBeDefined(); + expect(state.options).toEqual(expect.objectContaining(defaultOptions)); }); it('getState should return correct IGridState object when options are not default', () => { @@ -86,7 +87,7 @@ describe('IgxTreeGridState - input properties #tGrid', () => { const state = fix.componentInstance.state; const gridState = state.getState(); - expect(gridState).toBe(initialGridState, 'JSON string representation of the initial grid state is not correct'); + expect(gridState, 'JSON string representation of the initial grid state is not correct').toBe(initialGridState); }); it('getState should return correct IGridState object when using default options', () => { @@ -123,7 +124,7 @@ describe('IgxTreeGridState - input properties #tGrid', () => { const filtering = grid.filteringExpressionsTree; let gridState = state.getState(true, 'filtering'); - expect(gridState).toBe('{"filtering":{"filteringOperands":[],"operator":0}}', 'JSON string'); + expect(gridState, 'JSON string').toBe('{"filtering":{"filteringOperands":[],"operator":0}}'); gridState = state.getState(false, ['filtering']) as IGridState; HelperFunctions.verifyFilteringExpressions(filtering, gridState); @@ -151,7 +152,7 @@ describe('IgxTreeGridState - input properties #tGrid', () => { const moving = grid.moving; let gridState = state.getState(true, 'moving'); - expect(gridState).toBe('{"moving":true}', 'JSON string'); + expect(gridState, 'JSON string').toBe('{"moving":true}'); gridState = state.getState(false, ['moving']) as IGridState; HelperFunctions.verifyMoving(moving, gridState); @@ -275,42 +276,42 @@ describe('IgxTreeGridState - input properties #tGrid', () => { class HelperFunctions { public static verifyColumns(columns: IColumnState[], gridState: IGridState) { columns.forEach((c, index) => { - expect(gridState.columns[index]).toEqual(jasmine.objectContaining(c)); + expect(gridState.columns[index]).toEqual(expect.objectContaining(c)); }); } public static verifySortingExpressions(sortingExpressions: ISortingExpression[], gridState: IGridState) { sortingExpressions.forEach((expr, i) => { - expect(expr).toEqual(jasmine.objectContaining(gridState.sorting[i])); + expect(expr).toEqual(expect.objectContaining(gridState.sorting[i])); }); } public static verifyGroupingExpressions(groupingExpressions: IGroupingExpression[], gridState: IGridState) { groupingExpressions.forEach((expr, i) => { - expect(expr).toEqual(jasmine.objectContaining(gridState.groupBy.expressions[i])); + expect(expr).toEqual(expect.objectContaining(gridState.groupBy.expressions[i])); }); } public static verifyGroupingExpansion(groupingExpansion: IGroupByExpandState[], groupBy: IGroupingState) { groupingExpansion.forEach((exp, i) => { - expect(exp).toEqual(jasmine.objectContaining(groupBy.expansion[i])); + expect(exp).toEqual(expect.objectContaining(groupBy.expansion[i])); }); } public static verifyFilteringExpressions(expressions: IFilteringExpressionsTree, gridState: IGridState) { - expect(expressions.fieldName).toBe(gridState.filtering.fieldName, 'Filtering expression field name is not correct'); - expect(expressions.operator).toBe(gridState.filtering.operator, 'Filtering expression operator value is not correct'); + expect(expressions.fieldName, 'Filtering expression field name is not correct').toBe(gridState.filtering.fieldName); + expect(expressions.operator, 'Filtering expression operator value is not correct').toBe(gridState.filtering.operator); expressions.filteringOperands.forEach((expr, i) => { - expect(expr).toEqual(jasmine.objectContaining(gridState.filtering.filteringOperands[i])); + expect(expr).toEqual(expect.objectContaining(gridState.filtering.filteringOperands[i])); }); } public static verifyAdvancedFilteringExpressions(expressions: IFilteringExpressionsTree, gridState: IGridState) { if (gridState.advancedFiltering) { - expect(expressions.fieldName).toBe(gridState.advancedFiltering.fieldName, 'Filtering expression field name is not correct'); - expect(expressions.operator).toBe(gridState.advancedFiltering.operator, 'Filtering expression operator value is not correct'); + expect(expressions.fieldName, 'Filtering expression field name is not correct').toBe(gridState.advancedFiltering.fieldName); + expect(expressions.operator, 'Filtering expression operator value is not correct').toBe(gridState.advancedFiltering.operator); expressions.filteringOperands.forEach((expr, i) => { - expect(expr).toEqual(jasmine.objectContaining(gridState.advancedFiltering.filteringOperands[i])); + expect(expr).toEqual(expect.objectContaining(gridState.advancedFiltering.filteringOperands[i])); }); } else { expect(expressions).toBeFalsy(); @@ -318,10 +319,10 @@ class HelperFunctions { } public static verifyPaging(paging: IPagingState, gridState: IGridState) { - expect(paging).toEqual(jasmine.objectContaining(gridState.paging)); + expect(paging).toEqual(expect.objectContaining(gridState.paging)); } - public static verifyMoving(moving: boolean, gridState: IGridState){ + public static verifyMoving(moving: boolean, gridState: IGridState) { expect(moving).toEqual(gridState.moving); } @@ -333,7 +334,7 @@ class HelperFunctions { public static verifyCellSelection(selectedCells: GridSelectionRange[], gridState: IGridState) { selectedCells.forEach((expr, i) => { - expect(expr).toEqual(jasmine.objectContaining(gridState.cellSelection[i])); + expect(expr).toEqual(expect.objectContaining(gridState.cellSelection[i])); }); } } @@ -371,8 +372,10 @@ class HelperFunctions { imports: [IgxTreeGridComponent, IgxColumnComponent, IgxPaginatorComponent, IgxGridStateDirective] }) export class IgxTreeGridTreeDataTestComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; - @ViewChild(IgxGridStateDirective, { static: true }) public state: IgxGridStateDirective; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxGridStateDirective, { static: true }) + public state: IgxGridStateDirective; public columns: any[] = [ { field: 'ID', header: 'ID', width: '150px', dataType: 'number', pinned: true, sortable: true, filterable: true, groupable: false, hasSummary: false, hidden: false, maxWidth: '300px', searchable: false, sortingIgnoreCase: true, filteringIgnoreCase: true, editable: false, headerClasses: 'testCss', headerGroupClasses: '', resizable: true }, diff --git a/projects/igniteui-angular/grids/grid/src/cell-merge.spec.ts b/projects/igniteui-angular/grids/grid/src/cell-merge.spec.ts index 918975267a2..fc6d73a37a7 100644 --- a/projects/igniteui-angular/grids/grid/src/cell-merge.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/cell-merge.spec.ts @@ -2,7 +2,8 @@ import { Component, TemplateRef, ViewChild } from '@angular/core'; import { TestBed, waitForAsync } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { ByLevelTreeGridMergeStrategy, DefaultMergeStrategy, DefaultSortingStrategy, GridColumnDataType, GridTypeBase, IgxStringFilteringOperand, ɵSize, SortingDirection } from 'igniteui-angular/core'; -import { IgxPaginatorComponent } from 'igniteui-angular/paginator';; +import { IgxPaginatorComponent } from 'igniteui-angular/paginator'; +; import { DataParent } from '../../../test-utils/sample-test-data.spec'; import { GridFunctions, GridSelectionFunctions } from '../../../test-utils/grid-functions.spec'; import { By } from '@angular/platform-browser'; @@ -15,6 +16,7 @@ import { IgxGridComponent } from './grid.component'; import { IgxHierarchicalRowComponent } from '../../hierarchical-grid/src/hierarchical-row.component'; import { IgxHierarchicalGridComponent } from 'igniteui-angular/grids/hierarchical-grid'; import { GridCellMergeMode, IgxColumnComponent, IgxGridMRLNavigationService, IgxGridNavigationService } from 'igniteui-angular/grids/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxGrid - Cell merging #grid', () => { let fix; @@ -931,26 +933,23 @@ describe('IgxGrid - Cell merging #grid', () => { describe('Multi-row layout', () => { it('should throw warning and disallow merging with mrl.', () => { - jasmine.getEnv().allowRespy(true); - fix = TestBed.createComponent(ColumnLayoutTestComponent); fix.detectChanges(); grid = fix.componentInstance.grid; - spyOn(console, 'warn'); + vi.spyOn(console, 'warn'); grid.columns[1].merge = true; fix.detectChanges(); expect(console.warn).toHaveBeenCalledWith('Merging is not supported with multi-row layouts.'); expect(console.warn).toHaveBeenCalledTimes(1); - jasmine.getEnv().allowRespy(false); }); }); describe('Sizing', () => { it('should size correct when size is set to anything other than large', async () => { - fix.componentInstance.cols = [{ field: 'ProductName', dataType: GridColumnDataType.String, merge: true }] + fix.componentInstance.cols = [{ field: 'ProductName', dataType: GridColumnDataType.String, merge: true }]; fix.detectChanges(); - setElementSize(grid.nativeElement, ɵSize.Small) + setElementSize(grid.nativeElement, ɵSize.Small); fix.detectChanges(); await wait(100); fix.detectChanges(); @@ -1260,7 +1259,6 @@ export class DefaultCellMergeGridComponent extends DataParent { Released: true } ]; - } @Component({ @@ -1289,16 +1287,7 @@ export class IntegrationCellMergeGridComponent extends DefaultCellMergeGridCompo } class NoopMergeStrategy extends DefaultMergeStrategy { - public override merge( - data: any[], - field: string, - comparer: (prevRecord: any, record: any, field: string) => boolean = this.comparer, - result: any[], - activeRowIndexes: number[], - isDate?: boolean, - isTime?: boolean, - grid?: GridTypeBase - ) { + public override merge(data: any[], field: string, comparer: (prevRecord: any, record: any, field: string) => boolean = this.comparer, result: any[], activeRowIndexes: number[], isDate?: boolean, isTime?: boolean, grid?: GridTypeBase) { return data; } } diff --git a/projects/igniteui-angular/grids/grid/src/cell.spec.ts b/projects/igniteui-angular/grids/grid/src/cell.spec.ts index 95d97bc6142..b3de39bdb9f 100644 --- a/projects/igniteui-angular/grids/grid/src/cell.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/cell.spec.ts @@ -4,12 +4,12 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxGridComponent } from './public_api'; import { UIInteractions, wait } from '../../../test-utils/ui-interactions.spec'; import { SampleTestData } from '../../../test-utils/sample-test-data.spec'; -import { VirtualGridComponent, NoScrollsComponent, - NoColumnWidthGridComponent, IgxGridDateTimeColumnComponent } from '../../../test-utils/grid-samples.spec'; +import { VirtualGridComponent, NoScrollsComponent, NoColumnWidthGridComponent, IgxGridDateTimeColumnComponent } from '../../../test-utils/grid-samples.spec'; import { GridFunctions } from '../../../test-utils/grid-functions.spec'; import { TestNgZone } from '../../../test-utils/helper-utils.spec'; import { CellType, IGridCellEventArgs, IgxColumnComponent } from 'igniteui-angular/grids/core'; import { HammerGesturesManager, PlatformUtil } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxGrid - Cell component #grid', () => { @@ -40,9 +40,9 @@ describe('IgxGrid - Cell component #grid', () => { expect(firstCell.column.index).toEqual(grid.columnList.first.index); expect(firstCell.row.index).toEqual(grid.rowList.first.index); expect(firstCell.grid).toBe(grid); - expect(firstCell.active).toBeFalse(); - expect(firstCell.selected).toBeFalse(); - expect(firstCell.editMode).toBeFalse(); + expect(firstCell.active).toBe(false); + expect(firstCell.selected).toBe(false); + expect(firstCell.editMode).toBe(false); expect(firstCell.editValue).toBeUndefined(); expect(firstCellElem.nativeElement).toBeDefined(); expect(firstCellElem.nativeElement.textContent).toMatch('1'); @@ -52,11 +52,11 @@ describe('IgxGrid - Cell component #grid', () => { it('selection and selection events', () => { expect(cellElem.nativeElement.getAttribute('aria-selected')).toMatch('false'); - spyOn(grid.selected, 'emit').and.callThrough(); + vi.spyOn(grid.selected, 'emit'); UIInteractions.simulateClickAndSelectEvent(cellElem); const args: IGridCellEventArgs = { cell: grid.getCellByColumn(0, 'ID'), - event: jasmine.anything() as any + event: expect.anything() as any }; fix.detectChanges(); @@ -75,7 +75,7 @@ describe('IgxGrid - Cell component #grid', () => { grid.getColumnByName('ID').editable = true; fix.detectChanges(); - spyOn(grid.selected, 'emit').and.callThrough(); + vi.spyOn(grid.selected, 'emit'); UIInteractions.simulateClickAndSelectEvent(cellElem); fix.detectChanges(); @@ -92,7 +92,7 @@ describe('IgxGrid - Cell component #grid', () => { }); it('Should trigger onCellClick event when click into cell', () => { - spyOn(grid.cellClick, 'emit').and.callThrough(); + vi.spyOn(grid.cellClick, 'emit'); const event = new Event('click'); firstCellElem.nativeElement.dispatchEvent(event); const args: IGridCellEventArgs = { @@ -108,7 +108,7 @@ describe('IgxGrid - Cell component #grid', () => { it('Should trigger doubleClick event', () => { grid.columnList.get(0).editable = true; fix.detectChanges(); - spyOn(grid.doubleClick, 'emit').and.callThrough(); + vi.spyOn(grid.doubleClick, 'emit'); cellElem.triggerEventHandler('dblclick', new Event('dblclick')); fix.detectChanges(); @@ -120,22 +120,22 @@ describe('IgxGrid - Cell component #grid', () => { }); it('Should trigger contextMenu event when right click into cell', () => { - spyOn(grid.contextMenu, 'emit').and.callThrough(); + vi.spyOn(grid.contextMenu, 'emit'); const event = new Event('contextmenu', { bubbles: true }); cellElem.nativeElement.dispatchEvent(event); fix.detectChanges(); expect(grid.contextMenu.emit).toHaveBeenCalledTimes(1); - expect(grid.contextMenu.emit).toHaveBeenCalledWith(jasmine.objectContaining({ - cell: jasmine.anything(), - row: jasmine.anything() + expect(grid.contextMenu.emit).toHaveBeenCalledWith(expect.objectContaining({ + cell: expect.anything(), + row: expect.anything() })); }); it('Should trigger doubleClick event when double click into cell', () => { - spyOn(grid.doubleClick, 'emit').and.callThrough(); + vi.spyOn(grid.doubleClick, 'emit'); const event = new Event('dblclick'); - spyOn(event, 'preventDefault'); + vi.spyOn(event, 'preventDefault'); cellElem.nativeElement.dispatchEvent(event); const args: IGridCellEventArgs = { cell: grid.getCellByColumn(0, 'ID'), @@ -220,15 +220,15 @@ describe('IgxGrid - Cell component #grid', () => { }); it('should not make last column smaller when vertical scrollbar is on the right of last cell', () => { - fix.componentInstance.columns = fix.componentInstance.generateCols(4, '30px'); - fix.componentInstance.data = fix.componentInstance.generateData(10); - fix.detectChanges(); - - const lastColumnCells = grid.columnList.get(grid.columnList.length - 1).cells; - lastColumnCells.forEach((item) => { - expect(item.width).toEqual('30px'); - }); + fix.componentInstance.columns = fix.componentInstance.generateCols(4, '30px'); + fix.componentInstance.data = fix.componentInstance.generateData(10); + fix.detectChanges(); + + const lastColumnCells = grid.columnList.get(grid.columnList.length - 1).cells; + lastColumnCells.forEach((item) => { + expect(item.width).toEqual('30px'); }); + }); it('should not make last column smaller when vertical scrollbar is on the left of last cell', async () => { fix.componentInstance.columns = fix.componentInstance.generateCols(4, '500px'); @@ -275,7 +275,7 @@ describe('IgxGrid - Cell component #grid', () => { })); it('Should not attach doubletap handler for non-iOS', () => { - const addListenerSpy = spyOn(HammerGesturesManager.prototype, 'addEventListener'); + const addListenerSpy = vi.spyOn(HammerGesturesManager.prototype, 'addEventListener'); const platformUtil: PlatformUtil = TestBed.inject(PlatformUtil); const oldIsIOS = platformUtil.isIOS; platformUtil.isIOS = false; @@ -288,7 +288,7 @@ describe('IgxGrid - Cell component #grid', () => { }); it('Should handle doubletap on iOS, trigger doubleClick event', () => { - const addListenerSpy = spyOn(HammerGesturesManager.prototype, 'addEventListener'); + const addListenerSpy = vi.spyOn(HammerGesturesManager.prototype, 'addEventListener'); const platformUtil: PlatformUtil = TestBed.inject(PlatformUtil); const oldIsIOS = platformUtil.isIOS; platformUtil.isIOS = true; @@ -299,15 +299,14 @@ describe('IgxGrid - Cell component #grid', () => { const firstCellElem = grid.gridAPI.get_cell_by_index(0, 'ID'); // should attach 'doubletap' - expect(addListenerSpy.calls.count()).toBeGreaterThan(1); - expect(addListenerSpy).toHaveBeenCalledWith(firstCellElem.nativeElement, 'doubletap', firstCellElem.onDoubleClick, - { cssProps: {} as any }); + expect(vi.mocked(addListenerSpy).mock.calls.length).toBeGreaterThan(1); + expect(addListenerSpy).toHaveBeenCalledWith(firstCellElem.nativeElement, 'doubletap', firstCellElem.onDoubleClick, { cssProps: {} as any }); - spyOn(grid.doubleClick, 'emit').and.callThrough(); + vi.spyOn(grid.doubleClick, 'emit'); const event = { type: 'doubletap', - preventDefault: jasmine.createSpy('preventDefault') + preventDefault: vi.fn() }; firstCellElem.onDoubleClick(event as any); const args: IGridCellEventArgs = { @@ -428,7 +427,8 @@ describe('IgxGrid - Cell component #grid', () => { imports: [IgxGridComponent, IgxColumnComponent] }) export class ConditionalCellStyleTestComponent implements OnInit { - @ViewChild('grid', { static: true }) public grid: IgxGridComponent; + @ViewChild('grid', { static: true }) + public grid: IgxGridComponent; public data: Array; public columns: Array; diff --git a/projects/igniteui-angular/grids/grid/src/column-group.spec.ts b/projects/igniteui-angular/grids/grid/src/column-group.spec.ts index 232dc7f0d15..2faaaf6b978 100644 --- a/projects/igniteui-angular/grids/grid/src/column-group.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/column-group.spec.ts @@ -9,16 +9,10 @@ import { IgxGridHeaderComponent } from 'igniteui-angular/grids/core'; import { GridSummaryFunctions, GridFunctions } from '../../../test-utils/grid-functions.spec'; import { wait } from '../../../test-utils/ui-interactions.spec'; import { DropPosition } from 'igniteui-angular/grids/core'; -import { OneGroupOneColGridComponent, OneGroupThreeColsGridComponent, - BlueWhaleGridComponent, ColumnGroupTestComponent, ColumnGroupFourLevelTestComponent, - ThreeGroupsThreeColumnsGridComponent, - NestedColGroupsGridComponent, StegosaurusGridComponent, - OneColPerGroupGridComponent, NestedColumnGroupsGridComponent, - DynamicGridComponent, NestedColGroupsWithTemplatesGridComponent, - DynamicColGroupsGridComponent, - ColumnGroupHiddenInTemplateComponent} from '../../../test-utils/grid-mch-sample.spec'; +import { OneGroupOneColGridComponent, OneGroupThreeColsGridComponent, BlueWhaleGridComponent, ColumnGroupTestComponent, ColumnGroupFourLevelTestComponent, ThreeGroupsThreeColumnsGridComponent, NestedColGroupsGridComponent, StegosaurusGridComponent, OneColPerGroupGridComponent, NestedColumnGroupsGridComponent, DynamicGridComponent, NestedColGroupsWithTemplatesGridComponent, DynamicColGroupsGridComponent, ColumnGroupHiddenInTemplateComponent } from '../../../test-utils/grid-mch-sample.spec'; import { CellType } from 'igniteui-angular/grids/core'; import { DefaultSortingStrategy, IgxStringFilteringOperand, SortingDirection } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const GRID_COL_THEAD_TITLE_CLASS = 'igx-grid-th__title'; const GRID_COL_GROUP_THEAD_TITLE_CLASS = 'igx-grid-thead__title'; @@ -50,7 +44,7 @@ describe('IgxGrid - multi-column headers #grid', () => { ColumnGroupHiddenInTemplateComponent ] }) - .compileComponents(); + .compileComponents(); })); describe('Initialization and rendering tests: ', () => { @@ -72,8 +66,8 @@ describe('IgxGrid - multi-column headers #grid', () => { const expectedGridHeaderHeight = 151; const headerHeight = grid.nativeElement - .querySelector("igx-grid-header-row") - .getBoundingClientRect().height; + .querySelector("igx-grid-header-row") + .getBoundingClientRect().height; expect(Math.round(headerHeight)).toEqual(expectedGridHeaderHeight); }); @@ -93,9 +87,7 @@ describe('IgxGrid - multi-column headers #grid', () => { const secondSubGroupHeadersDepth = 2; const firstGroup = GridFunctions.getColumnGroupHeaders(fixture)[0]; - testColumnGroupHeaderRendering(firstGroup, firstGroupChildrenCount * columnWidthPx, - gridHeadersDepth * grid.defaultRowHeight, componentInstance.firstGroupTitle, - 'firstGroupColumn', firstGroupChildrenCount); + testColumnGroupHeaderRendering(firstGroup, firstGroupChildrenCount * columnWidthPx, gridHeadersDepth * grid.defaultRowHeight, componentInstance.firstGroupTitle, 'firstGroupColumn', firstGroupChildrenCount); let horizontalScroll = grid.headerContainer.getScroll(); let scrollToNextGroup = firstGroupChildrenCount * columnWidthPx + columnWidthPx; @@ -104,21 +96,12 @@ describe('IgxGrid - multi-column headers #grid', () => { tick(); fixture.detectChanges(); const secondGroup = GridFunctions.getColumnGroupHeaders(fixture)[1]; - testColumnGroupHeaderRendering(secondGroup, - secondGroupChildrenCount * secondSubGroupChildrenCount * columnWidthPx, - gridHeadersDepth * grid.defaultRowHeight, componentInstance.secondGroupTitle, - 'secondSubGroup', 0); + testColumnGroupHeaderRendering(secondGroup, secondGroupChildrenCount * secondSubGroupChildrenCount * columnWidthPx, gridHeadersDepth * grid.defaultRowHeight, componentInstance.secondGroupTitle, 'secondSubGroup', 0); const secondSubGroups = secondGroup.queryAll(By.css('.secondSubGroup')); - testColumnGroupHeaderRendering(secondSubGroups[0], - secondSubGroupChildrenCount * columnWidthPx, - secondSubGroupHeadersDepth * grid.defaultRowHeight, componentInstance.secondSubGroupTitle, - 'secondSubGroupColumn', secondSubGroupChildrenCount); + testColumnGroupHeaderRendering(secondSubGroups[0], secondSubGroupChildrenCount * columnWidthPx, secondSubGroupHeadersDepth * grid.defaultRowHeight, componentInstance.secondSubGroupTitle, 'secondSubGroupColumn', secondSubGroupChildrenCount); - testColumnGroupHeaderRendering(secondSubGroups[1], - secondSubGroupChildrenCount * columnWidthPx, - secondSubGroupHeadersDepth * grid.defaultRowHeight, componentInstance.secondSubGroupTitle, - 'secondSubGroupColumn', secondSubGroupChildrenCount); + testColumnGroupHeaderRendering(secondSubGroups[1], secondSubGroupChildrenCount * columnWidthPx, secondSubGroupHeadersDepth * grid.defaultRowHeight, componentInstance.secondSubGroupTitle, 'secondSubGroupColumn', secondSubGroupChildrenCount); horizontalScroll = grid.headerContainer.getScroll(); scrollToNextGroup = horizontalScroll.scrollLeft + @@ -130,17 +113,13 @@ describe('IgxGrid - multi-column headers #grid', () => { fixture.detectChanges(); const idColumn = fixture.debugElement.query(By.css('.lonelyId')); - testColumnHeaderRendering(idColumn, columnWidthPx, - gridHeadersDepth * grid.defaultRowHeight, componentInstance.idHeaderTitle); + testColumnHeaderRendering(idColumn, columnWidthPx, gridHeadersDepth * grid.defaultRowHeight, componentInstance.idHeaderTitle); const companyNameColumn = GridFunctions.getColumnHeader('CompanyName', fixture); - testColumnHeaderRendering(companyNameColumn, columnWidthPx, - 2 * grid.defaultRowHeight, componentInstance.companyNameTitle); + testColumnHeaderRendering(companyNameColumn, columnWidthPx, 2 * grid.defaultRowHeight, componentInstance.companyNameTitle); const personDetailsColumn = GridFunctions.getColumnGroupHeader('Person Details', fixture); - testColumnGroupHeaderRendering(personDetailsColumn, 2 * columnWidthPx, - 2 * grid.defaultRowHeight, componentInstance.personDetailsTitle, - 'personDetailsColumn', 2); + testColumnGroupHeaderRendering(personDetailsColumn, 2 * columnWidthPx, 2 * grid.defaultRowHeight, componentInstance.personDetailsTitle, 'personDetailsColumn', 2); })); @@ -239,9 +218,7 @@ describe('IgxGrid - multi-column headers #grid', () => { let firstGroupChildrenCount = 1; let firstGroup = GridFunctions.getColumnGroupHeaders(fixture)[0]; - testColumnGroupHeaderRendering(firstGroup, firstGroupChildrenCount * columnWidthPx, - gridHeadersDepth * grid.defaultRowHeight, componentInstance.firstGroupTitle, - 'firstGroupColumn', firstGroupChildrenCount); + testColumnGroupHeaderRendering(firstGroup, firstGroupChildrenCount * columnWidthPx, gridHeadersDepth * grid.defaultRowHeight, componentInstance.firstGroupTitle, 'firstGroupColumn', firstGroupChildrenCount); let allHeaders = GridFunctions.getColumnHeaders(fixture).map(x => x.componentInstance); let firstSixHeaders = allHeaders.slice(0, 6).map(x => x.column.field); @@ -253,9 +230,7 @@ describe('IgxGrid - multi-column headers #grid', () => { firstGroupChildrenCount = 2; firstGroup = GridFunctions.getColumnGroupHeaders(fixture)[0]; - testColumnGroupHeaderRendering(firstGroup, firstGroupChildrenCount * columnWidthPx, - gridHeadersDepth * grid.defaultRowHeight, componentInstance.firstGroupTitle, - 'firstGroupColumn', firstGroupChildrenCount); + testColumnGroupHeaderRendering(firstGroup, firstGroupChildrenCount * columnWidthPx, gridHeadersDepth * grid.defaultRowHeight, componentInstance.firstGroupTitle, 'firstGroupColumn', firstGroupChildrenCount); allHeaders = GridFunctions.getColumnHeaders(fixture).map(x => x.componentInstance); firstSixHeaders = allHeaders.slice(0, 6).map(x => x.column.field); @@ -284,40 +259,31 @@ describe('IgxGrid - multi-column headers #grid', () => { const addressColGroupDepth = 2; // one-level children const addressColGroupChildrenCount = 1; - testColumnGroupHeaderRendering(addressColGroup, parseInt(ci.columnWidth, 10), - addressColGroupDepth * grid.defaultRowHeight, ci.addressColGroupTitle, - 'addressCol', addressColGroupChildrenCount); + testColumnGroupHeaderRendering(addressColGroup, parseInt(ci.columnWidth, 10), addressColGroupDepth * grid.defaultRowHeight, ci.addressColGroupTitle, 'addressCol', addressColGroupChildrenCount); const addressCol = GridFunctions.getColumnHeader('Address', fixture); - testColumnHeaderRendering(addressCol, parseInt(ci.columnWidth, 10), - grid.defaultRowHeight, ci.addressColTitle); + testColumnHeaderRendering(addressCol, parseInt(ci.columnWidth, 10), grid.defaultRowHeight, ci.addressColTitle); const phoneColGroup = GridFunctions.getColumnGroupHeader('Phone Group', fixture); const phoneColGroupDepth = 2; // one-level children const phoneColGroupChildrenCount = 1; - testColumnGroupHeaderRendering(phoneColGroup, parseInt(ci.phoneColWidth, 10), - phoneColGroupDepth * grid.defaultRowHeight, ci.phoneColGroupTitle, - 'phoneCol', phoneColGroupChildrenCount); + testColumnGroupHeaderRendering(phoneColGroup, parseInt(ci.phoneColWidth, 10), phoneColGroupDepth * grid.defaultRowHeight, ci.phoneColGroupTitle, 'phoneCol', phoneColGroupChildrenCount); const phoneCol = GridFunctions.getColumnHeader('Phone', fixture); - testColumnHeaderRendering(phoneCol, parseInt(ci.phoneColWidth, 10), - grid.defaultRowHeight, ci.phoneColTitle); + testColumnHeaderRendering(phoneCol, parseInt(ci.phoneColWidth, 10), grid.defaultRowHeight, ci.phoneColTitle); const faxColGroup = GridFunctions.getColumnGroupHeader('Fax Group', fixture); const faxColGroupDepth = 2; // one-level children const faxColGroupChildrenCount = 1; - testColumnGroupHeaderRendering(faxColGroup, parseInt(ci.faxColWidth, 10), - faxColGroupDepth * grid.defaultRowHeight, ci.faxColGroupTitle, 'faxCol', - faxColGroupChildrenCount); + testColumnGroupHeaderRendering(faxColGroup, parseInt(ci.faxColWidth, 10), faxColGroupDepth * grid.defaultRowHeight, ci.faxColGroupTitle, 'faxCol', faxColGroupChildrenCount); const faxCol = GridFunctions.getColumnHeader('Fax', fixture); - testColumnHeaderRendering(faxCol, parseInt(ci.faxColWidth, 10), - grid.defaultRowHeight, ci.faxColTitle); + testColumnHeaderRendering(faxCol, parseInt(ci.faxColWidth, 10), grid.defaultRowHeight, ci.faxColTitle); }); it('Should render headers correctly when having nested column groups.', () => { @@ -341,7 +307,7 @@ describe('IgxGrid - multi-column headers #grid', () => { ' more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.'; ci.masterColGroupTitle = ci.firstSlaveColGroupTitle = ci.secondSlaveColGroupTitle = ci.addressColTitle = ci.phoneColTitle = - ci.faxColTitle = ci.cityColTitle = title; + ci.faxColTitle = ci.cityColTitle = title; fixture.detectChanges(); NestedColGroupsTests.testHeadersRendering(fixture); }); @@ -592,9 +558,9 @@ describe('IgxGrid - multi-column headers #grid', () => { it('Should not throw exception if multi-column header columns width is set as number', () => { expect(() => { - const cityColumn = grid.getColumnByName('City'); - (cityColumn.width as any) = 55; - fixture.detectChanges(); + const cityColumn = grid.getColumnByName('City'); + (cityColumn.width as any) = 55; + fixture.detectChanges(); }).not.toThrow(); }); @@ -774,20 +740,20 @@ describe('IgxGrid - multi-column headers #grid', () => { }); it('Width should be correct. Column group with three columns. Columns with width in px.', () => { - const columnWidth = '200px'; - componentInstance.columnWidth = columnWidth; - fixture.detectChanges(); + const columnWidth = '200px'; + componentInstance.columnWidth = columnWidth; + fixture.detectChanges(); - const locationColGroup = getColGroup(grid, 'Location'); - const groupWidth = parseInt(columnWidth, 10) * 3; - expect(locationColGroup.width).toBe(groupWidth + 'px'); - const countryColumn = grid.getColumnByName('Country'); - expect(countryColumn.width).toBe(columnWidth); - const regionColumn = grid.getColumnByName('Region'); - expect(regionColumn.width).toBe(columnWidth); - const cityColumn = grid.getColumnByName('City'); - expect(cityColumn.width).toBe(columnWidth); - }); + const locationColGroup = getColGroup(grid, 'Location'); + const groupWidth = parseInt(columnWidth, 10) * 3; + expect(locationColGroup.width).toBe(groupWidth + 'px'); + const countryColumn = grid.getColumnByName('Country'); + expect(countryColumn.width).toBe(columnWidth); + const regionColumn = grid.getColumnByName('Region'); + expect(regionColumn.width).toBe(columnWidth); + const cityColumn = grid.getColumnByName('City'); + expect(cityColumn.width).toBe(columnWidth); + }); it('Width should be correct. Column group with three columns. Columns with width in percent.', () => { const columnWidth = '20%'; @@ -921,23 +887,23 @@ describe('IgxGrid - multi-column headers #grid', () => { }); it('column hiding - Verify when 1 child column and 1 group are hidden, the Grouped column would be hidden as well.', () => { - testGroupsAndColumns(7, 11, fixture); + testGroupsAndColumns(7, 11, fixture); - // Hide 2 columns in the group - grid.getColumnByName('CompanyName').hidden = true; - fixture.detectChanges(); - getColGroup(grid, 'Person Details').hidden = true; - fixture.detectChanges(); + // Hide 2 columns in the group + grid.getColumnByName('CompanyName').hidden = true; + fixture.detectChanges(); + getColGroup(grid, 'Person Details').hidden = true; + fixture.detectChanges(); - testGroupsAndColumns(5, 8, fixture); - expect(getColGroup(grid, 'General Information').hidden).toEqual(true); + testGroupsAndColumns(5, 8, fixture); + expect(getColGroup(grid, 'General Information').hidden).toEqual(true); - // Show the group - getColGroup(grid, 'Person Details').hidden = false; - fixture.detectChanges(); - testGroupsAndColumns(7, 10, fixture); - expect(getColGroup(grid, 'General Information').hidden).toEqual(false); - }); + // Show the group + getColGroup(grid, 'Person Details').hidden = false; + fixture.detectChanges(); + testGroupsAndColumns(7, 10, fixture); + expect(getColGroup(grid, 'General Information').hidden).toEqual(false); + }); }); describe('API methods tests ', () => { @@ -1092,7 +1058,7 @@ describe('IgxGrid - multi-column headers #grid', () => { const ci = fixture.componentInstance; grid = ci.grid; - spyOn(grid.columnInit, 'emit').and.callThrough(); + vi.spyOn(grid.columnInit, 'emit'); fixture.detectChanges(); const colsCount = 4; const colGroupsCount = 3; @@ -1106,7 +1072,7 @@ describe('IgxGrid - multi-column headers #grid', () => { grid = componentInstance.grid; fixture.detectChanges(); - spyOn(grid.columnInit, 'emit').and.callThrough(); + vi.spyOn(grid.columnInit, 'emit'); componentInstance.mchCount.push({}); fixture.detectChanges(); const colsCount = grid.unpinnedColumns.length; // all @@ -1359,7 +1325,7 @@ describe('IgxGrid - multi-column headers #grid', () => { const ci = fixture.componentInstance; grid = ci.grid; const genInfoCols = [ci.genInfoColGroup, ci.companyNameCol, - ci.contactNameCol, ci.contactTitleCol]; + ci.contactNameCol, ci.contactTitleCol]; const locCols = [ci.locationColGroup, ci.countryCol, ci.regionCol, ci.cityCol]; const contactInfoCols = [ci.contactInfoColGroup, ci.phoneCol, ci.faxCol, ci.postalCodeCol]; @@ -1408,57 +1374,57 @@ describe('IgxGrid - multi-column headers #grid', () => { const ci = fixture.componentInstance; grid = ci.grid; const genInfoAndLocCols = [ci.genInfoColGroup, ci.companyNameCol, - ci.contactNameCol, ci.contactTitleCol, ci.locationColGroup, ci.countryCol, - ci.regionCol, ci.cityCol]; + ci.contactNameCol, ci.contactTitleCol, ci.locationColGroup, ci.countryCol, + ci.regionCol, ci.cityCol]; // moving last to be first grid.moveColumn(ci.postalCodeCol, ci.phoneCol, DropPosition.BeforeDropTarget); tick(); fixture.detectChanges(); testColumnsOrder(genInfoAndLocCols.concat([ci.contactInfoColGroup, - ci.postalCodeCol, ci.phoneCol, ci.faxCol])); + ci.postalCodeCol, ci.phoneCol, ci.faxCol])); // moving first to be last grid.moveColumn(ci.postalCodeCol, ci.faxCol); tick(); fixture.detectChanges(); testColumnsOrder(genInfoAndLocCols.concat([ci.contactInfoColGroup, - ci.phoneCol, ci.faxCol, ci.postalCodeCol])); + ci.phoneCol, ci.faxCol, ci.postalCodeCol])); // moving inner to be last grid.moveColumn(ci.faxCol, ci.postalCodeCol); tick(); fixture.detectChanges(); testColumnsOrder(genInfoAndLocCols.concat([ci.contactInfoColGroup, - ci.phoneCol, ci.postalCodeCol, ci.faxCol])); + ci.phoneCol, ci.postalCodeCol, ci.faxCol])); // moving inner to be first grid.moveColumn(ci.postalCodeCol, ci.phoneCol, DropPosition.BeforeDropTarget); tick(); fixture.detectChanges(); testColumnsOrder(genInfoAndLocCols.concat([ci.contactInfoColGroup, - ci.postalCodeCol, ci.phoneCol, ci.faxCol])); + ci.postalCodeCol, ci.phoneCol, ci.faxCol])); // moving to the sample spot, no change expected grid.moveColumn(ci.postalCodeCol, ci.postalCodeCol); tick(); fixture.detectChanges(); testColumnsOrder(genInfoAndLocCols.concat([ci.contactInfoColGroup, - ci.postalCodeCol, ci.phoneCol, ci.faxCol])); + ci.postalCodeCol, ci.phoneCol, ci.faxCol])); // moving column to the place of its column group, no change expected grid.moveColumn(ci.postalCodeCol, ci.contactInfoColGroup); tick(); fixture.detectChanges(); testColumnsOrder(genInfoAndLocCols.concat([ci.contactInfoColGroup, - ci.postalCodeCol, ci.phoneCol, ci.faxCol])); + ci.postalCodeCol, ci.phoneCol, ci.faxCol])); //// moving column to the place of a column group, no change expected grid.moveColumn(ci.postalCodeCol, ci.genInfoColGroup); tick(); fixture.detectChanges(); testColumnsOrder(genInfoAndLocCols.concat([ci.contactInfoColGroup, - ci.postalCodeCol, ci.phoneCol, ci.faxCol])); + ci.postalCodeCol, ci.phoneCol, ci.faxCol])); })); it('Should move columns and groups. Two level column groups.', fakeAsync(() => { @@ -1472,14 +1438,14 @@ describe('IgxGrid - multi-column headers #grid', () => { tick(); fixture.detectChanges(); testColumnsOrder([ci.contactInfoColGroup, ci.phoneCol, ci.locationColGroup, ci.countryCol, - ci.genInfoColGroup, ci.companyNameCol, ci.cityCol]); + ci.genInfoColGroup, ci.companyNameCol, ci.cityCol]); // moving a three-level col grid.moveColumn(ci.cityCol, ci.contactInfoColGroup, DropPosition.BeforeDropTarget); tick(); fixture.detectChanges(); const colsOrder = [ci.cityCol, ci.contactInfoColGroup, ci.phoneCol, - ci.locationColGroup, ci.countryCol, ci.genInfoColGroup, ci.companyNameCol]; + ci.locationColGroup, ci.countryCol, ci.genInfoColGroup, ci.companyNameCol]; testColumnsOrder(colsOrder); // moving between different groups, hould stay the same @@ -1679,8 +1645,7 @@ describe('IgxGrid - multi-column headers #grid', () => { fixture.detectChanges(); // Filter column - grid.filter('ContactTitle', 'Accounting Manager', - IgxStringFilteringOperand.instance().condition('equals'), true); + grid.filter('ContactTitle', 'Accounting Manager', IgxStringFilteringOperand.instance().condition('equals'), true); tick(); fixture.detectChanges(); expect(grid.rowList.length).toEqual(2); @@ -1775,8 +1740,7 @@ const getColGroup = (grid: IgxGridComponent, headerName: string): IgxColumnGroup }; // tests column and column group header rendering -const testColumnGroupHeaderRendering = (column: DebugElement, width: number, height: number, - title: string, descendentColumnCssClass?: string, descendentColumnCount?: number) => { +const testColumnGroupHeaderRendering = (column: DebugElement, width: number, height: number, title: string, descendentColumnCssClass?: string, descendentColumnCount?: number) => { expect(column.nativeElement.offsetHeight).toBe(height); expect(column.nativeElement.offsetWidth).toBe(width); @@ -1788,15 +1752,14 @@ const testColumnGroupHeaderRendering = (column: DebugElement, width: number, hei const colGroupDirectChildren = column.children .filter(c => c.nativeElement.classList.contains(GRID_COL_GROUP_THEAD_GROUP_CLASS))[0] .children.filter(c => { - const header = c.query(By.directive(IgxGridHeaderComponent)); - return header.nativeElement.classList.contains(descendentColumnCssClass); - }); + const header = c.query(By.directive(IgxGridHeaderComponent)); + return header.nativeElement.classList.contains(descendentColumnCssClass); + }); expect(colGroupDirectChildren.length).toBe(descendentColumnCount); }; -const testColumnHeaderRendering = (column: DebugElement, width: number, height: number, - title: string) => { +const testColumnHeaderRendering = (column: DebugElement, width: number, height: number, title: string) => { expect(column.nativeElement.offsetHeight).toBe(height); expect(column.nativeElement.offsetWidth).toBe(width); @@ -1883,27 +1846,21 @@ class NestedColGroupsTests { const firstSlaveColGroupChildrenCount = 2; const firstSlaveColGroupWidth = parseInt(ci.columnWidth, 10) + parseInt(ci.phoneColWidth, 10); - testColumnGroupHeaderRendering(firstSlaveColGroup, firstSlaveColGroupWidth, - firstSlaveColGroupDepth * grid.defaultRowHeight, - ci.firstSlaveColGroupTitle, 'firstSlaveChild', firstSlaveColGroupChildrenCount); + testColumnGroupHeaderRendering(firstSlaveColGroup, firstSlaveColGroupWidth, firstSlaveColGroupDepth * grid.defaultRowHeight, ci.firstSlaveColGroupTitle, 'firstSlaveChild', firstSlaveColGroupChildrenCount); const secondSlaveColGroup = fixture.debugElement.query(By.css('.secondSlaveColGroup')); const secondSlaveColGroupDepth = 2; // one-level children const secondSlaveColGroupChildrenCount = 2; const secondSlaveColGroupWidth = parseInt(ci.faxColWidth, 10) + parseInt(ci.cityColWidth, 10); - testColumnGroupHeaderRendering(secondSlaveColGroup, secondSlaveColGroupWidth, - secondSlaveColGroupDepth * grid.defaultRowHeight, - ci.secondSlaveColGroupTitle, 'secondSlaveChild', secondSlaveColGroupChildrenCount); + testColumnGroupHeaderRendering(secondSlaveColGroup, secondSlaveColGroupWidth, secondSlaveColGroupDepth * grid.defaultRowHeight, ci.secondSlaveColGroupTitle, 'secondSlaveChild', secondSlaveColGroupChildrenCount); const masterColGroup = fixture.debugElement.query(By.css('.masterColGroup')); const masterColGroupWidth = firstSlaveColGroupWidth + secondSlaveColGroupWidth; const masterSlaveColGroupDepth = 3; const masterColGroupChildrenCount = 0; - testColumnGroupHeaderRendering(masterColGroup, masterColGroupWidth, - masterSlaveColGroupDepth * grid.defaultRowHeight, ci.masterColGroupTitle, - 'slaveColGroup', masterColGroupChildrenCount); + testColumnGroupHeaderRendering(masterColGroup, masterColGroupWidth, masterSlaveColGroupDepth * grid.defaultRowHeight, ci.masterColGroupTitle, 'slaveColGroup', masterColGroupChildrenCount); } } diff --git a/projects/igniteui-angular/grids/grid/src/column-hiding.spec.ts b/projects/igniteui-angular/grids/grid/src/column-hiding.spec.ts index 03def055f9b..74a53d5039d 100644 --- a/projects/igniteui-angular/grids/grid/src/column-hiding.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/column-hiding.spec.ts @@ -9,6 +9,7 @@ import { GridFunctions } from '../../../test-utils/grid-functions.spec'; import { GridSelectionMode, ColumnDisplayOrder, IgxColumnActionsComponent } from 'igniteui-angular/grids/core'; import { ControlsFunction } from '../../../test-utils/controls-functions.spec'; import { SortingDirection } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('Column Hiding UI #grid', () => { @@ -113,8 +114,8 @@ describe('Column Hiding UI #grid', () => { }); it('"hiddenColumnsCount" reflects properly the number of hidden columns.', fakeAsync(() => { - spyOn(grid.columnVisibilityChanged, 'emit'); - spyOn(grid.columnVisibilityChanging, 'emit'); + vi.spyOn(grid.columnVisibilityChanged, 'emit'); + vi.spyOn(grid.columnVisibilityChanging, 'emit'); expect(fix.componentInstance.hiddenColumnsCount).toBe(3); @@ -144,39 +145,35 @@ describe('Column Hiding UI #grid', () => { }); it('columnToggled, columnVisibilityChanged, onColumnVisibilityChanging event is fired on toggling checkboxes.', () => { - spyOn(columnChooser.columnToggled, 'emit'); - spyOn(grid.columnVisibilityChanged, 'emit'); - spyOn(grid.columnVisibilityChanging, 'emit'); + vi.spyOn(columnChooser.columnToggled, 'emit'); + vi.spyOn(grid.columnVisibilityChanged, 'emit'); + vi.spyOn(grid.columnVisibilityChanging, 'emit'); GridFunctions.clickColumnChooserItem(columnChooserElement, 'ReleaseDate'); expect(columnChooser.columnToggled.emit).toHaveBeenCalledTimes(1); - expect(columnChooser.columnToggled.emit).toHaveBeenCalledWith( - { column: grid.getColumnByName('ReleaseDate'), checked: false }); + expect(columnChooser.columnToggled.emit).toHaveBeenCalledWith({ column: grid.getColumnByName('ReleaseDate'), checked: false }); expect(grid.columnVisibilityChanging.emit).toHaveBeenCalledTimes(1); expect(grid.columnVisibilityChanged.emit).toHaveBeenCalledTimes(1); GridFunctions.clickColumnChooserItem(columnChooserElement, 'ReleaseDate'); expect(columnChooser.columnToggled.emit).toHaveBeenCalledTimes(2); - expect(columnChooser.columnToggled.emit).toHaveBeenCalledWith( - { column: grid.getColumnByName('ReleaseDate'), checked: true }); + expect(columnChooser.columnToggled.emit).toHaveBeenCalledWith({ column: grid.getColumnByName('ReleaseDate'), checked: true }); expect(grid.columnVisibilityChanging.emit).toHaveBeenCalledTimes(2); expect(grid.columnVisibilityChanged.emit).toHaveBeenCalledTimes(2); GridFunctions.clickColumnChooserItem(columnChooserElement, 'Downloads'); expect(columnChooser.columnToggled.emit).toHaveBeenCalledTimes(3); - expect(columnChooser.columnToggled.emit).toHaveBeenCalledWith( - { column: grid.getColumnByName('Downloads'), checked: true }); + expect(columnChooser.columnToggled.emit).toHaveBeenCalledWith({ column: grid.getColumnByName('Downloads'), checked: true }); expect(grid.columnVisibilityChanging.emit).toHaveBeenCalledTimes(3); expect(grid.columnVisibilityChanged.emit).toHaveBeenCalledTimes(3); GridFunctions.clickColumnChooserItem(columnChooserElement, 'Downloads'); expect(columnChooser.columnToggled.emit).toHaveBeenCalledTimes(4); - expect(columnChooser.columnToggled.emit).toHaveBeenCalledWith( - { column: grid.getColumnByName('Downloads'), checked: false }); + expect(columnChooser.columnToggled.emit).toHaveBeenCalledWith({ column: grid.getColumnByName('Downloads'), checked: false }); expect(grid.columnVisibilityChanging.emit).toHaveBeenCalledTimes(4); expect(grid.columnVisibilityChanged.emit).toHaveBeenCalledTimes(4); }); @@ -210,8 +207,8 @@ describe('Column Hiding UI #grid', () => { }); it('reflects properly grid column hidden value changes.', () => { - spyOn(grid.columnVisibilityChanged, 'emit'); - spyOn(grid.columnVisibilityChanging, 'emit'); + vi.spyOn(grid.columnVisibilityChanged, 'emit'); + vi.spyOn(grid.columnVisibilityChanging, 'emit'); const name = 'ReleaseDate'; verifyCheckbox(name, true, false, columnChooserElement); @@ -264,14 +261,14 @@ describe('Column Hiding UI #grid', () => { GridFunctions.clickColumnChooserItem(columnChooserElement, name); fix.detectChanges(); - expect(GridFunctions.getColumnChooserItemInput(checkbox).checked).toBe(true, 'Checkbox is not checked!'); + expect(GridFunctions.getColumnChooserItemInput(checkbox).checked, 'Checkbox is not checked!').toBe(true); ControlsFunction.verifyButtonIsDisabled(showAll); ControlsFunction.verifyButtonIsDisabled(hideAll, false); GridFunctions.clickColumnChooserItem(columnChooserElement, name); fix.detectChanges(); - expect(GridFunctions.getColumnChooserItemInput(checkbox).checked).toBe(false, 'Checkbox is not unchecked!'); + expect(GridFunctions.getColumnChooserItemInput(checkbox).checked, 'Checkbox is not unchecked!').toBe(false); ControlsFunction.verifyButtonIsDisabled(showAll, false); ControlsFunction.verifyButtonIsDisabled(hideAll); @@ -448,8 +445,8 @@ describe('Column Hiding UI #grid', () => { })); it('- Hide All button operates over the filtered in columns only', fakeAsync(() => { - spyOn(grid.columnVisibilityChanged, 'emit'); - spyOn(grid.columnVisibilityChanging, 'emit'); + vi.spyOn(grid.columnVisibilityChanged, 'emit'); + vi.spyOn(grid.columnVisibilityChanging, 'emit'); grid.columnList.get(1).disableHiding = false; columnChooser.filterCriteria = 're'; @@ -492,7 +489,7 @@ describe('Column Hiding UI #grid', () => { tick(); fix.detectChanges(); - expect(columnChooser.filterCriteria).toBe('', 'Filter criteria is not empty string!'); + expect(columnChooser.filterCriteria, 'Filter criteria is not empty string!').toBe(''); expect(GridFunctions.getColumnChooserItemInput(checkbox).checked).toBe(false); checkbox = GridFunctions.getColumnChooserItemElement(columnChooserElement, 'ID'); expect(GridFunctions.getColumnChooserItemInput(checkbox).checked).toBe(true); @@ -518,7 +515,8 @@ describe('Column Hiding UI #grid', () => { }); fix.detectChanges(); - let fixEl = fix.nativeElement; let gridEl = grid.nativeElement; + let fixEl = fix.nativeElement; + let gridEl = grid.nativeElement; let tHeadItems = fixEl.querySelector('igx-grid-header-group'); let gridRows = fixEl.querySelector('igx-grid-row'); const paging = fixEl.querySelector('.igx-paginator'); @@ -556,8 +554,8 @@ describe('Column Hiding UI #grid', () => { })); it('- Show All button operates over the filtered in columns only', fakeAsync(() => { - spyOn(grid.columnVisibilityChanged, 'emit'); - spyOn(grid.columnVisibilityChanging, 'emit'); + vi.spyOn(grid.columnVisibilityChanged, 'emit'); + vi.spyOn(grid.columnVisibilityChanging, 'emit'); grid.columnList.get(1).disableHiding = false; fix.detectChanges(); @@ -606,7 +604,7 @@ describe('Column Hiding UI #grid', () => { fix.detectChanges(); tick(); - expect(columnChooser.filterCriteria).toBe('', 'Filter criteria is not empty string!'); + expect(columnChooser.filterCriteria, 'Filter criteria is not empty string!').toBe(''); checkbox = GridFunctions.getColumnChooserItemElement(columnChooserElement, 'ID'); expect(GridFunctions.getColumnChooserItemInput(checkbox).checked).toBe(true); @@ -630,18 +628,18 @@ describe('Column Hiding UI #grid', () => { fix.detectChanges(); ControlsFunction.verifyButtonIsDisabled(showAll.nativeElement); - expect(grid.columnList.get(2).hidden).toBe(false, 'Downloads column is not hidden!'); + expect(grid.columnList.get(2).hidden, 'Downloads column is not hidden!').toBe(false); UIInteractions.triggerInputEvent(filterInput, ''); fix.detectChanges(); ControlsFunction.verifyButtonIsDisabled(showAll.nativeElement); - expect(grid.columnList.get(0).hidden).toBe(false, 'ID column is not shown!'); + expect(grid.columnList.get(0).hidden, 'ID column is not shown!').toBe(false); GridFunctions.clickColumnChooserItem(columnChooserElement, 'ID'); fix.detectChanges(); ControlsFunction.verifyButtonIsDisabled(showAll.nativeElement, false); - expect(grid.columnList.get(0).hidden).toBe(true, 'ID column is not hidden!'); + expect(grid.columnList.get(0).hidden, 'ID column is not hidden!').toBe(true); }); it('height can be controlled via columnsAreaMaxHeight input.', () => { @@ -692,7 +690,7 @@ describe('Column Hiding UI #grid', () => { grid = fix.componentInstance.grid; columnChooser = fix.componentInstance.chooser; columnChooserElement = GridFunctions.getColumnHidingElement(fix); - }); + }); it('indents columns according to their level.', () => { const items = GridFunctions.getColumnChooserItems(columnChooserElement); diff --git a/projects/igniteui-angular/grids/grid/src/column-moving.spec.ts b/projects/igniteui-angular/grids/grid/src/column-moving.spec.ts index 7c928783665..0b649adb2c8 100644 --- a/projects/igniteui-angular/grids/grid/src/column-moving.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/column-moving.spec.ts @@ -5,16 +5,12 @@ import { By } from '@angular/platform-browser'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxColumnComponent, IgxColumnGroupComponent } from 'igniteui-angular/grids/core'; import { IgxInputDirective } from 'igniteui-angular/input-group'; -import { - MovableColumnsComponent, - MovableTemplatedColumnsComponent, - MovableColumnsLargeComponent, - MultiColumnHeadersComponent - } from '../../../test-utils/grid-samples.spec'; +import { MovableColumnsComponent, MovableTemplatedColumnsComponent, MovableColumnsLargeComponent, MultiColumnHeadersComponent } from '../../../test-utils/grid-samples.spec'; import { UIInteractions, wait } from '../../../test-utils/ui-interactions.spec'; import { IgxGridComponent } from './grid.component'; import { GridSelectionFunctions, GridFunctions } from '../../../test-utils/grid-functions.spec'; import { ColumnType, SortingDirection } from 'igniteui-angular/core'; +import { describe, it, test, expect, beforeEach, vi } from 'vitest'; describe('IgxGrid - Column Moving #grid', () => { const CELL_CSS_CLASS = '.igx-grid__td'; @@ -22,7 +18,8 @@ describe('IgxGrid - Column Moving #grid', () => { const COLUMN_GROUP_HEADER_CLASS = '.igx-grid-thead__title'; const COLUMN_RESIZE_CLASS = '.igx-grid-th__resize-line'; - let fixture; let grid: IgxGridComponent; + let fixture; + let grid: IgxGridComponent; beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ @@ -117,7 +114,7 @@ describe('IgxGrid - Column Moving #grid', () => { let columnsList = grid.columns; const column = columnsList[0] as IgxColumnComponent; - spyOn(grid.columnMovingEnd, 'emit').and.callThrough(); + vi.spyOn(grid.columnMovingEnd, 'emit'); column.move(2); tick(); @@ -496,8 +493,10 @@ describe('IgxGrid - Column Moving #grid', () => { expect(columnsList[2].field).toEqual('LastName'); })); - it('Should preserve filtering after columns are reordered.', async () => { - pending('This scenario need to be reworked with new Filtering row'); + it.skip('Should preserve filtering after columns are reordered.', async () => { + // TODO: vitest-migration: The pending() function was converted to a skipped test (`it.skip`). See: https://vitest.dev/api/vi.html#it-skip + // pending('This scenario need to be reworked with new Filtering row'); + ; fixture.componentInstance.isFilterable = true; fixture.detectChanges(); @@ -953,7 +952,7 @@ describe('IgxGrid - Column Moving #grid', () => { fixture.detectChanges(); const cell = grid.gridAPI.get_cell_by_index(25, 'Phone'); - const selectedData = [{ Phone: '40.32.21.21'}]; + const selectedData = [{ Phone: '40.32.21.21' }]; UIInteractions.simulateClickAndSelectEvent(cell); fixture.detectChanges(); @@ -987,7 +986,7 @@ describe('IgxGrid - Column Moving #grid', () => { await wait(100); fixture.detectChanges(); - const newSelectedData = [{Country: 'France'}]; + const newSelectedData = [{ Country: 'France' }]; GridSelectionFunctions.verifySelectedRange(grid, 25, 25, 9, 9); expect(grid.getSelectedData()).toEqual(newSelectedData); })); @@ -1897,7 +1896,7 @@ describe('IgxGrid - Column Moving #grid', () => { fixture.detectChanges(); GridSelectionFunctions.verifySelectedRange(grid, 0, 0, 2, 2); - expect(grid.getSelectedData()).toEqual([{CompanyName: 'Alfreds Futterkiste' }]); + expect(grid.getSelectedData()).toEqual([{ CompanyName: 'Alfreds Futterkiste' }]); // step 3 - navigate right and verify cell selection is updated const cellEl = fixture.debugElement.queryAll(By.css(CELL_CSS_CLASS))[2]; @@ -1907,7 +1906,7 @@ describe('IgxGrid - Column Moving #grid', () => { fixture.detectChanges(); GridSelectionFunctions.verifySelectedRange(grid, 0, 0, 3, 3); - expect(grid.getSelectedData()).toEqual([{ContactName: 'Maria Anders' }]); + expect(grid.getSelectedData()).toEqual([{ ContactName: 'Maria Anders' }]); }); it('MCH - should pin only top level columns.', (async () => { diff --git a/projects/igniteui-angular/grids/grid/src/column-pinning.spec.ts b/projects/igniteui-angular/grids/grid/src/column-pinning.spec.ts index f2b3ede7e1f..12b2b8efbf2 100644 --- a/projects/igniteui-angular/grids/grid/src/column-pinning.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/column-pinning.spec.ts @@ -3,15 +3,12 @@ import { DebugElement } from '@angular/core'; import { TestBed, waitForAsync, ComponentFixture } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxGridComponent } from './grid.component'; -import { - ColumnPinningTestComponent, - ColumnGroupsPinningTestComponent, - ColumnPinningWithTemplateTestComponent -} from '../../../test-utils/grid-base-components.spec'; +import { ColumnPinningTestComponent, ColumnGroupsPinningTestComponent, ColumnPinningWithTemplateTestComponent } from '../../../test-utils/grid-base-components.spec'; import { GridFunctions } from '../../../test-utils/grid-functions.spec'; import { ControlsFunction } from '../../../test-utils/controls-functions.spec'; import { wait } from '../../../test-utils/ui-interactions.spec'; import { IgxColumnActionsComponent } from 'igniteui-angular/grids/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('Column Pinning UI #grid', () => { let fix: ComponentFixture; @@ -143,80 +140,68 @@ describe('Column Pinning UI #grid', () => { }); it('columnPin event is fired on toggling checkboxes.', waitForAsync(() => { - spyOn(grid.columnPin, 'emit').and.callThrough(); - spyOn(grid.columnPinned, 'emit').and.callThrough(); + vi.spyOn(grid.columnPin, 'emit'); + vi.spyOn(grid.columnPinned, 'emit'); GridFunctions.clickColumnChooserItem(columnChooserElement, 'ReleaseDate'); fix.detectChanges(); expect(grid.columnPin.emit).toHaveBeenCalledTimes(1); - expect(grid.columnPin.emit).toHaveBeenCalledWith( - { column: grid.getColumnByName('ReleaseDate'), insertAtIndex: 0, isPinned: false, cancel: false }); + expect(grid.columnPin.emit).toHaveBeenCalledWith({ column: grid.getColumnByName('ReleaseDate'), insertAtIndex: 0, isPinned: false, cancel: false }); expect(grid.columnPinned.emit).toHaveBeenCalledTimes(1); - expect(grid.columnPinned.emit).toHaveBeenCalledWith( - { column: grid.getColumnByName('ReleaseDate'), insertAtIndex: 0, isPinned: true }); + expect(grid.columnPinned.emit).toHaveBeenCalledWith({ column: grid.getColumnByName('ReleaseDate'), insertAtIndex: 0, isPinned: true }); GridFunctions.clickColumnChooserItem(columnChooserElement, 'Downloads'); fix.detectChanges(); expect(grid.columnPin.emit).toHaveBeenCalledTimes(2); - expect(grid.columnPin.emit).toHaveBeenCalledWith( - { column: grid.getColumnByName('Downloads'), insertAtIndex: 1, isPinned: false, cancel: false }); + expect(grid.columnPin.emit).toHaveBeenCalledWith({ column: grid.getColumnByName('Downloads'), insertAtIndex: 1, isPinned: false, cancel: false }); expect(grid.columnPinned.emit).toHaveBeenCalledTimes(2); - expect(grid.columnPinned.emit).toHaveBeenCalledWith( - { column: grid.getColumnByName('Downloads'), insertAtIndex: 1, isPinned: true }); + expect(grid.columnPinned.emit).toHaveBeenCalledWith({ column: grid.getColumnByName('Downloads'), insertAtIndex: 1, isPinned: true }); GridFunctions.clickColumnChooserItem(columnChooserElement, 'ReleaseDate'); fix.detectChanges(); // When unpinning columns columnPin event should be fired expect(grid.columnPin.emit).toHaveBeenCalledTimes(3); - expect(grid.columnPin.emit).toHaveBeenCalledWith( - { column: grid.getColumnByName('ReleaseDate'), insertAtIndex: 3, isPinned: true, cancel: false }); + expect(grid.columnPin.emit).toHaveBeenCalledWith({ column: grid.getColumnByName('ReleaseDate'), insertAtIndex: 3, isPinned: true, cancel: false }); expect(grid.columnPinned.emit).toHaveBeenCalledTimes(3); - expect(grid.columnPinned.emit).toHaveBeenCalledWith( - { column: grid.getColumnByName('ReleaseDate'), insertAtIndex: 3, isPinned: false }); + expect(grid.columnPinned.emit).toHaveBeenCalledWith({ column: grid.getColumnByName('ReleaseDate'), insertAtIndex: 3, isPinned: false }); GridFunctions.clickColumnChooserItem(columnChooserElement, 'Downloads'); fix.detectChanges(); expect(grid.columnPin.emit).toHaveBeenCalledTimes(4); - expect(grid.columnPin.emit).toHaveBeenCalledWith( - { column: grid.getColumnByName('Downloads'), insertAtIndex: 2, isPinned: true, cancel: false }); + expect(grid.columnPin.emit).toHaveBeenCalledWith({ column: grid.getColumnByName('Downloads'), insertAtIndex: 2, isPinned: true, cancel: false }); expect(grid.columnPinned.emit).toHaveBeenCalledTimes(4); - expect(grid.columnPinned.emit).toHaveBeenCalledWith( - { column: grid.getColumnByName('Downloads'), insertAtIndex: 2, isPinned: false }); + expect(grid.columnPinned.emit).toHaveBeenCalledWith({ column: grid.getColumnByName('Downloads'), insertAtIndex: 2, isPinned: false }); GridFunctions.clickColumnChooserItem(columnChooserElement, 'ProductName'); fix.detectChanges(); expect(grid.columnPin.emit).toHaveBeenCalledTimes(5); - expect(grid.columnPin.emit).toHaveBeenCalledWith( - { column: grid.getColumnByName('ProductName'), insertAtIndex: 0, isPinned: false, cancel: false }); + expect(grid.columnPin.emit).toHaveBeenCalledWith({ column: grid.getColumnByName('ProductName'), insertAtIndex: 0, isPinned: false, cancel: false }); expect(grid.columnPinned.emit).toHaveBeenCalledTimes(5); - expect(grid.columnPinned.emit).toHaveBeenCalledWith( - { column: grid.getColumnByName('ProductName'), insertAtIndex: 0, isPinned: true }); + expect(grid.columnPinned.emit).toHaveBeenCalledWith({ column: grid.getColumnByName('ProductName'), insertAtIndex: 0, isPinned: true }); })); it('columnPin event should fire when pinning and unpining using api', waitForAsync(() => { - spyOn(grid.columnPin, 'emit').and.callThrough(); - spyOn(grid.columnPinned, 'emit').and.callThrough(); + vi.spyOn(grid.columnPin, 'emit'); + vi.spyOn(grid.columnPinned, 'emit'); grid.columnList.get(0).pin(); expect(grid.columnPin.emit).toHaveBeenCalledTimes(1); - expect(grid.columnPin.emit).toHaveBeenCalledWith( - { column: grid.getColumnByName('ID'), insertAtIndex: 0, isPinned: false, cancel: false }); + expect(grid.columnPin.emit).toHaveBeenCalledWith({ column: grid.getColumnByName('ID'), insertAtIndex: 0, isPinned: false, cancel: false }); expect(grid.columnPinned.emit).toHaveBeenCalledTimes(1); - expect(grid.columnPinned.emit).toHaveBeenCalledWith( - { column: grid.getColumnByName('ID'), insertAtIndex: 0, isPinned: true }); + expect(grid.columnPinned.emit).toHaveBeenCalledWith({ column: grid.getColumnByName('ID'), insertAtIndex: 0, isPinned: true }); // columnPin should not be fired if column is already pinned grid.columnList.get(0).pin(); @@ -227,12 +212,10 @@ describe('Column Pinning UI #grid', () => { grid.columnList.get(0).unpin(); expect(grid.columnPin.emit).toHaveBeenCalledTimes(2); - expect(grid.columnPin.emit).toHaveBeenCalledWith( - { column: grid.getColumnByName('ID'), insertAtIndex: 0, isPinned: true, cancel: false }); + expect(grid.columnPin.emit).toHaveBeenCalledWith({ column: grid.getColumnByName('ID'), insertAtIndex: 0, isPinned: true, cancel: false }); expect(grid.columnPinned.emit).toHaveBeenCalledTimes(2); - expect(grid.columnPinned.emit).toHaveBeenCalledWith( - { column: grid.getColumnByName('ID'), insertAtIndex: 0, isPinned: false }); + expect(grid.columnPinned.emit).toHaveBeenCalledWith({ column: grid.getColumnByName('ID'), insertAtIndex: 0, isPinned: false }); })); it('does pin columns if unpinned area width will become less than the defined minimum.', () => { @@ -281,9 +264,7 @@ describe('Column Pinning UI #grid', () => { if (index === grid.unpinnedColumns.length - 1) { return; } - expect( - column.index < grid.unpinnedColumns[index + 1].index - ).toBe(true); + expect(column.index < grid.unpinnedColumns[index + 1].index).toBe(true); }); }); diff --git a/projects/igniteui-angular/grids/grid/src/column-resizing.spec.ts b/projects/igniteui-angular/grids/grid/src/column-resizing.spec.ts index 3b65edeacba..d513c19c5e0 100644 --- a/projects/igniteui-angular/grids/grid/src/column-resizing.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/column-resizing.spec.ts @@ -14,6 +14,7 @@ import { IgxColumnResizerDirective } from 'igniteui-angular/grids/core'; import { ɵSize } from 'igniteui-angular/core'; import { IgxAvatarComponent } from 'igniteui-angular/avatar'; import { Calendar } from 'igniteui-angular/calendar'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxGrid - Deferred Column Resizing #grid', () => { @@ -143,13 +144,13 @@ describe('IgxGrid - Deferred Column Resizing #grid', () => { const resizer = GridFunctions.getResizer(fixture); const resizerDirective = resizer.componentInstance.resizer as IgxColumnResizerDirective; - const leftSetterSpy = spyOnProperty(resizerDirective, 'left', 'set').and.callThrough(); + const leftSetterSpy = vi.spyOn(resizerDirective, 'left', 'set'); UIInteractions.simulateMouseEvent('mousemove', resizer.nativeElement, 200, 5); UIInteractions.simulateMouseEvent('mouseup', resizer.nativeElement, 200, 5); fixture.detectChanges(); expect(leftSetterSpy).toHaveBeenCalled(); - expect(parseInt(leftSetterSpy.calls.mostRecent().args[0].toFixed(0))).toEqual(200); + expect(parseInt(vi.mocked(leftSetterSpy).mock.lastCall[0].toFixed(0))).toEqual(200); expect(parseInt(grid.columnList.get(1).headerCell.nativeElement.getBoundingClientRect().width.toFixed(0))).toEqual(173); })); @@ -199,7 +200,7 @@ describe('IgxGrid - Deferred Column Resizing #grid', () => { fixture.detectChanges(); expect(column.width).toEqual('80px'); - setElementSize(grid.nativeElement, ɵSize.Medium) + setElementSize(grid.nativeElement, ɵSize.Medium); tick(16); // needed because of the throttleTime of the resize obserer fixture.detectChanges(); @@ -214,7 +215,7 @@ describe('IgxGrid - Deferred Column Resizing #grid', () => { fixture.detectChanges(); expect(column.width).toEqual('64px'); - setElementSize(grid.nativeElement, ɵSize.Small) + setElementSize(grid.nativeElement, ɵSize.Small); tick(16); // needed because of the throttleTime of the resize obserer fixture.detectChanges(); @@ -673,7 +674,7 @@ describe('IgxGrid - Deferred Column Resizing #grid', () => { })); it('should fire columnResized with correct event args.', fakeAsync(() => { - const resizingSpy = spyOn(grid.columnResized, 'emit').and.callThrough(); + const resizingSpy = vi.spyOn(grid.columnResized, 'emit'); const headers: DebugElement[] = GridFunctions.getColumnHeaders(fixture); expect(grid.columnList.get(0).width).toEqual('150px'); @@ -981,19 +982,20 @@ describe('IgxGrid - Deferred Column Resizing #grid', () => { imports: [IgxGridComponent, IgxColumnComponent] }) export class ResizableColumnsComponent { - @ViewChild(IgxGridComponent, { static: true }) public grid: IgxGridComponent; + @ViewChild(IgxGridComponent, { static: true }) + public grid: IgxGridComponent; public data = SampleTestData.personIDNameRegionData(); } @Component({ - template: GridTemplateStrings.declareGrid(`width="500px" height="300px"`, ``, - 'Grid Toolbar' + + template: GridTemplateStrings.declareGrid(`width="500px" height="300px"`, ``, 'Grid Toolbar' + ColumnDefinitions.resizableThreeOfFour), imports: [IgxGridComponent, IgxColumnComponent, IgxGridToolbarComponent, IgxGridToolbarTitleComponent] }) export class ResizableColumnsWithToolbarComponent { - @ViewChild(IgxGridComponent, { static: true }) public grid: IgxGridComponent; + @ViewChild(IgxGridComponent, { static: true }) + public grid: IgxGridComponent; public data = SampleTestData.personIDNameRegionData(); } @@ -1015,7 +1017,8 @@ export class ResizableColumnsWithToolbarComponent { imports: [IgxGridComponent, IgxColumnComponent, IgxCellTemplateDirective] }) export class LargePinnedColGridComponent implements OnInit { - @ViewChild(IgxGridComponent, { static: true }) public grid: IgxGridComponent; + @ViewChild(IgxGridComponent, { static: true }) + public grid: IgxGridComponent; public timeGenerator: Calendar = new Calendar(); public today: Date = new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate(), 0, 0, 0); @@ -1036,7 +1039,8 @@ export class LargePinnedColGridComponent implements OnInit { imports: [IgxGridComponent, IgxColumnComponent, IgxCellTemplateDirective, IgxCellHeaderTemplateDirective, IgxAvatarComponent] }) export class GridFeaturesComponent { - @ViewChild(IgxGridComponent, { static: true }) public grid: IgxGridComponent; + @ViewChild(IgxGridComponent, { static: true }) + public grid: IgxGridComponent; public timeGenerator: Calendar = new Calendar(); public today: Date = new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate(), 0, 0, 0); @@ -1049,7 +1053,8 @@ export class GridFeaturesComponent { imports: [IgxGridComponent, IgxColumnComponent] }) export class NullColumnsComponent implements OnInit { - @ViewChild(IgxGridComponent, { static: true }) public grid: IgxGridComponent; + @ViewChild(IgxGridComponent, { static: true }) + public grid: IgxGridComponent; public data = []; public columns = []; @@ -1080,7 +1085,8 @@ export class NullColumnsComponent implements OnInit { imports: [IgxGridComponent, IgxColumnComponent] }) export class MinWidthColumnsComponent implements OnInit { - @ViewChild(IgxGridComponent, { static: true }) public grid: IgxGridComponent; + @ViewChild(IgxGridComponent, { static: true }) + public grid: IgxGridComponent; public data = []; @@ -1099,7 +1105,8 @@ export class MinWidthColumnsComponent implements OnInit { imports: [IgxGridComponent, IgxColumnComponent] }) export class ColGridComponent implements OnInit { - @ViewChild(IgxGridComponent, { static: true }) public grid: IgxGridComponent; + @ViewChild(IgxGridComponent, { static: true }) + public grid: IgxGridComponent; public data = []; @@ -1116,7 +1123,8 @@ export class ColGridComponent implements OnInit { imports: [IgxGridComponent, IgxColumnComponent] }) export class ColPercentageGridComponent implements OnInit { - @ViewChild(IgxGridComponent, { static: true }) public grid: IgxGridComponent; + @ViewChild(IgxGridComponent, { static: true }) + public grid: IgxGridComponent; public data = []; @@ -1141,7 +1149,8 @@ export class ColPercentageGridComponent implements OnInit { imports: [IgxGridComponent, IgxColumnComponent] }) export class ColAutosizeGridComponent implements OnInit { - @ViewChild(IgxGridComponent, { static: true }) public grid: IgxGridComponent; + @ViewChild(IgxGridComponent, { static: true }) + public grid: IgxGridComponent; public data = []; diff --git a/projects/igniteui-angular/grids/grid/src/column-selection.spec.ts b/projects/igniteui-angular/grids/grid/src/column-selection.spec.ts index ca124d9bbda..2802f85736a 100644 --- a/projects/igniteui-angular/grids/grid/src/column-selection.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/column-selection.spec.ts @@ -7,6 +7,7 @@ import { IgxColumnComponent } from 'igniteui-angular/grids/core'; import { IColumnSelectionEventArgs } from 'igniteui-angular/grids/core'; import { GridSelectionMode } from 'igniteui-angular/grids/core'; import { IgxStringFilteringOperand } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const SELECTED_COLUMN_CLASS = 'igx-grid-th--selected'; const SELECTED_COLUMN_CELL_CLASS = 'igx-grid__td--column-selected'; @@ -54,7 +55,7 @@ describe('IgxGrid - Column Selection #grid', () => { }); it('setting selected and selectable properties ', () => { - spyOn(grid.columnSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.columnSelectionChanging, 'emit'); grid.columnList.forEach(column => { expect(column.selectable).toBeTruthy(); expect(column.selected).toBeFalsy(); @@ -81,7 +82,7 @@ describe('IgxGrid - Column Selection #grid', () => { }); it('selecting a column with mouse click', () => { - spyOn(grid.columnSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.columnSelectionChanging, 'emit'); colProductName.selectable = false; fix.detectChanges(); @@ -93,7 +94,7 @@ describe('IgxGrid - Column Selection #grid', () => { newSelection: ['ProductID'], added: ['ProductID'], removed: [], - event: jasmine.anything() as any, + event: expect.anything() as any, cancel: false }; expect(grid.columnSelectionChanging.emit).toHaveBeenCalledWith(args); @@ -112,7 +113,7 @@ describe('IgxGrid - Column Selection #grid', () => { newSelection: ['InStock'], added: ['InStock'], removed: ['ProductID'], - event: jasmine.anything() as any, + event: expect.anything() as any, cancel: false }; expect(grid.columnSelectionChanging.emit).toHaveBeenCalledWith(args); @@ -125,7 +126,7 @@ describe('IgxGrid - Column Selection #grid', () => { newSelection: [], added: [], removed: ['InStock'], - event: jasmine.anything() as any, + event: expect.anything() as any, cancel: false }; expect(grid.columnSelectionChanging.emit).toHaveBeenCalledWith(args); @@ -208,7 +209,7 @@ describe('IgxGrid - Column Selection #grid', () => { }); it('verify method selectColumns', () => { - spyOn(grid.columnSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.columnSelectionChanging, 'emit'); const colUnits = grid.getColumnByName('UnitsInStock'); const colOrderDate = grid.getColumnByName('OrderDate'); // select columns with array of fields @@ -249,7 +250,7 @@ describe('IgxGrid - Column Selection #grid', () => { }); it('verify method deselectColumns', () => { - spyOn(grid.columnSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.columnSelectionChanging, 'emit'); grid.columns.forEach(col => col.selected = true); const colUnits = grid.getColumnByName('UnitsInStock'); @@ -280,7 +281,7 @@ describe('IgxGrid - Column Selection #grid', () => { }); it('verify methods selectAllColumns and deselectAllColumns', () => { - spyOn(grid.columnSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.columnSelectionChanging, 'emit'); // select all columns grid.selectAllColumns(); fix.detectChanges(); @@ -358,7 +359,7 @@ describe('IgxGrid - Column Selection #grid', () => { }); it('selecting a column with ctrl + mouse click', () => { - spyOn(grid.columnSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.columnSelectionChanging, 'emit'); colProductName.selectable = false; fix.detectChanges(); @@ -372,7 +373,7 @@ describe('IgxGrid - Column Selection #grid', () => { newSelection: ['ProductID'], added: ['ProductID'], removed: [], - event: jasmine.anything() as any, + event: expect.anything() as any, cancel: false }; expect(grid.columnSelectionChanging.emit).toHaveBeenCalledWith(args); @@ -388,7 +389,7 @@ describe('IgxGrid - Column Selection #grid', () => { newSelection: ['ProductID', 'InStock'], added: ['InStock'], removed: [], - event: jasmine.anything() as any, + event: expect.anything() as any, cancel: false }; expect(grid.columnSelectionChanging.emit).toHaveBeenCalledWith(args); @@ -410,7 +411,7 @@ describe('IgxGrid - Column Selection #grid', () => { newSelection: ['ProductID', 'InStock', 'OrderDate'], added: ['OrderDate'], removed: [], - event: jasmine.anything() as any, + event: expect.anything() as any, cancel: false }; expect(grid.columnSelectionChanging.emit).toHaveBeenCalledWith(args); @@ -427,7 +428,7 @@ describe('IgxGrid - Column Selection #grid', () => { newSelection: ['ProductID', 'OrderDate'], added: [], removed: ['InStock'], - event: jasmine.anything() as any, + event: expect.anything() as any, cancel: false }; expect(grid.columnSelectionChanging.emit).toHaveBeenCalledWith(args); @@ -443,14 +444,14 @@ describe('IgxGrid - Column Selection #grid', () => { newSelection: ['OrderDate'], added: [], removed: ['ProductID'], - event: jasmine.anything() as any, + event: expect.anything() as any, cancel: false }; expect(grid.columnSelectionChanging.emit).toHaveBeenCalledWith(args); }); it('selecting a column with shift + mouse click', () => { - spyOn(grid.columnSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.columnSelectionChanging, 'emit'); const colUnits = grid.getColumnByName('UnitsInStock'); const colOrderDate = grid.getColumnByName('OrderDate'); colUnits.selected = true; @@ -468,7 +469,7 @@ describe('IgxGrid - Column Selection #grid', () => { newSelection: ['UnitsInStock', 'InStock'], added: ['InStock'], removed: [], - event: jasmine.anything() as any, + event: expect.anything() as any, cancel: false }; expect(grid.columnSelectionChanging.emit).toHaveBeenCalledWith(args); @@ -485,7 +486,7 @@ describe('IgxGrid - Column Selection #grid', () => { newSelection: ['UnitsInStock', 'InStock', 'OrderDate'], added: ['OrderDate'], removed: [], - event: jasmine.anything() as any, + event: expect.anything() as any, cancel: false }; expect(grid.columnSelectionChanging.emit).toHaveBeenCalledWith(args); @@ -504,7 +505,7 @@ describe('IgxGrid - Column Selection #grid', () => { newSelection: ['UnitsInStock', 'InStock', 'ProductID'], added: ['ProductID'], removed: ['OrderDate'], - event: jasmine.anything() as any, + event: expect.anything() as any, cancel: false }; expect(grid.columnSelectionChanging.emit).toHaveBeenCalledWith(args); @@ -633,7 +634,7 @@ describe('IgxGrid - Column Selection #grid', () => { const companyName = grid.getColumnByName('CompanyName'); const contactName = grid.getColumnByName('ContactName'); const contactTitle = grid.getColumnByName('ContactTitle'); - spyOn(grid.columnSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.columnSelectionChanging, 'emit'); // verify setting selected true on a column group genInf.selected = true; @@ -669,7 +670,7 @@ describe('IgxGrid - Column Selection #grid', () => { const postalCode = grid.getColumnByName('PostalCode'); const city = grid.getColumnByName('City'); const address = grid.getColumnByName('Address'); - spyOn(grid.columnSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.columnSelectionChanging, 'emit'); // verify setting selected true on a column group countryInf.selected = true; @@ -697,7 +698,7 @@ describe('IgxGrid - Column Selection #grid', () => { const companyName = grid.getColumnByName('CompanyName'); const contactName = grid.getColumnByName('ContactName'); const contactTitle = grid.getColumnByName('ContactTitle'); - spyOn(grid.columnSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.columnSelectionChanging, 'emit'); // verify setting selected true on a column group contactName.selectable = false; diff --git a/projects/igniteui-angular/grids/grid/src/column.spec.ts b/projects/igniteui-angular/grids/grid/src/column.spec.ts index 45de39793ef..6d1e0919078 100644 --- a/projects/igniteui-angular/grids/grid/src/column.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/column.spec.ts @@ -8,15 +8,7 @@ import localeJa from '@angular/common/locales/ja'; import { IgxGridComponent } from './grid.component'; import { GridTemplateStrings, ColumnDefinitions } from '../../../test-utils/template-strings.spec'; import { SampleTestData } from '../../../test-utils/sample-test-data.spec'; -import { - ColumnHiddenFromMarkupComponent, - ColumnCellFormatterComponent, - DynamicColumnsComponent, - GridAddColumnComponent, - IgxGridCurrencyColumnComponent, - IgxGridPercentColumnComponent, - IgxGridDateTimeColumnComponent -} from '../../../test-utils/grid-samples.spec'; +import { ColumnHiddenFromMarkupComponent, ColumnCellFormatterComponent, DynamicColumnsComponent, GridAddColumnComponent, IgxGridCurrencyColumnComponent, IgxGridPercentColumnComponent, IgxGridDateTimeColumnComponent } from '../../../test-utils/grid-samples.spec'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { UIInteractions, wait } from '../../../test-utils/ui-interactions.spec'; import { GridFunctions, GridSummaryFunctions } from '../../../test-utils/grid-functions.spec'; @@ -25,6 +17,7 @@ import { IgxGridRowComponent } from './grid-row.component'; import { GridColumnDataType, IgxStringFilteringOperand, SortingDirection } from 'igniteui-angular/core'; import { IgxButtonDirective, IgxDateTimeEditorDirective } from 'igniteui-angular/directives'; import { IgxInputDirective } from 'igniteui-angular/input-group'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('IgxGrid - Column properties #grid', () => { @@ -195,7 +188,7 @@ describe('IgxGrid - Column properties #grid', () => { expect(headers[1].nativeElement.textContent).toMatch('Name'); })); - it('should support adding and removing columns through a declared iterable', fakeAsync(/** columnList.changes rAF */() => { + it('should support adding and removing columns through a declared iterable', fakeAsync(/** columnList.changes rAF */ () => { const fix = TestBed.createComponent(ColumnsFromIterableComponent); fix.detectChanges(); @@ -331,14 +324,11 @@ describe('IgxGrid - Column properties #grid', () => { const grid = fixture.componentInstance.instance; - grid.getColumnByName('Name')._cells.forEach(c => - expect(c.nativeElement.querySelector('.customCellTemplate')).toBeDefined()); + grid.getColumnByName('Name')._cells.forEach(c => expect(c.nativeElement.querySelector('.customCellTemplate')).toBeDefined()); - grid.headerCellList.forEach(header => - expect(header.nativeElement.querySelector('.customHeaderTemplate')).toBeDefined()); + grid.headerCellList.forEach(header => expect(header.nativeElement.querySelector('.customHeaderTemplate')).toBeDefined()); - grid.summariesRowList.forEach(summary => - expect(summary.nativeElement.querySelector('.customSummaryTemplate')).not.toBeNull()); + grid.summariesRowList.forEach(summary => expect(summary.nativeElement.querySelector('.customSummaryTemplate')).not.toBeNull()); const cell = grid.getCellByColumn(0, 'ID'); cell.editMode = true; @@ -632,15 +622,13 @@ describe('IgxGrid - Column properties #grid', () => { fix.detectChanges(); let summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '$0', '$20,000', '$39,004', '$3,900.4']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '$0', '$20,000', '$39,004', '$3,900.4']); grid.locale = 'fr-FR'; fix.detectChanges(); summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0 €', '20 000 €', '39 004 €', '3 900,4 €']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0 €', '20 000 €', '39 004 €', '3 900,4 €']); }); it('filtering UI list should be populated with correct values based on the currency code, locale and/or pipeArgs', fakeAsync(() => { @@ -790,8 +778,7 @@ describe('IgxGrid - Column properties #grid', () => { fix.detectChanges(); const summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '-70%', '1,100%', '2,153.9%', '215.39%']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '-70%', '1,100%', '2,153.9%', '215.39%']); }); it('filtering UI list should be populated with correct values based on the currency code, locale and/or pipeArgs', fakeAsync(() => { @@ -971,10 +958,8 @@ describe('IgxGrid - Column properties #grid', () => { fix.detectChanges(); let summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, - ['Count', 'Earliest', 'Latest'], ['10', 'Mar 12, 2015, 9:31:22 PM', 'Aug 3, 2021, 3:15:00 PM']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['10', '6:40:18 AM', '8:20:24 PM']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Earliest', 'Latest'], ['10', 'Mar 12, 2015, 9:31:22 PM', 'Aug 3, 2021, 3:15:00 PM']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['10', '6:40:18 AM', '8:20:24 PM']); column.pipeArgs = { format: 'short' }; receiveTimeColumn.pipeArgs = { format: 'shortTime' }; @@ -982,10 +967,8 @@ describe('IgxGrid - Column properties #grid', () => { fix.detectChanges(); summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, - ['Count', 'Earliest', 'Latest'], ['10', '3/12/15, 9:31 PM', '8/3/21, 3:15 PM']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['10', '6:40 AM', '8:20 PM']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Earliest', 'Latest'], ['10', '3/12/15, 9:31 PM', '8/3/21, 3:15 PM']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['10', '6:40 AM', '8:20 PM']); }); it('DateTime: filtering UI list should be populated with correct values based on the pipeArgs', fakeAsync(() => { @@ -1091,7 +1074,7 @@ describe('IgxGrid - Column properties #grid', () => { receiveTimeColumn.editorOptions = { dateTimeFormat: 'h-mm-ss aaaaa' }; fix.detectChanges(); - producedDateColumn._cells[0].setEditMode(true) + producedDateColumn._cells[0].setEditMode(true); fix.detectChanges(); tick(); @@ -1103,7 +1086,7 @@ describe('IgxGrid - Column properties #grid', () => { expect((dateTimeEditor.nativeElement as any).value).toEqual('2014-10-01'); - orderDateColumn._cells[0].setEditMode(true) + orderDateColumn._cells[0].setEditMode(true); fix.detectChanges(); tick(); @@ -1115,7 +1098,7 @@ describe('IgxGrid - Column properties #grid', () => { expect((dateTimeEditor.nativeElement as any).value).toEqual('2015--10--01'); - receiveTimeColumn._cells[0].setEditMode(true) + receiveTimeColumn._cells[0].setEditMode(true); fix.detectChanges(); tick(); @@ -1267,7 +1250,7 @@ describe('IgxGrid - Column properties #grid', () => { }; fix.detectChanges(); - producedDateColumn._cells[0].setEditMode(true) + producedDateColumn._cells[0].setEditMode(true); fix.detectChanges(); let inputDebugElement = fix.debugElement.query(By.directive(IgxInputDirective)); @@ -1278,7 +1261,7 @@ describe('IgxGrid - Column properties #grid', () => { expect(dateTimeEditor.nativeElement.value).toEqual('10/01/2014'); - orderDateColumn._cells[0].setEditMode(true) + orderDateColumn._cells[0].setEditMode(true); fix.detectChanges(); inputDebugElement = fix.debugElement.query(By.directive(IgxInputDirective)); @@ -1289,7 +1272,7 @@ describe('IgxGrid - Column properties #grid', () => { expect(dateTimeEditor.nativeElement.value.normalize('NFKC')).toEqual('10/01/2015, 11:37:22 AM'); - receiveTimeColumn._cells[0].setEditMode(true) + receiveTimeColumn._cells[0].setEditMode(true); fix.detectChanges(); inputDebugElement = fix.debugElement.query(By.directive(IgxInputDirective)); @@ -1307,9 +1290,9 @@ describe('IgxGrid - Column properties #grid', () => { fix.detectChanges(); const sortedValues = [new Date(2015, 2, 12, 21, 31, 22), new Date(2015, 9, 1, 11, 37, 22), new Date(2016, 7, 18, 11, 17, 22), - new Date(2018, 6, 14, 17, 27, 23), new Date(2019, 3, 17, 5, 5, 15), new Date(2019, 9, 30, 16, 17, 27), - new Date(2021, 4, 11, 7, 47, 1), new Date(2021, 4, 11, 18, 37, 2), - new Date(2021, 7, 3, 15, 15, 0), new Date(2021, 7, 3, 15, 15, 0)]; + new Date(2018, 6, 14, 17, 27, 23), new Date(2019, 3, 17, 5, 5, 15), new Date(2019, 9, 30, 16, 17, 27), + new Date(2021, 4, 11, 7, 47, 1), new Date(2021, 4, 11, 18, 37, 2), + new Date(2021, 7, 3, 15, 15, 0), new Date(2021, 7, 3, 15, 15, 0)]; expect(grid.rowList.length).toEqual(sortedValues.length); sortedValues.forEach((value, index) => { @@ -1353,41 +1336,41 @@ describe('IgxGrid - Column properties #grid', () => { let fix: ComponentFixture; let grid: IgxGridComponent; const dataWithImages = [{ - avatar: './test-utils/assets/images/avatar/1.jpg', - phone: '770-504-2217', - text: 'Terrance Orta', - available: false - }, { - avatar: './test-utils/assets/images/avatar/2.jpg', - phone: '423-676-2869', - text: 'Richard Mahoney', - available: true - }, { - avatar: './test-utils/assets/images/avatar/3.jpg', - phone: '859-496-2817', - text: 'Donna Price', - available: true - }, { - avatar: './test-utils/assets/images/avatar/4.jpg', - phone: '901-747-3428', - text: 'Lisa Landers', - available: true - }, { - avatar: './test-utils/assets/images/avatar/12.jpg', - phone: '573-394-9254', - text: 'Dorothy H. Spencer', - available: true - }, { - avatar: './test-utils/assets/images/avatar/13.jpg', - phone: '323-668-1482', - text: 'Stephanie May', - available: false - }, { - avatar: './test-utils/assets/images/avatar/14.jpg', - phone: '401-661-3742', - text: 'Marianne Taylor', - available: true - }]; + avatar: './test-utils/assets/images/avatar/1.jpg', + phone: '770-504-2217', + text: 'Terrance Orta', + available: false + }, { + avatar: './test-utils/assets/images/avatar/2.jpg', + phone: '423-676-2869', + text: 'Richard Mahoney', + available: true + }, { + avatar: './test-utils/assets/images/avatar/3.jpg', + phone: '859-496-2817', + text: 'Donna Price', + available: true + }, { + avatar: './test-utils/assets/images/avatar/4.jpg', + phone: '901-747-3428', + text: 'Lisa Landers', + available: true + }, { + avatar: './test-utils/assets/images/avatar/12.jpg', + phone: '573-394-9254', + text: 'Dorothy H. Spencer', + available: true + }, { + avatar: './test-utils/assets/images/avatar/13.jpg', + phone: '323-668-1482', + text: 'Stephanie May', + available: false + }, { + avatar: './test-utils/assets/images/avatar/14.jpg', + phone: '401-661-3742', + text: 'Marianne Taylor', + available: true + }]; beforeEach(waitForAsync(() => { fix = TestBed.createComponent(IgxGridComponent); @@ -1402,11 +1385,11 @@ describe('IgxGrid - Column properties #grid', () => { it('should initialize correctly with autoGenerate and image data', () => { const column = grid.getColumnByName('avatar'); expect(column.dataType).toBe(GridColumnDataType.Image); - expect(column.sortable).toBeFalse(); - expect(column.groupable).toBeFalse(); - expect(column.filterable).toBeFalse(); - expect(column.editable).toBeFalse(); - expect(column.hasSummary).toBeFalse(); + expect(column.sortable).toBe(false); + expect(column.groupable).toBe(false); + expect(column.filterable).toBe(false); + expect(column.editable).toBe(false); + expect(column.hasSummary).toBe(false); const cell = column._cells[0]; expect(cell.nativeElement.firstElementChild.tagName).toBe('IMG'); @@ -1646,13 +1629,13 @@ describe('IgxGrid - Column properties #grid', () => { .filter(attr => Boolean(attr)); for (const attr of gridAttributes) { - expect(grid[attr]).toBe(true, `Grid attribute: '${attr}' failed`); + expect(grid[attr], `Grid attribute: '${attr}' failed`).toBe(true); } for (const attr of columnAttributes) { - expect(column[attr]).toBe(true, `Column attribute: '${attr}' failed`); + expect(column[attr], `Column attribute: '${attr}' failed`).toBe(true); } - })) + })); }); }); @@ -1669,8 +1652,8 @@ export class ColumnsFromIterableComponent { } interface IColumnConfig { - field: string, - width: string, + field: string; + width: string; minWidth?: string; maxWidth?: string; hidden?: boolean; diff --git a/projects/igniteui-angular/grids/grid/src/grid-add-row.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-add-row.spec.ts index bc3beb7bfeb..37f78f7659e 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-add-row.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-add-row.spec.ts @@ -3,9 +3,7 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { TestBed, fakeAsync, tick, waitForAsync } from '@angular/core/testing'; import { DebugElement } from '@angular/core'; import { GridFunctions, GridSummaryFunctions } from '../../../test-utils/grid-functions.spec'; -import { - IgxAddRowComponent, IgxGridRowEditingDefinedColumnsComponent, IgxGridRowEditingTransactionComponent -} from '../../../test-utils/grid-samples.spec'; +import { IgxAddRowComponent, IgxGridRowEditingDefinedColumnsComponent, IgxGridRowEditingTransactionComponent } from '../../../test-utils/grid-samples.spec'; import { By } from '@angular/platform-browser'; import { IgxActionStripComponent } from 'igniteui-angular/action-strip'; @@ -17,24 +15,25 @@ import { takeUntil, first } from 'rxjs/operators'; import { Subject } from 'rxjs'; import { DefaultSortingStrategy, IgxStringFilteringOperand, SortingDirection, TransactionType } from 'igniteui-angular/core'; import { IgxGridMRLNavigationService } from 'igniteui-angular/grids/core'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; const DEBOUNCETIME = 30; describe('IgxGrid - Row Adding #grid', () => { - const GRID_ROW = 'igx-grid-row'; - const DISPLAY_CONTAINER = 'igx-display-container'; - const SUMMARY_ROW = 'igx-grid-summary-row'; - const GRID_THEAD_ITEM = '.igx-grid-thead__item'; - - let fixture; - let grid: IgxGridComponent; - let gridContent: DebugElement; - let actionStrip: IgxActionStripComponent; + const GRID_ROW = 'igx-grid-row'; + const DISPLAY_CONTAINER = 'igx-display-container'; + const SUMMARY_ROW = 'igx-grid-summary-row'; + const GRID_THEAD_ITEM = '.igx-grid-thead__item'; + + let fixture; + let grid: IgxGridComponent; + let gridContent: DebugElement; + let actionStrip: IgxActionStripComponent; const endTransition = () => { - // transition end needs to be simulated - const animationElem = fixture.nativeElement.querySelector('.igx-grid__tr--inner'); - const endEvent = new AnimationEvent('animationend'); - animationElem.dispatchEvent(endEvent); + // transition end needs to be simulated + const animationElem = fixture.nativeElement.querySelector('.igx-grid__tr--inner'); + const endEvent = new AnimationEvent('animationend'); + animationElem.dispatchEvent(endEvent); }; beforeEach(waitForAsync(() => { @@ -70,7 +69,7 @@ describe('IgxGrid - Row Adding #grid', () => { addRowIcon.parent.triggerEventHandler('click', new Event('click')); fixture.detectChanges(); const addRow = grid.gridAPI.get_row_by_index(1); - expect(addRow.addRowUI).toBeTrue(); + expect(addRow.addRowUI).toBe(true); }); it('Should be able to enter add row mode through the exposed API method.', () => { @@ -81,17 +80,17 @@ describe('IgxGrid - Row Adding #grid', () => { endTransition(); let addRow = grid.gridAPI.get_row_by_index(1); - expect(addRow.addRowUI).toBeTrue(); + expect(addRow.addRowUI).toBe(true); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fixture.detectChanges(); addRow = grid.gridAPI.get_row_by_index(1); - expect(addRow.addRowUI).toBeFalse(); + expect(addRow.addRowUI).toBe(false); rows[1].beginAddRow(); fixture.detectChanges(); addRow = grid.gridAPI.get_row_by_index(2); - expect(addRow.addRowUI).toBeTrue(); + expect(addRow.addRowUI).toBe(true); }); it('Should display the banner above the row if there is no room underneath it', () => { @@ -115,7 +114,7 @@ describe('IgxGrid - Row Adding #grid', () => { endTransition(); const addRow = grid.gridAPI.get_row_by_index(lastRowIndex + 1); - // expect(addRow.addRow).toBeTrue(); + // expect(addRow.addRow).toBeTrue(); const banner = GridFunctions.getRowEditingOverlay(fixture); fixture.detectChanges(); @@ -137,7 +136,7 @@ describe('IgxGrid - Row Adding #grid', () => { fixture.detectChanges(); const addRow = grid.gridAPI.get_row_by_index(1); - expect(addRow.addRowUI).toBeTrue(); + expect(addRow.addRowUI).toBe(true); }); @@ -150,7 +149,7 @@ describe('IgxGrid - Row Adding #grid', () => { const banner = GridFunctions.getRowEditingOverlay(fixture); expect(banner).toBeNull(); - expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBeFalse(); + expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBe(false); }); it('Should not be able to enter add row mode when rowEditing is disabled', () => { @@ -162,7 +161,7 @@ describe('IgxGrid - Row Adding #grid', () => { const banner = GridFunctions.getRowEditingOverlay(fixture); expect(banner).toBeNull(); - expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBeFalse(); + expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBe(false); }); it('Should allow adding row from pinned row.', () => { @@ -276,12 +275,12 @@ describe('IgxGrid - Row Adding #grid', () => { // check page is correct expect(grid.paginator.page).toBe(5); - // check added row is rendered and is in view - const row = grid.gridAPI.get_row_by_key(addedRec[grid.primaryKey]); - expect(row).not.toBeNull(); - const gridOffsets = grid.tbody.nativeElement.getBoundingClientRect(); - const rowOffsets = row.nativeElement.getBoundingClientRect(); - expect(rowOffsets.top >= gridOffsets.top && rowOffsets.bottom <= gridOffsets.bottom).toBeTruthy(); + // check added row is rendered and is in view + const row = grid.gridAPI.get_row_by_key(addedRec[grid.primaryKey]); + expect(row).not.toBeNull(); + const gridOffsets = grid.tbody.nativeElement.getBoundingClientRect(); + const rowOffsets = row.nativeElement.getBoundingClientRect(); + expect(rowOffsets.top >= gridOffsets.top && rowOffsets.bottom <= gridOffsets.bottom).toBeTruthy(); }); it('Should generate correct row ID based on the primary column type', () => { @@ -293,9 +292,9 @@ describe('IgxGrid - Row Adding #grid', () => { fixture.detectChanges(); const newRow = grid.gridAPI.get_row_by_index(1); - expect(newRow.addRowUI).toBeTrue(); + expect(newRow.addRowUI).toBe(true); const cell = newRow.cells.find(c => c.column === column); - expect(typeof(cell.value)).toBe(type); + expect(typeof (cell.value)).toBe(type); }); it('should allow setting a different display time for snackbar', async () => { @@ -327,7 +326,7 @@ describe('IgxGrid - Row Adding #grid', () => { endTransition(); const addRow = grid.gridAPI.get_row_by_index(1); - expect(addRow.addRowUI).toBeTrue(); + expect(addRow.addRowUI).toBe(true); expect(GridFunctions.getRowEditingBannerText(fixture)).toEqual('Adding Row'); }); @@ -348,14 +347,14 @@ describe('IgxGrid - Row Adding #grid', () => { }); it('Should emit all events in the correct order', () => { - spyOn(grid.rowEditEnter, 'emit').and.callThrough(); - spyOn(grid.cellEditEnter, 'emit').and.callThrough(); - spyOn(grid.cellEdit, 'emit').and.callThrough(); - spyOn(grid.cellEditDone, 'emit').and.callThrough(); - spyOn(grid.cellEditExit, 'emit').and.callThrough(); - spyOn(grid.rowEdit, 'emit').and.callThrough(); - spyOn(grid.rowEditDone, 'emit').and.callThrough(); - spyOn(grid.rowEditExit, 'emit').and.callThrough(); + vi.spyOn(grid.rowEditEnter, 'emit'); + vi.spyOn(grid.cellEditEnter, 'emit'); + vi.spyOn(grid.cellEdit, 'emit'); + vi.spyOn(grid.cellEditDone, 'emit'); + vi.spyOn(grid.cellEditExit, 'emit'); + vi.spyOn(grid.rowEdit, 'emit'); + vi.spyOn(grid.rowEditDone, 'emit'); + vi.spyOn(grid.rowEditExit, 'emit'); grid.rowEditEnter.pipe(takeUntil($destroyer)).subscribe(() => { expect(grid.rowEditEnter.emit).toHaveBeenCalledTimes(1); @@ -408,7 +407,7 @@ describe('IgxGrid - Row Adding #grid', () => { endTransition(); - const cell = grid.gridAPI.get_cell_by_index(1, 'CompanyName'); + const cell = grid.gridAPI.get_cell_by_index(1, 'CompanyName'); const cellInput = cell.nativeElement.querySelector('[igxinput]'); UIInteractions.setInputElementValue(cellInput, 'aaa'); fixture.detectChanges(); @@ -417,10 +416,10 @@ describe('IgxGrid - Row Adding #grid', () => { }); it('Should emit all grid editing events as per row editing specification', () => { - spyOn(grid.cellEditEnter, 'emit').and.callThrough(); - spyOn(grid.cellEditDone, 'emit').and.callThrough(); - spyOn(grid.rowEditEnter, 'emit').and.callThrough(); - spyOn(grid.rowEditDone, 'emit').and.callThrough(); + vi.spyOn(grid.cellEditEnter, 'emit'); + vi.spyOn(grid.cellEditDone, 'emit'); + vi.spyOn(grid.rowEditEnter, 'emit'); + vi.spyOn(grid.rowEditDone, 'emit'); const row = grid.gridAPI.get_row_by_index(0); row.beginAddRow(); @@ -429,11 +428,11 @@ describe('IgxGrid - Row Adding #grid', () => { endTransition(); const newRow = grid.gridAPI.get_row_by_index(1); - expect(newRow.addRowUI).toBeTrue(); + expect(newRow.addRowUI).toBe(true); expect(grid.cellEditEnter.emit).toHaveBeenCalled(); expect(grid.rowEditEnter.emit).toHaveBeenCalled(); - const cell = grid.gridAPI.get_cell_by_index(1, 'CompanyName'); + const cell = grid.gridAPI.get_cell_by_index(1, 'CompanyName'); const cellInput = cell.nativeElement.querySelector('[igxinput]'); UIInteractions.setInputElementValue(cellInput, 'aaa'); fixture.detectChanges(); @@ -455,7 +454,7 @@ describe('IgxGrid - Row Adding #grid', () => { fixture.detectChanges(); endTransition(); - expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBeFalse(); + expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBe(false); }); it('Should enter add mode but close it when cellEditEnter is canceled', () => { @@ -467,7 +466,7 @@ describe('IgxGrid - Row Adding #grid', () => { grid.rowList.first.beginAddRow(); fixture.detectChanges(); - expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBeTrue(); + expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBe(true); expect(grid.crudService.cellInEditMode).toEqual(false); grid.gridAPI.crudService.endEdit(false); @@ -477,11 +476,11 @@ describe('IgxGrid - Row Adding #grid', () => { grid.rowList.first.beginAddRow(); fixture.detectChanges(); - expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBeTrue(); + expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBe(true); }); it(`Should emit 'rowEditEnter' only once while adding a new row`, () => { - spyOn(grid.rowEditEnter, 'emit').and.callThrough(); + vi.spyOn(grid.rowEditEnter, 'emit'); const row = grid.gridAPI.get_row_by_index(0); row.beginAddRow(); fixture.detectChanges(); @@ -489,7 +488,7 @@ describe('IgxGrid - Row Adding #grid', () => { endTransition(); const newRow = grid.gridAPI.get_row_by_index(1); - expect(newRow.addRowUI).toBeTrue(); + expect(newRow.addRowUI).toBe(true); let targetCell = grid.gridAPI.get_cell_by_index(1, 'ContactName') as any; UIInteractions.simulateClickAndSelectEvent(targetCell); @@ -516,10 +515,10 @@ describe('IgxGrid - Row Adding #grid', () => { await wait(DEBOUNCETIME); fixture.detectChanges(); - expect(grid.gridAPI.get_row_by_index(0).addRowUI).toBeTrue(); + expect(grid.gridAPI.get_row_by_index(0).addRowUI).toBe(true); }); - xit('Should scroll and start adding a row as for a row that is not in view', async () => { + it.skip('Should scroll and start adding a row as for a row that is not in view', async () => { await wait(DEBOUNCETIME); fixture.detectChanges(); @@ -528,7 +527,7 @@ describe('IgxGrid - Row Adding #grid', () => { await wait(DEBOUNCETIME); fixture.detectChanges(); - expect(grid.gridAPI.get_row_by_index(8).addRowUI).toBeTrue(); + expect(grid.gridAPI.get_row_by_index(8).addRowUI).toBe(true); }); }); @@ -550,14 +549,14 @@ describe('IgxGrid - Row Adding #grid', () => { endTransition(); let newRow = grid.gridAPI.get_row_by_index(1); - expect(newRow.addRowUI).toBeTrue(); + expect(newRow.addRowUI).toBe(true); const doneButtonElement = GridFunctions.getRowEditingDoneButton(fixture); doneButtonElement.click(); fixture.detectChanges(); newRow = grid.gridAPI.get_row_by_index(1); - expect(newRow.addRowUI).toBeFalse(); + expect(newRow.addRowUI).toBe(false); expect(grid.data.length).toBe(dataLength + 1); }); @@ -570,7 +569,7 @@ describe('IgxGrid - Row Adding #grid', () => { endTransition(); let newRow = grid.gridAPI.get_row_by_index(1); - expect(newRow.addRowUI).toBeTrue(); + expect(newRow.addRowUI).toBe(true); const cancelButtonElement = GridFunctions.getRowEditingCancelButton(fixture); cancelButtonElement.click(); @@ -579,7 +578,7 @@ describe('IgxGrid - Row Adding #grid', () => { fixture.detectChanges(); newRow = grid.gridAPI.get_row_by_index(1); - expect(newRow.addRowUI).toBeFalse(); + expect(newRow.addRowUI).toBe(false); expect(grid.data.length).toBe(dataLength); }); @@ -592,13 +591,13 @@ describe('IgxGrid - Row Adding #grid', () => { endTransition(); let newRow = grid.gridAPI.get_row_by_index(1); - expect(newRow.addRowUI).toBeTrue(); + expect(newRow.addRowUI).toBe(true); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fixture.detectChanges(); newRow = grid.gridAPI.get_row_by_index(1); - expect(newRow.addRowUI).toBeFalse(); + expect(newRow.addRowUI).toBe(false); expect(grid.data.length).toBe(dataLength); }); @@ -611,13 +610,13 @@ describe('IgxGrid - Row Adding #grid', () => { endTransition(); let newRow = grid.gridAPI.get_row_by_index(1); - expect(newRow.addRowUI).toBeTrue(); + expect(newRow.addRowUI).toBe(true); UIInteractions.triggerEventHandlerKeyDown('enter', gridContent); fixture.detectChanges(); newRow = grid.gridAPI.get_row_by_index(1); - expect(newRow.addRowUI).toBeFalse(); + expect(newRow.addRowUI).toBe(false); expect(grid.data.length).toBe(dataLength + 1); }); @@ -633,7 +632,7 @@ describe('IgxGrid - Row Adding #grid', () => { endTransition(); let newRow = grid.gridAPI.get_row_by_index(1); - expect(newRow.addRowUI).toBeTrue(); + expect(newRow.addRowUI).toBe(true); const cancelButtonElement = GridFunctions.getRowEditingCancelButton(fixture); cancelButtonElement.click(); @@ -642,7 +641,7 @@ describe('IgxGrid - Row Adding #grid', () => { fixture.detectChanges(); newRow = grid.gridAPI.get_row_by_index(1); - expect(newRow.addRowUI).toBeFalse(); + expect(newRow.addRowUI).toBe(false); expect(grid.data.length).toBe(dataLength); (grid as any).scrollTo(0, grid.columnList.length - 1); @@ -666,7 +665,7 @@ describe('IgxGrid - Row Adding #grid', () => { gridContent = GridFunctions.getGridContent(fixture); }); - it('Should preserve the changes after page navigation', () => { + it('Should preserve the changes after page navigation', () => { const dataLength = grid.data.length; fixture.componentInstance.paging = true; fixture.detectChanges(); @@ -716,7 +715,7 @@ describe('IgxGrid - Row Adding #grid', () => { }); it('Should exit add row mode on filter applied and discard', () => { - spyOn(grid.gridAPI.crudService, 'endEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); const dataLength = grid.data.length; const row = grid.rowList.first; @@ -744,9 +743,9 @@ describe('IgxGrid - Row Adding #grid', () => { endTransition(); const newRow = grid.gridAPI.get_row_by_index(1); - expect(newRow.addRowUI).toBeTrue(); + expect(newRow.addRowUI).toBe(true); - const cell = grid.gridAPI.get_cell_by_index(1, 'CompanyName'); + const cell = grid.gridAPI.get_cell_by_index(1, 'CompanyName'); const cellInput = cell.nativeElement.querySelector('[igxinput]'); UIInteractions.setInputElementValue(cellInput, 'Alan'); grid.gridAPI.crudService.endEdit(true); @@ -765,9 +764,9 @@ describe('IgxGrid - Row Adding #grid', () => { endTransition(); const newRow = grid.gridAPI.get_row_by_index(1); - expect(newRow.addRowUI).toBeTrue(); + expect(newRow.addRowUI).toBe(true); - const cell = grid.gridAPI.get_cell_by_index(1, 'CompanyName'); + const cell = grid.gridAPI.get_cell_by_index(1, 'CompanyName'); const cellInput = cell.nativeElement.querySelector('[igxinput]'); UIInteractions.setInputElementValue(cellInput, 'Xuary'); grid.gridAPI.crudService.endEdit(true); @@ -788,7 +787,7 @@ describe('IgxGrid - Row Adding #grid', () => { }); it('Should exit add row mode and discard on sorting', () => { - spyOn(grid.gridAPI.crudService, 'endEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); const dataLength = grid.data.length; const row = grid.rowList.first; @@ -819,9 +818,9 @@ describe('IgxGrid - Row Adding #grid', () => { endTransition(); const newRow = grid.gridAPI.get_row_by_index(1); - expect(newRow.addRowUI).toBeTrue(); + expect(newRow.addRowUI).toBe(true); - const cell = grid.gridAPI.get_cell_by_index(1, 'CompanyName'); + const cell = grid.gridAPI.get_cell_by_index(1, 'CompanyName'); const cellInput = cell.nativeElement.querySelector('[igxinput]'); UIInteractions.setInputElementValue(cellInput, 'Azua'); grid.gridAPI.crudService.endEdit(true); @@ -839,18 +838,18 @@ describe('IgxGrid - Row Adding #grid', () => { gridContent = GridFunctions.getGridContent(fixture); }); - it('Should collapse expanded detail view before spawning add row UI', () => { + it('Should collapse expanded detail view before spawning add row UI', () => { grid.rowEditable = true; fixture.detectChanges(); const row = grid.rowList.first; grid.expandRow(row.key); fixture.detectChanges(); - expect(row.expanded).toBeTrue(); + expect(row.expanded).toBe(true); row.beginAddRow(); fixture.detectChanges(); - expect(row.expanded).toBeFalse(); - expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBeTrue(); + expect(row.expanded).toBe(false); + expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBe(true); }); }); @@ -871,7 +870,7 @@ describe('IgxGrid - Row Adding #grid', () => { gridFirstRow.beginAddRow(); fixture.detectChanges(); const newRow = grid.gridAPI.get_row_by_index(1); - expect(newRow.addRowUI).toBeTrue(); + expect(newRow.addRowUI).toBe(true); GridFunctions.verifyLayoutHeadersAreAligned(grid, newRow); }); }); @@ -895,14 +894,14 @@ describe('IgxGrid - Row Adding #grid', () => { let groupRows = grid.groupsRowList.toArray(); grid.toggleGroup(groupRows[2].groupRow); fixture.detectChanges(); - expect(groupRows[2].expanded).toBeFalse(); + expect(groupRows[2].expanded).toBe(false); const row = grid.gridAPI.get_row_by_index(1); row.beginAddRow(); fixture.detectChanges(); endTransition(); - const cell = grid.gridAPI.get_cell_by_index(2, 'CompanyName'); + const cell = grid.gridAPI.get_cell_by_index(2, 'CompanyName'); const cellInput = cell.nativeElement.querySelector('[igxinput]'); UIInteractions.setInputElementValue(cellInput, 'Antonio Moreno Taquería'); grid.gridAPI.crudService.endEdit(true); @@ -916,7 +915,7 @@ describe('IgxGrid - Row Adding #grid', () => { groupRows = grid.groupsRowList.toArray(); expect(row2).not.toBeNull(); - expect(groupRows[2].expanded).toBeTrue(); + expect(groupRows[2].expanded).toBe(true); expect(groupRows[2].groupRow.records.length).toEqual(2); expect(groupRows[2].groupRow.records[1]).toBe(row2.data); }); @@ -958,7 +957,7 @@ describe('IgxGrid - Row Adding #grid', () => { }); it('Should exit add row mode when moving a column', fakeAsync(() => { - spyOn(grid.gridAPI.crudService, 'endEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); const dataLength = grid.data.length; const row = grid.rowList.first; row.beginAddRow(); @@ -966,7 +965,7 @@ describe('IgxGrid - Row Adding #grid', () => { endTransition(); - expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBeTrue(); + expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBe(true); expect(grid.rowEditingOverlay.collapsed).toEqual(false); grid.moveColumn(grid.columnList.get(1), grid.columnList.get(2)); @@ -979,14 +978,14 @@ describe('IgxGrid - Row Adding #grid', () => { })); it('Should exit add row mode when pinning/unpinning a column', () => { - spyOn(grid.gridAPI.crudService, 'endEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); const dataLength = grid.data.length; const row = grid.rowList.first; row.beginAddRow(); fixture.detectChanges(); endTransition(); - expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBeTrue(); + expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBe(true); expect(grid.rowEditingOverlay.collapsed).toEqual(false); grid.pinColumn('CompanyName'); @@ -1008,7 +1007,7 @@ describe('IgxGrid - Row Adding #grid', () => { }); it('Should exit add row mode when resizing a column', async () => { - spyOn(grid.gridAPI.crudService, 'endEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); fixture.detectChanges(); @@ -1019,7 +1018,7 @@ describe('IgxGrid - Row Adding #grid', () => { endTransition(); - expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBeTrue(); + expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBe(true); expect(grid.rowEditingOverlay.collapsed).toEqual(false); const headers: DebugElement[] = fixture.debugElement.queryAll(By.css(GRID_THEAD_ITEM)); @@ -1039,7 +1038,7 @@ describe('IgxGrid - Row Adding #grid', () => { }); it('Should exit add row mode when hiding a column', () => { - spyOn(grid.gridAPI.crudService, 'endEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); const dataLength = grid.data.length; const row = grid.rowList.first; row.beginAddRow(); @@ -1047,7 +1046,7 @@ describe('IgxGrid - Row Adding #grid', () => { endTransition(); - expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBeTrue(); + expect(grid.gridAPI.get_row_by_index(1).addRowUI).toBe(true); expect(grid.rowEditingOverlay.collapsed).toEqual(false); const column = grid.columnList.filter(c => c.field === 'ContactName')[0]; @@ -1095,7 +1094,7 @@ describe('IgxGrid - Row Adding #grid', () => { expect(states.length).toEqual(1); expect(states[0].type).toEqual(TransactionType.ADD); - const cell = grid.getCellByColumn(grid.dataView.length - 1, 'ProductName'); + const cell = grid.getCellByColumn(grid.dataView.length - 1, 'ProductName'); cell.update('aaa'); fixture.detectChanges(); states = grid.transactions.getAggregatedChanges(true); diff --git a/projects/igniteui-angular/grids/grid/src/grid-cell-editing.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-cell-editing.spec.ts index c84769e3161..a0905dd8fd7 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-cell-editing.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-cell-editing.spec.ts @@ -4,17 +4,13 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxGridComponent } from './public_api'; import { UIInteractions, wait } from '../../../test-utils/ui-interactions.spec'; import { GridFunctions } from '../../../test-utils/grid-functions.spec'; -import { - CellEditingTestComponent, CellEditingScrollTestComponent, - SelectionWithTransactionsComponent, - ColumnEditablePropertyTestComponent, - CellEditingCustomEditorTestComponent -} from '../../../test-utils/grid-samples.spec'; +import { CellEditingTestComponent, CellEditingScrollTestComponent, SelectionWithTransactionsComponent, ColumnEditablePropertyTestComponent, CellEditingCustomEditorTestComponent } from '../../../test-utils/grid-samples.spec'; import { DebugElement } from '@angular/core'; import { first, takeUntil } from 'rxjs/operators'; import { Subject, fromEvent } from 'rxjs'; import { IGridEditDoneEventArgs, IGridEditEventArgs, IgxColumnComponent } from 'igniteui-angular/grids/core'; import { IgxStringFilteringOperand, SortingDirection } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; const DEBOUNCE_TIME = 30; const CELL_CSS_CLASS = '.igx-grid__td'; @@ -314,7 +310,7 @@ describe('IgxGrid - Cell Editing #grid', () => { it('should focus the first cell when editing mode is cell', fakeAsync(() => { const cell = grid.gridAPI.get_cell_by_index(0, 'fullName'); expect(cell.editMode).toBe(false); - expect(document.activeElement.nodeName).toEqual('BODY') + expect(document.activeElement.nodeName).toEqual('BODY'); // Enter cell edit mode UIInteractions.simulateDoubleClickAndSelectEvent(cell); @@ -323,10 +319,10 @@ describe('IgxGrid - Cell Editing #grid', () => { // Check focused element and selection expect(cell.editMode).toBe(true); - expect(document.activeElement.nodeName).toEqual('INPUT') + expect(document.activeElement.nodeName).toEqual('INPUT'); expect((document.activeElement as HTMLInputElement).value).toBe('John Brown'); - expect((document.activeElement as HTMLInputElement).selectionStart).toEqual(0) - expect((document.activeElement as HTMLInputElement).selectionEnd).toEqual(10) + expect((document.activeElement as HTMLInputElement).selectionStart).toEqual(0); + expect((document.activeElement as HTMLInputElement).selectionEnd).toEqual(10); })); it('should work correct when not using ngModel but value and change event', fakeAsync(() => { @@ -377,7 +373,7 @@ describe('IgxGrid - Cell Editing #grid', () => { UIInteractions.simulateDoubleClickAndSelectEvent(cell); fixture.detectChanges(); tick(16); - expect(cell.editMode).toBeTrue(); + expect(cell.editMode).toBe(true); const editInput = fixture.debugElement.query(By.css('igx-grid-cell input')); if (editInput) { @@ -390,7 +386,7 @@ describe('IgxGrid - Cell Editing #grid', () => { tick(100); fixture.detectChanges(); - expect(cell.editMode).toBeFalse(); + expect(cell.editMode).toBe(false); expect(document.activeElement).toBe(grid.tbody.nativeElement); @@ -657,7 +653,7 @@ describe('IgxGrid - Cell Editing #grid', () => { })); it(`Should properly emit 'cellEditEnter' event`, () => { - spyOn(grid.cellEditEnter, 'emit').and.callThrough(); + vi.spyOn(grid.cellEditEnter, 'emit'); const cell = grid.gridAPI.get_cell_by_index(0, 'fullName'); let initialRowData = { ...cell.row.data }; expect(cell.editMode).toBeFalsy(); @@ -676,7 +672,7 @@ describe('IgxGrid - Cell Editing #grid', () => { valid: true, column: cell.column, owner: grid, - event: jasmine.anything() as any + event: expect.anything() as any }; expect(grid.cellEditEnter.emit).toHaveBeenCalledTimes(1); expect(grid.cellEditEnter.emit).toHaveBeenCalledWith(cellArgs); @@ -700,7 +696,7 @@ describe('IgxGrid - Cell Editing #grid', () => { cancel: false, column: cell2.column, owner: grid, - event: jasmine.anything() as any + event: expect.anything() as any }; expect(grid.cellEditEnter.emit).toHaveBeenCalledTimes(2); expect(grid.cellEditEnter.emit).toHaveBeenCalledWith(cellArgs); @@ -708,7 +704,7 @@ describe('IgxGrid - Cell Editing #grid', () => { }); it(`Should be able to cancel 'cellEditEnter' event`, () => { - spyOn(grid.cellEditEnter, 'emit').and.callThrough(); + vi.spyOn(grid.cellEditEnter, 'emit'); grid.cellEditEnter.subscribe((e: IGridEditEventArgs) => { e.cancel = true; }); @@ -730,7 +726,7 @@ describe('IgxGrid - Cell Editing #grid', () => { valid: true, column: cell.column, owner: grid, - event: jasmine.anything() as any + event: expect.anything() as any }; expect(grid.cellEditEnter.emit).toHaveBeenCalledTimes(1); expect(grid.cellEditEnter.emit).toHaveBeenCalledWith(cellArgs); @@ -755,7 +751,7 @@ describe('IgxGrid - Cell Editing #grid', () => { cancel: true, column: cell.column, owner: grid, - event: jasmine.anything() as any, + event: expect.anything() as any, valid: true }; expect(grid.cellEditEnter.emit).toHaveBeenCalledTimes(2); @@ -764,7 +760,7 @@ describe('IgxGrid - Cell Editing #grid', () => { }); it(`Should properly emit 'cellEditExit' event`, () => { - spyOn(grid.cellEditExit, 'emit').and.callThrough(); + vi.spyOn(grid.cellEditExit, 'emit'); let cell = grid.gridAPI.get_cell_by_index(0, 'fullName'); let initialRowData = { ...cell.row.data }; expect(cell.editMode).toBeFalsy(); @@ -787,7 +783,7 @@ describe('IgxGrid - Cell Editing #grid', () => { oldValue: 'John Brown', column: cell.column, owner: grid, - event: jasmine.anything() as any + event: expect.anything() as any }; expect(grid.cellEditExit.emit).toHaveBeenCalledTimes(1); @@ -811,14 +807,14 @@ describe('IgxGrid - Cell Editing #grid', () => { valid: true, column: cell.column, owner: grid, - event: jasmine.anything() as any + event: expect.anything() as any }; expect(grid.cellEditExit.emit).toHaveBeenCalledTimes(2); expect(grid.cellEditExit.emit).toHaveBeenCalledWith(cellArgs); }); it(`Should properly emit 'cellEdit' event`, () => { - spyOn(grid.cellEdit, 'emit').and.callThrough(); + vi.spyOn(grid.cellEdit, 'emit'); let cellArgs: IGridEditEventArgs; let cell = grid.gridAPI.get_cell_by_index(0, 'fullName'); @@ -846,7 +842,7 @@ describe('IgxGrid - Cell Editing #grid', () => { cancel: false, column: cell.column, owner: grid, - event: jasmine.anything() as any, + event: expect.anything() as any, valid: true }; expect(grid.cellEdit.emit).toHaveBeenCalledTimes(1); @@ -874,7 +870,7 @@ describe('IgxGrid - Cell Editing #grid', () => { cancel: false, column: cell.column, owner: grid, - event: jasmine.anything() as any, + event: expect.anything() as any, valid: true }; expect(grid.cellEdit.emit).toHaveBeenCalledTimes(2); @@ -882,7 +878,7 @@ describe('IgxGrid - Cell Editing #grid', () => { }); it(`Should be able to cancel 'cellEdit' event`, fakeAsync(() => { - const emitSpy = spyOn(grid.cellEdit, 'emit').and.callThrough(); + const emitSpy = vi.spyOn(grid.cellEdit, 'emit'); grid.cellEdit.subscribe((e: IGridEditEventArgs) => { e.cancel = true; }); @@ -921,11 +917,11 @@ describe('IgxGrid - Cell Editing #grid', () => { expect(grid.cellEdit.emit).toHaveBeenCalledTimes(1); expect(grid.cellEdit.emit).toHaveBeenCalledWith(cellArgs); - emitSpy.calls.reset(); + emitSpy.mockClear(); UIInteractions.triggerEventHandlerKeyDown('tab', gridContent); fixture.detectChanges(); - cellArgs.event = jasmine.anything() as any; + cellArgs.event = expect.anything() as any; expect(cell.editMode).toBe(true); expect(cell.value).toBe(cellValue); expect(document.activeElement).toBe(editInput); @@ -936,7 +932,7 @@ describe('IgxGrid - Cell Editing #grid', () => { expect(nextCell.editMode).toBe(false); // activate the new cell - emitSpy.calls.reset(); + emitSpy.mockClear(); grid.gridAPI.get_cell_by_index(0, 'age').activate(new FocusEvent('focus')); fixture.detectChanges(); expect(grid.cellEdit.emit).toHaveBeenCalledTimes(1); @@ -946,7 +942,7 @@ describe('IgxGrid - Cell Editing #grid', () => { expect(cell.editMode).toBe(true); expect(document.activeElement).toBe(editInput); - emitSpy.calls.reset(); + emitSpy.mockClear(); UIInteractions.triggerEventHandlerKeyDown('enter', gridContent); fixture.detectChanges(); @@ -960,7 +956,7 @@ describe('IgxGrid - Cell Editing #grid', () => { grid.primaryKey = 'personNumber'; fixture.detectChanges(); - spyOn(grid.cellEdit, 'emit').and.callThrough(); + vi.spyOn(grid.cellEdit, 'emit'); grid.cellEdit.subscribe((e: IGridEditEventArgs) => { if (e.cellID.columnID === 0) { grid.updateCell(1, e.rowID, 'age'); @@ -1032,7 +1028,7 @@ describe('IgxGrid - Cell Editing #grid', () => { expect(cell.value).toBe(initialValue); }); - xit(`Should emit the committed/new rowData cellEditDone`, () => { + it.skip(`Should emit the committed/new rowData cellEditDone`, () => { fixture = TestBed.createComponent(SelectionWithTransactionsComponent); fixture.detectChanges(); grid = fixture.componentInstance.grid; @@ -1042,7 +1038,7 @@ describe('IgxGrid - Cell Editing #grid', () => { const newValue = 'New Name'; const updatedRowData = Object.assign({}, cell.row.data, { Name: newValue }); - spyOn(grid.cellEditDone, 'emit').and.callThrough(); + vi.spyOn(grid.cellEditDone, 'emit'); cell.update(newValue); fixture.detectChanges(); @@ -1065,7 +1061,7 @@ describe('IgxGrid - Cell Editing #grid', () => { }); it(`Should properly emit 'cellEditExit' event`, () => { - spyOn(grid.cellEditExit, 'emit').and.callThrough(); + vi.spyOn(grid.cellEditExit, 'emit'); const cell = grid.gridAPI.get_cell_by_index(0, 'fullName'); const initialRowData = { ...cell.row.data }; @@ -1091,7 +1087,7 @@ describe('IgxGrid - Cell Editing #grid', () => { newValue: 'New Name', column: cell.column, owner: grid, - event: jasmine.anything() as any, + event: expect.anything() as any, valid: true }; expect(grid.cellEditExit.emit).toHaveBeenCalledTimes(1); @@ -1101,7 +1097,7 @@ describe('IgxGrid - Cell Editing #grid', () => { }); it(`Should properly emit 'cellEditDone' event`, () => { - const doneSpy = spyOn(grid.cellEditDone, 'emit').and.callThrough(); + const doneSpy = vi.spyOn(grid.cellEditDone, 'emit'); let cellArgs: IGridEditDoneEventArgs; let cell = grid.getCellByColumn(0, 'fullName'); @@ -1131,7 +1127,7 @@ describe('IgxGrid - Cell Editing #grid', () => { newValue: firstNewValue, column: cell.column, owner: grid, - event: jasmine.anything() as any, + event: expect.anything() as any, valid: true }; expect(grid.cellEditDone.emit).toHaveBeenCalledTimes(1); @@ -1158,13 +1154,13 @@ describe('IgxGrid - Cell Editing #grid', () => { newValue: secondNewValue, column: cell.column, owner: grid, - event: jasmine.anything() as any, + event: expect.anything() as any, valid: true }; expect(grid.cellEditDone.emit).toHaveBeenCalledTimes(2); expect(grid.cellEditDone.emit).toHaveBeenCalledWith(cellArgs); - const spyDoneArgs = doneSpy.calls.mostRecent().args[0] as IGridEditDoneEventArgs; + const spyDoneArgs = vi.mocked(doneSpy).mock.lastCall[0] as IGridEditDoneEventArgs; expect(spyDoneArgs.rowData).toBe(grid.data[0]); }); diff --git a/projects/igniteui-angular/grids/grid/src/grid-cell-selection.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-cell-selection.spec.ts index 93ba9188b21..2fabeb840be 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-cell-selection.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-cell-selection.spec.ts @@ -1,16 +1,11 @@ import { TestBed, fakeAsync, tick, ComponentFixture, waitForAsync } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxGridComponent } from './public_api'; -import { - SelectionWithScrollsComponent, - SelectionWithTransactionsComponent, - CellSelectionNoneComponent, - CellSelectionSingleComponent, - IgxGridRowEditingWithoutEditableColumnsComponent -} from '../../../test-utils/grid-samples.spec'; +import { SelectionWithScrollsComponent, SelectionWithTransactionsComponent, CellSelectionNoneComponent, CellSelectionSingleComponent, IgxGridRowEditingWithoutEditableColumnsComponent } from '../../../test-utils/grid-samples.spec'; import { UIInteractions, wait } from '../../../test-utils/ui-interactions.spec'; import { clearGridSubs, setupGridScrollDetection } from '../../../test-utils/helper-utils.spec'; import { GridSelectionMode } from 'igniteui-angular/grids/core'; +import { describe, it, test, expect, beforeEach, afterEach, vi } from 'vitest'; import { GridSelectionFunctions, GridFunctions } from '../../../test-utils/grid-functions.spec'; import { DebugElement } from '@angular/core'; @@ -45,7 +40,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should be able to select a range with mouse dragging', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const startCell = grid.gridAPI.get_cell_by_index(2, 'ParentID'); const endCell = grid.gridAPI.get_cell_by_index(3, 'ID'); const range = { rowStart: 2, rowEnd: 3, columnStart: 0, columnEnd: 1 }; @@ -99,7 +94,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should not lose selection on right clicking', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const range = { rowStart: 2, rowEnd: 3, columnStart: 0, columnEnd: 1 }; grid.setSelection(range); detect(); @@ -125,7 +120,7 @@ describe('IgxGrid - Cell selection #grid', () => { it('Should be able to select multiple ranges with Ctrl key and mouse drag', () => { let firstCell = grid.gridAPI.get_cell_by_index(1, 'ParentID'); let secondCell = grid.gridAPI.get_cell_by_index(2, 'Name'); - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); GridSelectionFunctions.selectCellsRangeNoWait(fix, firstCell, secondCell); detect(); @@ -198,7 +193,7 @@ describe('IgxGrid - Cell selection #grid', () => { const firstCell = grid.gridAPI.get_cell_by_index(1, 'ParentID'); const secondCell = grid.gridAPI.get_cell_by_index(2, 'Name'); const thirdCell = grid.gridAPI.get_cell_by_index(0, 'ID'); - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); UIInteractions.simulateClickAndSelectEvent(firstCell); fix.detectChanges(); @@ -229,7 +224,7 @@ describe('IgxGrid - Cell selection #grid', () => { GridSelectionFunctions.verifySelectedRange(grid, 0, 0, 0, 0, 2, 3); }); - it('Should be able to select cells correctly when focus is returned to the grid', async() => { + it('Should be able to select cells correctly when focus is returned to the grid', async () => { const firstCell = grid.gridAPI.get_cell_by_index(1, 'ParentID'); const secondCell = grid.gridAPI.get_cell_by_index(2, 'Name'); @@ -270,7 +265,7 @@ describe('IgxGrid - Cell selection #grid', () => { column.bodyTemplate = component.customCell; fix.detectChanges(); - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const cell = grid.gridAPI.get_cell_by_index(1, 'ProductID'); const cellElement = cell.nativeElement; const span = cellElement.querySelector('span'); @@ -286,7 +281,7 @@ describe('IgxGrid - Cell selection #grid', () => { const firstCell = grid.gridAPI.get_cell_by_index(3, 'HireDate'); const secondCell = grid.gridAPI.get_cell_by_index(1, 'ID'); const thirdCell = grid.gridAPI.get_cell_by_index(0, 'Name'); - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); GridSelectionFunctions.selectCellsRangeWithShiftKeyNoWait(fix, firstCell, secondCell); expect(grid.selectedCells.length).toBe(12); @@ -323,7 +318,7 @@ describe('IgxGrid - Cell selection #grid', () => { it('Should be able to select range with Shift key when first cell is not visible', (async () => { const firstCell = grid.gridAPI.get_cell_by_index(1, 'ID'); - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const expectedData1 = [ { ID: 957, ParentID: 147 }, { ID: 317, ParentID: 147 }, @@ -390,7 +385,7 @@ describe('IgxGrid - Cell selection #grid', () => { const firstCell = grid.gridAPI.get_cell_by_index(2, 'ID'); const secondCell = grid.gridAPI.get_cell_by_index(0, 'ParentID'); const thirdCell = grid.gridAPI.get_cell_by_index(0, 'Name'); - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const expectedData1 = [ { ID: 475, ParentID: 147 }, { ID: 957, ParentID: 147 }, @@ -446,7 +441,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should not be possible to select a range when change cellSelection to none', () => { - const rangeChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const rangeChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const startCell = grid.gridAPI.get_cell_by_index(0, 'Name'); const endCell = grid.gridAPI.get_cell_by_index(2, 'ParentID'); @@ -476,7 +471,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should not be possible to select a range when change cellSelection to single', () => { - const rangeChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const rangeChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const startCell = grid.gridAPI.get_cell_by_index(0, 'ID'); const endCell = grid.gridAPI.get_cell_by_index(1, 'ParentID'); @@ -526,7 +521,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should select a single cell', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const range = { rowStart: 2, rowEnd: 2, columnStart: 1, columnEnd: 1 }; const cell = grid.gridAPI.get_cell_by_index(2, 'ParentID'); const expectedData = [ @@ -542,7 +537,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should select a region', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const range = { rowStart: 0, rowEnd: 2, columnStart: 'Name', columnEnd: 'ParentID' }; const expectedData = [ { ParentID: 147, Name: 'Michael Langdon' }, @@ -559,7 +554,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should select a region when one of cells is not visible', (async () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const range = { rowStart: 3, rowEnd: 7, columnStart: 'ID', columnEnd: 'ParentID' }; const expectedData = [ { ID: 225, ParentID: 847 }, @@ -588,7 +583,7 @@ describe('IgxGrid - Cell selection #grid', () => { })); it('Should select a region when two of cells are not visible', (async () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const range = { rowStart: 6, rowEnd: 6, columnStart: 'OnPTO', columnEnd: 'Age' }; const expectedData = [ { Age: 50, OnPTO: false } @@ -616,7 +611,7 @@ describe('IgxGrid - Cell selection #grid', () => { })); it('Should add new range when there is already added range', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const range1 = { rowStart: 0, rowEnd: 1, columnStart: 'ID', columnEnd: 'ParentID' }; const range2 = { rowStart: 1, rowEnd: 2, columnStart: 'ParentID', columnEnd: 'Name' }; const expectedData1 = [ @@ -649,7 +644,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should add multiple ranges', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const range1 = { rowStart: 0, rowEnd: 0, columnStart: 'ID', columnEnd: 'ParentID' }; const range2 = { rowStart: 2, rowEnd: 3, columnStart: 'ParentID', columnEnd: 'Name' }; const expectedData = [ @@ -670,7 +665,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should add multiple ranges when they have same cells', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const range1 = { rowStart: 1, rowEnd: 3, columnStart: 'ID', columnEnd: 'ParentID' }; const range2 = { rowStart: 3, rowEnd: 1, columnStart: 'ParentID', columnEnd: 'ID' }; const expectedData = [ @@ -689,7 +684,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should add multiple ranges when some of their cells are same', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const range1 = { rowStart: 1, rowEnd: 3, columnStart: 'ID', columnEnd: 'ParentID' }; const range2 = { rowStart: 4, rowEnd: 2, columnStart: 'ParentID', columnEnd: 'ID' }; const expectedData = [ @@ -710,7 +705,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should not add range when column is hidden', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const range = { rowStart: 1, rowEnd: 3, columnStart: 'ID', columnEnd: 'Name' }; grid.getColumnByName('Name').hidden = true; fix.detectChanges(); @@ -730,7 +725,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should not add range when column is hidden and there is already selected range', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const range1 = { rowStart: 1, rowEnd: 2, columnStart: 'ID', columnEnd: 'Name' }; const range2 = { rowStart: 0, rowEnd: 4, columnStart: 'ParentID', columnEnd: 'OnPTO' }; const expectedData = [ @@ -763,7 +758,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should not add range when column does not exist', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const range = { rowStart: 1, rowEnd: 3, columnStart: 'NotExisting', columnEnd: 'Name' }; let errorMessage = ''; @@ -781,7 +776,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should add range when row does not exist', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const range = { rowStart: -7, rowEnd: 100, columnStart: 'ID', columnEnd: 'ID' }; const expectedData = [ { ID: 475 }, @@ -803,7 +798,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should add range when columnStart index does not exist', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const range = { rowStart: 0, rowEnd: 1, columnStart: -4, columnEnd: 0 }; const expectedData = [ { ID: 475 }, @@ -819,7 +814,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should add range when columnStart and columnEnd indexes do not exist', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const range = { rowStart: 1, rowEnd: 2, columnStart: 5, columnEnd: 10 }; const expectedData = [ { OnPTO: true }, @@ -835,7 +830,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should not add range when columnStart and columnEnd indexes do not exist', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const range = { rowStart: 1, rowEnd: 2, columnStart: 10, columnEnd: 100 }; grid.selectRange(range); @@ -847,7 +842,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should be able to clear the selected ranges', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const range = { rowStart: 1, rowEnd: 2, columnStart: 1, columnEnd: 2 }; const expectedData = [ { ParentID: 147, Name: 'Thomas Hardy' }, @@ -886,7 +881,7 @@ describe('IgxGrid - Cell selection #grid', () => { it('Should be able to clear the selection when there are no selected cells', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); grid.selectRange(); fix.detectChanges(); expect(grid.getSelectedRanges().length).toEqual(0); @@ -917,7 +912,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('rangeSelected event should be emitted when pointer leaves active state outside grid\'s cells', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const startCell = grid.gridAPI.get_cell_by_index(2, 'ParentID'); const range = { rowStart: 2, rowEnd: 3, columnStart: 0, columnEnd: 1 }; @@ -991,7 +986,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should be able to select a range with arrow keys and holding Shift', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); let cell = grid.gridAPI.get_cell_by_index(1, 'ParentID'); UIInteractions.simulateClickAndSelectEvent(cell); fix.detectChanges(); @@ -1037,7 +1032,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it(`Should not clear selection from keyboard shift-state on non-primary click`, () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); let cell = grid.gridAPI.get_cell_by_index(1, 'ParentID'); UIInteractions.simulateClickAndSelectEvent(cell); @@ -1065,9 +1060,11 @@ describe('IgxGrid - Cell selection #grid', () => { GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 2, 1, 2); }); - it(`Should not clear range when try to navigate out the grid with shift + it.skip(`Should not clear range when try to navigate out the grid with shift + arrrow keys and then click on other cell with pressed Ctrl'`, () => { - pending('# Issue should be fixedy'); + // TODO: vitest-migration: The pending() function was converted to a skipped test (`it.skip`). See: https://vitest.dev/api/vi.html#it-skip + // pending('# Issue should be fixedy'); + ; let cell = grid.gridAPI.get_cell_by_index(0, 'ID'); UIInteractions.simulateClickAndSelectEvent(cell); fix.detectChanges(); @@ -1092,7 +1089,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should be able to select and move scroll with arrow keys and holding Shift', (async () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); let cell = grid.gridAPI.get_cell_by_index(1, 'Name'); UIInteractions.simulateClickAndSelectEvent(cell); fix.detectChanges(); @@ -1138,7 +1135,7 @@ describe('IgxGrid - Cell selection #grid', () => { })); it('Should not fire event when no new cells are selected', (async () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); let cell = grid.gridAPI.get_cell_by_index(0, 'ID'); UIInteractions.simulateClickAndSelectEvent(cell); fix.detectChanges(); @@ -1191,7 +1188,7 @@ describe('IgxGrid - Cell selection #grid', () => { })); it('Should select cells when select region with keyboard and then click on a cell holding Ctrl', (async () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const firstCell = grid.gridAPI.get_cell_by_index(2, 'Name'); const secondCell = grid.gridAPI.get_cell_by_index(3, 'ParentID'); const expectedData = [ @@ -1221,7 +1218,7 @@ describe('IgxGrid - Cell selection #grid', () => { })); it('Should correct range when navigate with the keyboard and click on another cell with Shift key', (async () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const firstCell = grid.gridAPI.get_cell_by_index(1, 'ID'); const secondCell = grid.gridAPI.get_cell_by_index(2, 'Name'); const expectedData = [ @@ -1253,7 +1250,7 @@ describe('IgxGrid - Cell selection #grid', () => { const secondCell = grid.gridAPI.get_cell_by_index(4, 'Name'); const thirdCell = grid.gridAPI.get_cell_by_index(2, 'ParentID'); - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); await GridSelectionFunctions.selectCellsRange(fix, firstCell, secondCell); detect(); @@ -1276,7 +1273,7 @@ describe('IgxGrid - Cell selection #grid', () => { const secondCell = grid.gridAPI.get_cell_by_index(2, 'ID'); const thirdCell = grid.gridAPI.get_cell_by_index(2, 'ParentID'); - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); await GridSelectionFunctions.selectCellsRangeWithShiftKey(fix, firstCell, secondCell); expect(selectionChangeSpy).toHaveBeenCalledTimes(1); @@ -1299,7 +1296,7 @@ describe('IgxGrid - Cell selection #grid', () => { const secondCell = grid.gridAPI.get_cell_by_index(2, 'HireDate'); const thirdCell = grid.gridAPI.get_cell_by_index(1, 'HireDate'); - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); UIInteractions.simulateClickAndSelectEvent(firstCell); fix.detectChanges(); @@ -1328,7 +1325,7 @@ describe('IgxGrid - Cell selection #grid', () => { it('Should handle Shift + Ctrl + Arrow Down keys combination', (async () => { const firstCell = grid.gridAPI.get_cell_by_index(2, 'Name'); - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); UIInteractions.simulateClickAndSelectEvent(firstCell); fix.detectChanges(); @@ -1354,7 +1351,7 @@ describe('IgxGrid - Cell selection #grid', () => { it('Should handle Shift + Ctrl + Arrow Up keys combination', (async () => { const cell = grid.gridAPI.get_cell_by_index(4, 'ParentID'); - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); UIInteractions.simulateClickAndSelectEvent(cell); fix.detectChanges(); @@ -1374,7 +1371,7 @@ describe('IgxGrid - Cell selection #grid', () => { it('Should handle Shift + Ctrl + Arrow Left keys combination', () => { const firstCell = grid.gridAPI.get_cell_by_index(3, 'HireDate'); - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); UIInteractions.simulateClickAndSelectEvent(firstCell); fix.detectChanges(); @@ -1393,7 +1390,7 @@ describe('IgxGrid - Cell selection #grid', () => { it('Should handle Shift + Ctrl + Arrow Right keys combination', (async () => { const firstCell = grid.gridAPI.get_cell_by_index(4, 'Name'); - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); UIInteractions.simulateClickAndSelectEvent(firstCell); fix.detectChanges(); @@ -1415,7 +1412,7 @@ describe('IgxGrid - Cell selection #grid', () => { it('Should handle Shift + Ctrl + Home keys combination', (async () => { const firstCell = grid.gridAPI.get_cell_by_index(3, 'HireDate'); - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); UIInteractions.simulateClickAndSelectEvent(firstCell); fix.detectChanges(); @@ -1441,7 +1438,7 @@ describe('IgxGrid - Cell selection #grid', () => { it('Should handle Shift + Ctrl + End keys combination', (async () => { const firstCell = grid.gridAPI.get_cell_by_index(2, 'ID'); - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); UIInteractions.simulateClickAndSelectEvent(firstCell); await wait(); @@ -1461,7 +1458,7 @@ describe('IgxGrid - Cell selection #grid', () => { })); it('Grouping: should select cells with arrow up and down keys', (async () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); grid.getColumnByName('ParentID').groupable = true; fix.detectChanges(); @@ -1563,7 +1560,7 @@ describe('IgxGrid - Cell selection #grid', () => { })); it('Grouping: should clear selection when you press arrowkey without shift on groupRow', (async () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); grid.getColumnByName('ParentID').groupable = true; fix.detectChanges(); @@ -1601,7 +1598,7 @@ describe('IgxGrid - Cell selection #grid', () => { })); it('Grouping and Summaries: should select cells with arrow up and down keys', (async () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); grid.getColumnByName('ParentID').groupable = true; grid.getColumnByName('Name').hasSummary = true; grid.summaryCalculationMode = 'childLevelsOnly'; @@ -1679,7 +1676,7 @@ describe('IgxGrid - Cell selection #grid', () => { })); it('Grouping and Summaries: should select cells with arrow up and down keys when there are scrolls', (async () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); grid.getColumnByName('ParentID').groupable = true; grid.getColumnByName('Name').hasSummary = true; grid.summaryCalculationMode = 'childLevelsOnly'; @@ -1754,9 +1751,8 @@ describe('IgxGrid - Cell selection #grid', () => { it('Sorting: selection should not change when sorting is performed', () => { const column = grid.getColumnByName('ID'); column.sortable = true; - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); - GridSelectionFunctions.selectCellsRangeNoWait( - fix, grid.gridAPI.get_cell_by_index(1, 'ParentID'), grid.gridAPI.get_cell_by_index(4, 'HireDate')); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); + GridSelectionFunctions.selectCellsRangeNoWait(fix, grid.gridAPI.get_cell_by_index(1, 'ParentID'), grid.gridAPI.get_cell_by_index(4, 'HireDate')); detect(); expect(selectionChangeSpy).toHaveBeenCalledTimes(1); @@ -1795,7 +1791,7 @@ describe('IgxGrid - Cell selection #grid', () => { it('Sorting: selection containing selected cell out of the view should not change when sorting is performed', () => { const column = grid.getColumnByName('ID'); column.sortable = true; - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const range = { rowStart: 2, rowEnd: 7, columnStart: 'ID', columnEnd: 'OnPTO' }; grid.selectRange(range); fix.detectChanges(); @@ -1834,16 +1830,16 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Filtering: selected range should not change when filtering is performed', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const firstCell = grid.gridAPI.get_cell_by_index(0, 'ParentID'); const secondCell = grid.gridAPI.get_cell_by_index(3, 'HireDate'); GridSelectionFunctions.selectCellsRangeNoWait(fix, firstCell, secondCell); detect(); const selectedData = [{ ParentID: 147, Name: 'Michael Langdon', HireDate: new Date('Jul 3, 2011') }, - { ParentID: 147, Name: 'Thomas Hardy', HireDate: new Date('Jul 19, 2009') }, - { ParentID: 147, Name: 'Monica Reyes', HireDate: new Date('Sep 18, 2014') }, - { ParentID: 847, Name: 'Laurence Johnson', HireDate: new Date('May 4, 2014') } + { ParentID: 147, Name: 'Thomas Hardy', HireDate: new Date('Jul 19, 2009') }, + { ParentID: 147, Name: 'Monica Reyes', HireDate: new Date('Sep 18, 2014') }, + { ParentID: 847, Name: 'Laurence Johnson', HireDate: new Date('May 4, 2014') } ]; GridSelectionFunctions.verifySelectedRange(grid, 0, 3, 1, 3); GridSelectionFunctions.verifyCellsRegionSelected(grid, 0, 3, 1, 3); @@ -1852,9 +1848,9 @@ describe('IgxGrid - Cell selection #grid', () => { fix.detectChanges(); const filteredSelectedData = [{ ParentID: 147, Name: 'Michael Langdon', HireDate: new Date('Jul 3, 2011') }, - { ParentID: 147, Name: 'Thomas Hardy', HireDate: new Date('Jul 19, 2009') }, - { ParentID: 147, Name: 'Monica Reyes', HireDate: new Date('Sep 18, 2014') }, - { ParentID: 19, Name: 'Antonio Moreno', HireDate: new Date('May 4, 2014') } + { ParentID: 147, Name: 'Thomas Hardy', HireDate: new Date('Jul 19, 2009') }, + { ParentID: 147, Name: 'Monica Reyes', HireDate: new Date('Sep 18, 2014') }, + { ParentID: 19, Name: 'Antonio Moreno', HireDate: new Date('May 4, 2014') } ]; GridSelectionFunctions.verifySelectedRange(grid, 0, 3, 1, 3); GridSelectionFunctions.verifyCellsRegionSelected(grid, 0, 3, 1, 3); @@ -1889,9 +1885,9 @@ describe('IgxGrid - Cell selection #grid', () => { grid.filter('Name', 'm', IgxStringFilteringOperand.instance().condition('contains'), false); fix.detectChanges(); const filteredSelectedData = [{ ID: 475, ParentID: 147, Name: 'Michael Langdon', HireDate: new Date('Jul 3, 2011') }, - { ID: 957, ParentID: 147, Name: 'Thomas Hardy', HireDate: new Date('Jul 19, 2009') }, - { ID: 317, ParentID: 147, Name: 'Monica Reyes', HireDate: new Date('Sep 18, 2014') }, - { ID: 15, ParentID: 19, Name: 'Antonio Moreno', HireDate: new Date('May 4, 2014') } + { ID: 957, ParentID: 147, Name: 'Thomas Hardy', HireDate: new Date('Jul 19, 2009') }, + { ID: 317, ParentID: 147, Name: 'Monica Reyes', HireDate: new Date('Sep 18, 2014') }, + { ID: 15, ParentID: 19, Name: 'Antonio Moreno', HireDate: new Date('May 4, 2014') } ]; GridSelectionFunctions.verifySelectedRange(grid, 0, 4, 0, 3); @@ -1974,9 +1970,9 @@ describe('IgxGrid - Cell selection #grid', () => { fix.detectChanges(); const selectedData = [{ ID: 957, ParentID: 147, Name: 'Thomas Hardy', HireDate: new Date('Jul 19, 2009') }, - { ID: 317, ParentID: 147, Name: 'Monica Reyes', HireDate: new Date('Sep 18, 2014') }, - { ID: 225, ParentID: 847, Name: 'Laurence Johnson', HireDate: new Date('May 4, 2014') }, - { ID: 663, ParentID: 847, Name: 'Elizabeth Richards', HireDate: new Date('Dec 9, 2017') } + { ID: 317, ParentID: 147, Name: 'Monica Reyes', HireDate: new Date('Sep 18, 2014') }, + { ID: 225, ParentID: 847, Name: 'Laurence Johnson', HireDate: new Date('May 4, 2014') }, + { ID: 663, ParentID: 847, Name: 'Elizabeth Richards', HireDate: new Date('Dec 9, 2017') } ]; GridSelectionFunctions.verifySelectedRange(grid, 1, 4, 0, 3); GridSelectionFunctions.verifyCellsRegionSelected(grid, 1, 4, 0, 3); @@ -2020,7 +2016,7 @@ describe('IgxGrid - Cell selection #grid', () => { expect(grid.getSelectedData()).toEqual([]); })); - xit('Resizing: selected range should not change on resizing', fakeAsync(() => { + it.skip('Resizing: selected range should not change on resizing', fakeAsync(() => { const range = { rowStart: 2, rowEnd: 4, columnStart: 'ID', columnEnd: 'HireDate' }; grid.selectRange(range); fix.detectChanges(); @@ -2091,7 +2087,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Hiding: when hide last column which is in selected range, selection range is changed', (async () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); grid.dataRowList.first.virtDirRow.scrollTo(5); await wait(100); fix.detectChanges(); @@ -2101,7 +2097,7 @@ describe('IgxGrid - Cell selection #grid', () => { fix.detectChanges(); const selectedData = [{ HireDate: new Date('Sep 18, 2014'), Age: 31, OnPTO: false }, - { HireDate: new Date('May 4, 2014'), Age: 44, OnPTO: true } + { HireDate: new Date('May 4, 2014'), Age: 44, OnPTO: true } ]; GridSelectionFunctions.verifySelectedRange(grid, 2, 3, 3, 5); GridSelectionFunctions.verifyCellsRegionSelected(grid, 2, 3, 3, 5); @@ -2157,7 +2153,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Pinning: should be able to select cells from unpinned cols to pinned', (async () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); grid.dataRowList.first.virtDirRow.scrollTo(5); await wait(100); fix.detectChanges(); @@ -3016,8 +3012,8 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('When click on cell it should not be selected', () => { - const rangeChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); - const selectionChangeSpy = spyOn(grid.selected, 'emit').and.callThrough(); + const rangeChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); + const selectionChangeSpy = vi.spyOn(grid.selected, 'emit'); const firstCell = grid.gridAPI.get_cell_by_index(1, 'ParentID'); const secondCell = grid.gridAPI.get_cell_by_index(2, 'Name'); const thirdCell = grid.gridAPI.get_cell_by_index(0, 'ID'); @@ -3048,8 +3044,8 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('When when navigate with keyboard cells should not be selected', () => { - const rangeChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); - const selectionChangeSpy = spyOn(grid.selected, 'emit').and.callThrough(); + const rangeChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); + const selectionChangeSpy = vi.spyOn(grid.selected, 'emit'); let cell = grid.gridAPI.get_cell_by_index(1, 'ParentID'); UIInteractions.simulateClickAndSelectEvent(cell); fix.detectChanges(); @@ -3093,7 +3089,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should not select select a range with mouse dragging', () => { - const rangeChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const rangeChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const startCell = grid.gridAPI.get_cell_by_index(0, 'ID'); const endCell = grid.gridAPI.get_cell_by_index(3, 'ID'); @@ -3125,7 +3121,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should select a cell from API', () => { - const selectionChangeSpy = spyOn(grid.selected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.selected, 'emit'); const cell = grid.gridAPI.get_cell_by_index(1, 'Name'); cell.selected = true; fix.detectChanges(); @@ -3137,7 +3133,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('When change cell selection to multi it should be possible to select cells with mouse dragging', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const startCell = grid.gridAPI.get_cell_by_index(0, 'ParentID'); const endCell = grid.gridAPI.get_cell_by_index(1, 'ParentID'); const expectedData = [ @@ -3175,8 +3171,8 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('When click on cell it should selected', () => { - const rangeChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); - const selectionChangeSpy = spyOn(grid.selected, 'emit').and.callThrough(); + const rangeChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); + const selectionChangeSpy = vi.spyOn(grid.selected, 'emit'); const firstCell = grid.gridAPI.get_cell_by_index(1, 'ParentID'); const secondCell = grid.gridAPI.get_cell_by_index(2, 'Name'); const thirdCell = grid.gridAPI.get_cell_by_index(0, 'ID'); @@ -3211,7 +3207,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should deselect a selected cell with Ctrl + click', () => { - const selectionChangeSpy = spyOn(grid.selected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.selected, 'emit'); const firstCell = grid.gridAPI.get_cell_by_index(1, 'ParentID'); // Click on a cell @@ -3230,7 +3226,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('When when navigate with arrow keys cell selection should be changed', () => { - const selectionChangeSpy = spyOn(grid.selected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.selected, 'emit'); let cell = grid.gridAPI.get_cell_by_index(1, 'Name'); UIInteractions.simulateClickAndSelectEvent(cell); fix.detectChanges(); @@ -3257,8 +3253,8 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('When when navigate with arrow keys and holding Shift only one cell should be selected', () => { - const selectionChangeSpy = spyOn(grid.selected, 'emit').and.callThrough(); - const rangeChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.selected, 'emit'); + const rangeChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); let cell = grid.gridAPI.get_cell_by_index(3, 'ParentID'); UIInteractions.simulateClickAndSelectEvent(cell); fix.detectChanges(); @@ -3286,7 +3282,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('Should not select select a range with mouse dragging', () => { - const rangeChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const rangeChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const startCell = grid.gridAPI.get_cell_by_index(0, 'ID'); const endCell = grid.gridAPI.get_cell_by_index(1, 'ParentID'); @@ -3322,7 +3318,7 @@ describe('IgxGrid - Cell selection #grid', () => { }); it('When change cell selection to multi it should be possible to select cells with mouse dragging', () => { - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const startCell = grid.gridAPI.get_cell_by_index(3, 'ParentID'); const endCell = grid.gridAPI.get_cell_by_index(2, 'Name'); const expectedData = [ diff --git a/projects/igniteui-angular/grids/grid/src/grid-clipboard.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-clipboard.spec.ts index 2ebd4142ac7..acc7adc3575 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-clipboard.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-clipboard.spec.ts @@ -8,6 +8,7 @@ import { GridFunctions } from '../../../test-utils/grid-functions.spec'; import { IgxGridFilteringRowComponent } from 'igniteui-angular/grids/core'; import { CancelableEventArgs } from 'igniteui-angular/core'; import { IgxInputDirective } from 'igniteui-angular/input-group'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxGrid - Clipboard #grid', () => { @@ -28,7 +29,7 @@ describe('IgxGrid - Clipboard #grid', () => { }); it('Copy data with default settings', () => { - const copySpy = spyOn(grid.gridCopy, 'emit').and.callThrough(); + const copySpy = vi.spyOn(grid.gridCopy, 'emit'); const range = { rowStart: 0, rowEnd: 1, columnStart: 1, columnEnd: 3 }; grid.selectRange(range); fix.detectChanges(); @@ -41,7 +42,7 @@ describe('IgxGrid - Clipboard #grid', () => { }); it('Copy data when there are no selected cells', () => { - const copySpy = spyOn(grid.gridCopy, 'emit').and.callThrough(); + const copySpy = vi.spyOn(grid.gridCopy, 'emit'); const eventData = dispatchCopyEventOnGridBody(fix); expect(copySpy).toHaveBeenCalledTimes(1); expect(copySpy).toHaveBeenCalledWith({ @@ -52,7 +53,7 @@ describe('IgxGrid - Clipboard #grid', () => { }); it('Copy data with different separator', () => { - const copySpy = spyOn(grid.gridCopy, 'emit').and.callThrough(); + const copySpy = vi.spyOn(grid.gridCopy, 'emit'); grid.clipboardOptions.separator = ';'; grid.selectRange({ rowStart: 0, rowEnd: 0, columnStart: 0, columnEnd: 0 }); grid.selectRange({ rowStart: 1, rowEnd: 1, columnStart: 1, columnEnd: 1 }); @@ -71,7 +72,7 @@ describe('IgxGrid - Clipboard #grid', () => { }); it('Copy data without headers', () => { - const copySpy = spyOn(grid.gridCopy, 'emit').and.callThrough(); + const copySpy = vi.spyOn(grid.gridCopy, 'emit'); grid.clipboardOptions.copyHeaders = false; grid.selectRange({ rowStart: 1, rowEnd: 2, columnStart: 2, columnEnd: 3 }); fix.detectChanges(); @@ -96,7 +97,7 @@ describe('IgxGrid - Clipboard #grid', () => { grid.paginator.page = 1; fix.detectChanges(); - const copySpy = spyOn(grid.gridCopy, 'emit').and.callThrough(); + const copySpy = vi.spyOn(grid.gridCopy, 'emit'); grid.clipboardOptions.copyHeaders = false; grid.selectRange({ rowStart: 1, rowEnd: 2, columnStart: 2, columnEnd: 3 }); fix.detectChanges(); @@ -107,7 +108,7 @@ describe('IgxGrid - Clipboard #grid', () => { }); it('Disable clipboardOptions', () => { - const copySpy = spyOn(grid.gridCopy, 'emit').and.callThrough(); + const copySpy = vi.spyOn(grid.gridCopy, 'emit'); grid.clipboardOptions.enabled = false; grid.selectRange({ rowStart: 0, rowEnd: 2, columnStart: 0, columnEnd: 3 }); fix.detectChanges(); @@ -118,7 +119,7 @@ describe('IgxGrid - Clipboard #grid', () => { }); it('Disable copyFormatters', () => { - const copySpy = spyOn(grid.gridCopy, 'emit').and.callThrough(); + const copySpy = vi.spyOn(grid.gridCopy, 'emit'); grid.clipboardOptions.copyFormatters = false; grid.selectRange({ rowStart: 1, rowEnd: 3, columnStart: 1, columnEnd: 1 }); fix.detectChanges(); @@ -135,7 +136,7 @@ describe('IgxGrid - Clipboard #grid', () => { }); it('Cancel gridCopy event ', () => { - const copySpy = spyOn(grid.gridCopy, 'emit').and.callThrough(); + const copySpy = vi.spyOn(grid.gridCopy, 'emit'); grid.gridCopy.pipe(take(1)).subscribe((e: CancelableEventArgs) => e.cancel = true); grid.selectRange({ rowStart: 1, rowEnd: 3, columnStart: 0, columnEnd: 3 }); fix.detectChanges(); @@ -150,9 +151,9 @@ describe('IgxGrid - Clipboard #grid', () => { }); it('Copy when there is a cell in edit mode', fakeAsync(() => { - const copySpy = spyOn(grid.gridCopy, 'emit').and.callThrough(); + const copySpy = vi.spyOn(grid.gridCopy, 'emit'); const cell = grid.getCellByColumn(0, 'ProductName'); - grid.gridAPI.get_cell_by_index(0, 'ProductName').nativeElement.dispatchEvent( new Event('dblclick')); + grid.gridAPI.get_cell_by_index(0, 'ProductName').nativeElement.dispatchEvent(new Event('dblclick')); tick(16); fix.detectChanges(); expect(cell.editMode).toBe(true); @@ -181,7 +182,7 @@ describe('IgxGrid - Clipboard #grid', () => { const input = inputDebugElement.nativeElement; const searchVal = 'aaa'; - const ev = new ClipboardEvent('copy', {bubbles: true, clipboardData: new DataTransfer()}); + const ev = new ClipboardEvent('copy', { bubbles: true, clipboardData: new DataTransfer() }); ev.clipboardData.setData('text/plain', searchVal); input.dispatchEvent(ev); fix.detectChanges(); @@ -192,8 +193,8 @@ describe('IgxGrid - Clipboard #grid', () => { const dispatchCopyEventOnGridBody = (fixture) => { const gridBody = fixture.debugElement.query(By.css('.igx-grid__tbody')).nativeElement; - const ev = new ClipboardEvent('copy', {clipboardData: new DataTransfer()}); + const ev = new ClipboardEvent('copy', { clipboardData: new DataTransfer() }); gridBody.dispatchEvent(ev); fixture.detectChanges(); - return ev.clipboardData.getData('text/plain'); + return ev.clipboardData.getData('text/plain'); }; diff --git a/projects/igniteui-angular/grids/grid/src/grid-collapsible-columns.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-collapsible-columns.spec.ts index f4fc2273286..dbb82d929ff 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-collapsible-columns.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-collapsible-columns.spec.ts @@ -1,16 +1,13 @@ import { TestBed, fakeAsync, tick, waitForAsync } from '@angular/core/testing'; import { IgxGridComponent } from './grid.component'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { - CollapsibleColumnGroupTestComponent, - CollapsibleGroupsTemplatesTestComponent, - CollapsibleGroupsDynamicColComponent -} from '../../../test-utils/grid-samples.spec'; +import { CollapsibleColumnGroupTestComponent, CollapsibleGroupsTemplatesTestComponent, CollapsibleGroupsDynamicColComponent } from '../../../test-utils/grid-samples.spec'; import { GridFunctions } from '../../../test-utils/grid-functions.spec'; import { UIInteractions, wait } from '../../../test-utils/ui-interactions.spec'; import { DropPosition } from 'igniteui-angular/grids/core'; import { IgxColumnGroupComponent } from 'igniteui-angular/grids/core'; import { SortingDirection } from 'igniteui-angular/core'; +import { describe, it, test, expect, beforeEach, vi } from 'vitest'; describe('IgxGrid - multi-column headers #grid', () => { let contactInf; @@ -58,7 +55,7 @@ describe('IgxGrid - multi-column headers #grid', () => { GridFunctions.verifyGroupIsExpanded(fixture, addressInf); GridFunctions.verifyGroupIsExpanded(fixture, contactInf, false); - spyOn(addressInf.collapsibleChange, 'emit').and.callThrough(); + vi.spyOn(addressInf.collapsibleChange, 'emit'); addressInf.collapsible = false; fixture.detectChanges(); @@ -108,7 +105,7 @@ describe('IgxGrid - multi-column headers #grid', () => { }); it('verify setting expanded to a column group', () => { - spyOn(addressInf.expandedChange, 'emit').and.callThrough(); + vi.spyOn(addressInf.expandedChange, 'emit'); addressInf.expanded = false; fixture.detectChanges(); @@ -133,7 +130,7 @@ describe('IgxGrid - multi-column headers #grid', () => { }); it('verify setting expanded to a column group form UI', () => { - spyOn(addressInf.expandedChange, 'emit').and.callThrough(); + vi.spyOn(addressInf.expandedChange, 'emit'); GridFunctions.clickGroupExpandIndicator(fixture, addressInf); fixture.detectChanges(); @@ -162,9 +159,9 @@ describe('IgxGrid - multi-column headers #grid', () => { countryCol.visibleWhenCollapsed = false; regionInf.visibleWhenCollapsed = false; fixture.detectChanges(); - spyOn(countryCol.visibleWhenCollapsedChange, 'emit').and.callThrough(); - spyOn(cityInf.visibleWhenCollapsedChange, 'emit').and.callThrough(); - spyOn(emptyCol.visibleWhenCollapsedChange, 'emit').and.callThrough(); + vi.spyOn(countryCol.visibleWhenCollapsedChange, 'emit'); + vi.spyOn(cityInf.visibleWhenCollapsedChange, 'emit'); + vi.spyOn(emptyCol.visibleWhenCollapsedChange, 'emit'); GridFunctions.verifyGroupIsExpanded(fixture, countryInf); GridFunctions.verifyColumnsAreHidden([countryCol, emptyCol, regionInf], false, 13); @@ -208,9 +205,9 @@ describe('IgxGrid - multi-column headers #grid', () => { countryInf.expanded = false; fixture.detectChanges(); - spyOn(regionInf.visibleWhenCollapsedChange, 'emit').and.callThrough(); - spyOn(cityInf.visibleWhenCollapsedChange, 'emit').and.callThrough(); - spyOn(countryCol.visibleWhenCollapsedChange, 'emit').and.callThrough(); + vi.spyOn(regionInf.visibleWhenCollapsedChange, 'emit'); + vi.spyOn(cityInf.visibleWhenCollapsedChange, 'emit'); + vi.spyOn(countryCol.visibleWhenCollapsedChange, 'emit'); // set visibleWhenCollapsed to true regionInf.visibleWhenCollapsed = true; @@ -318,14 +315,16 @@ describe('IgxGrid - multi-column headers #grid', () => { grid = fixture.componentInstance.grid; }); - it('verify adding columns', () => { - pending('The test will work when use Angular 9'); + it.skip('verify adding columns', () => { + // TODO: vitest-migration: The pending() function was converted to a skipped test (`it.skip`). See: https://vitest.dev/api/vi.html#it-skip + // pending('The test will work when use Angular 9'); + ; const firstGroup = GridFunctions.getColGroup(grid, 'First'); GridFunctions.verifyGroupIsExpanded(fixture, firstGroup, false); fixture.detectChanges(); // add a column to first group - fixture.componentInstance.columnGroups[0].columns.push({ field: 'Fax', type: 'string', visibleWhenCollapsed: false }); + fixture.componentInstance.columnGroups[0].columns.push({ field: 'Fax', type: 'string', visibleWhenCollapsed: false }); fixture.detectChanges(); GridFunctions.verifyGroupIsExpanded(fixture, firstGroup); @@ -334,13 +333,14 @@ describe('IgxGrid - multi-column headers #grid', () => { fixture.detectChanges(); GridFunctions.verifyGroupIsExpanded(fixture, firstGroup, true, false); - GridFunctions.verifyColumnsAreHidden( - [grid.getColumnByName('ID'), grid.getColumnByName('CompanyName'), grid.getColumnByName('ContactName')], false, 7); + GridFunctions.verifyColumnsAreHidden([grid.getColumnByName('ID'), grid.getColumnByName('CompanyName'), grid.getColumnByName('ContactName')], false, 7); GridFunctions.verifyColumnIsHidden(grid.getColumnByName('Fax'), true, 7); }); - it('verify deleting columns', () => { - pending('The test will work when use Angular 9'); + it.skip('verify deleting columns', () => { + // TODO: vitest-migration: The pending() function was converted to a skipped test (`it.skip`). See: https://vitest.dev/api/vi.html#it-skip + // pending('The test will work when use Angular 9'); + ; const secondGroup = GridFunctions.getColGroup(grid, 'Second'); GridFunctions.verifyGroupIsExpanded(fixture, secondGroup); fixture.detectChanges(); @@ -360,8 +360,10 @@ describe('IgxGrid - multi-column headers #grid', () => { GridFunctions.verifyGroupIsExpanded(fixture, secondGroup, false); }); - it('verify updating columns', () => { - pending('The test will work when use Angular 9'); + it.skip('verify updating columns', () => { + // TODO: vitest-migration: The pending() function was converted to a skipped test (`it.skip`). See: https://vitest.dev/api/vi.html#it-skip + // pending('The test will work when use Angular 9'); + ; const secondGroup = GridFunctions.getColGroup(grid, 'Second'); const firstGroup = GridFunctions.getColGroup(grid, 'First'); diff --git a/projects/igniteui-angular/grids/grid/src/grid-filtering-advanced.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-filtering-advanced.spec.ts index 0c8c636f9b1..65d323130bd 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-filtering-advanced.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-filtering-advanced.spec.ts @@ -1,17 +1,10 @@ +import type { Mock } from "vitest"; import { fakeAsync, TestBed, tick, flush, ComponentFixture, waitForAsync } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxGridComponent } from './grid.component'; import { UIInteractions } from '../../../test-utils/ui-interactions.spec'; import { GridFunctions } from '../../../test-utils/grid-functions.spec'; -import { - IgxGridAdvancedFilteringColumnGroupComponent, - IgxGridAdvancedFilteringComponent, - IgxGridExternalAdvancedFilteringComponent, - IgxGridAdvancedFilteringBindingComponent, - IgxGridAdvancedFilteringDynamicColumnsComponent, - IgxGridAdvancedFilteringSerializedTreeComponent, - IgxGridAdvancedFilteringWithToolbarComponent -} from '../../../test-utils/grid-samples.spec'; +import { IgxGridAdvancedFilteringColumnGroupComponent, IgxGridAdvancedFilteringComponent, IgxGridExternalAdvancedFilteringComponent, IgxGridAdvancedFilteringBindingComponent, IgxGridAdvancedFilteringDynamicColumnsComponent, IgxGridAdvancedFilteringSerializedTreeComponent, IgxGridAdvancedFilteringWithToolbarComponent } from '../../../test-utils/grid-samples.spec'; import { IgxHierarchicalGridExportComponent, IgxHierarchicalGridTestBaseComponent, IgxHierGridExternalAdvancedFilteringComponent } from '../../../test-utils/hierarchical-grid-components.spec'; import { SampleTestData } from '../../../test-utils/sample-test-data.spec'; import { By } from '@angular/platform-browser'; @@ -22,6 +15,7 @@ import { FilteringExpressionsTree, FilteringLogic, FormattedValuesFilteringStrat import { QueryBuilderSelectors } from 'igniteui-angular/query-builder/src/query-builder/query-builder.common'; import { IgxDateTimeEditorDirective } from 'igniteui-angular/directives'; import { IgxHierarchicalGridComponent } from 'igniteui-angular/grids/hierarchical-grid'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxGrid - Advanced Filtering #grid - ', () => { beforeEach(waitForAsync(() => { @@ -58,21 +52,21 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { it('Should show/hide Advanced Filtering button in toolbar based on respective input.', fakeAsync(() => { // Verify Advanced Filtering button in toolbar is visible. let advFilterButton = GridFunctions.getAdvancedFilteringButton(fix); - expect(advFilterButton !== null && advFilterButton !== undefined).toBe(true, 'Adv.Filter button is not visible.'); + expect(advFilterButton !== null && advFilterButton !== undefined, 'Adv.Filter button is not visible.').toBe(true); grid.allowAdvancedFiltering = false; fix.detectChanges(); // Verify Advanced Filtering button in toolbar is not visible. advFilterButton = GridFunctions.getAdvancedFilteringButton(fix); - expect(advFilterButton !== null && advFilterButton !== undefined).toBe(false, 'Adv.Filter button is visible.'); + expect(advFilterButton !== null && advFilterButton !== undefined, 'Adv.Filter button is visible.').toBe(false); grid.allowAdvancedFiltering = true; fix.detectChanges(); // Verify Advanced Filtering button in toolbar is visible. advFilterButton = GridFunctions.getAdvancedFilteringButton(fix); - expect(advFilterButton !== null && advFilterButton !== undefined).toBe(true, 'Adv.Filter button is not visible.'); + expect(advFilterButton !== null && advFilterButton !== undefined, 'Adv.Filter button is not visible.').toBe(true); })); it('Should correctly initialize the Advanced Filtering dialog.', fakeAsync(() => { @@ -178,8 +172,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { it('Should update the Advanced Filtering button in toolbar when (filtering)/(clear filtering).', fakeAsync(() => { // Verify that the advanced filtering button indicates there are no filters. let advFilterBtn = GridFunctions.getAdvancedFilteringButton(fix); - expect(Array.from(advFilterBtn.children).some(c => (c as any).classList.contains('igx-adv-filter--column-number'))) - .toBe(false, 'Button indicates there is active filtering.'); + expect(Array.from(advFilterBtn.children).some(c => (c as any).classList.contains('igx-adv-filter--column-number')), 'Button indicates there is active filtering.').toBe(false); // Open Advanced Filtering dialog. grid.openAdvancedFilteringDialog(); @@ -206,8 +199,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { // Verify that the advanced filtering button indicates there are filters. advFilterBtn = GridFunctions.getAdvancedFilteringButton(fix); - expect(Array.from(advFilterBtn.children).some(c => (c as any).classList.contains('igx-adv-filter--column-number'))) - .toBe(true, 'Button indicates there is no active filtering.'); + expect(Array.from(advFilterBtn.children).some(c => (c as any).classList.contains('igx-adv-filter--column-number')), 'Button indicates there is no active filtering.').toBe(true); // Open Advanced Filtering dialog. grid.openAdvancedFilteringDialog(); @@ -223,11 +215,10 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { // Verify that the advanced filtering button indicates there are no filters. advFilterBtn = GridFunctions.getAdvancedFilteringButton(fix); - expect(Array.from(advFilterBtn.children).some(c => (c as any).classList.contains('igx-adv-filter--column-number'))) - .toBe(false, 'Button indicates there is active filtering.'); + expect(Array.from(advFilterBtn.children).some(c => (c as any).classList.contains('igx-adv-filter--column-number')), 'Button indicates there is active filtering.').toBe(false); })); - it('The Clear/Cancel/Apply buttons type should be set to "button"', fakeAsync(() => { + it('The Clear/Cancel/Apply buttons type should be set to "button"', fakeAsync(() => { // Open Advanced Filtering dialog. grid.openAdvancedFilteringDialog(); fix.detectChanges(); @@ -240,13 +231,13 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { const expectedButtonType = 'button'; // Verify buttons type is set to "button". - expect(clearButtonType).toBe(expectedButtonType, 'Clear button type is not "button"'); - expect(cancelButtonType).toBe(expectedButtonType, 'Cancel button type is not "button"'); - expect(applyButtonType).toBe(expectedButtonType, 'Apply button type is not "button"'); + expect(clearButtonType, 'Clear button type is not "button"').toBe(expectedButtonType); + expect(cancelButtonType, 'Cancel button type is not "button"').toBe(expectedButtonType); + expect(applyButtonType, 'Apply button type is not "button"').toBe(expectedButtonType); })); it('Should emit the filtering event when applying filters.', fakeAsync(() => { - spyOn(grid.filtering, 'emit'); + vi.spyOn(grid.filtering, 'emit'); // Open Advanced Filtering dialog. grid.openAdvancedFilteringDialog(); @@ -273,7 +264,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { fix.detectChanges(); // Ensure that filtering event was emitted with expected arguments - expect(grid.filtering.emit).toHaveBeenCalledWith(jasmine.objectContaining({ + expect(grid.filtering.emit).toHaveBeenCalledWith(expect.objectContaining({ owner: grid, filteringExpressions: grid.advancedFilteringExpressionsTree, cancel: false @@ -281,7 +272,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { })); it('Should cancel filtering if cancel is set to true.', fakeAsync(() => { - spyOn(grid.filtering, 'emit').and.callFake((args: IFilteringEventArgs) => { + vi.spyOn(grid.filtering, 'emit').mockImplementation((args: IFilteringEventArgs) => { args.cancel = true; }); @@ -311,15 +302,15 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { // Ensure that cancel flag is true expect(grid.filtering.emit).toHaveBeenCalled(); - const emittedArgs: IFilteringEventArgs = (grid.filtering.emit as jasmine.Spy).calls.mostRecent().args[0]; - expect(emittedArgs.cancel).toBeTrue(); + const emittedArgs: IFilteringEventArgs = vi.mocked((grid.filtering.emit as Mock)).mock.lastCall[0]; + expect(emittedArgs.cancel).toBe(true); // Ensure that grid.filteredData is null expect(grid.filteredData).toEqual(null); })); it('Should emit the filteringDone event when applying filters.', fakeAsync(() => { - spyOn(grid.filteringDone, 'emit'); + vi.spyOn(grid.filteringDone, 'emit'); // Open Advanced Filtering dialog. grid.openAdvancedFilteringDialog(); @@ -979,7 +970,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { fix.detectChanges(); const rows = GridFunctions.getRows(fix); - expect(rows.length).toEqual(3, 'Wrong filtered rows count'); + expect(rows.length, 'Wrong filtered rows count').toEqual(3); })); it('Should filter by cells formatted data when using FormattedValuesFilteringStrategy with rowData', fakeAsync(() => { @@ -1013,7 +1004,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { fix.detectChanges(); const rows = GridFunctions.getRows(fix); - expect(rows.length).toEqual(1, 'Wrong filtered rows count'); + expect(rows.length, 'Wrong filtered rows count').toEqual(1); })); it('DateTime: Should set editorOptions.dateTimeFormat prop as inputFormat for the filter value editor', fakeAsync(() => { @@ -1021,7 +1012,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { releaseDateColumn.dataType = 'dateTime'; releaseDateColumn.editorOptions = { dateTimeFormat: 'dd-MM-yyyy HH:mm aaaaa' - } + }; fix.detectChanges(); grid.openAdvancedFilteringDialog(); @@ -1052,7 +1043,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { releaseDateColumn.dataType = 'dateTime'; releaseDateColumn.pipeArgs = { format: 'dd-MM-yyyy HH:mm aaaaa' - } + }; fix.detectChanges(); grid.openAdvancedFilteringDialog(); @@ -1078,7 +1069,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { const releaseTimeColumn = grid.getColumnByName('ReleaseTime'); releaseTimeColumn.editorOptions = { dateTimeFormat: 'hh:mm' - } + }; fix.detectChanges(); grid.openAdvancedFilteringDialog(); @@ -1103,7 +1094,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { const releaseTimeColumn = grid.getColumnByName('ReleaseTime'); releaseTimeColumn.pipeArgs = { format: 'hh:mm' - } + }; fix.detectChanges(); grid.openAdvancedFilteringDialog(); @@ -1181,7 +1172,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { flush(); // Spy for error messages in the console - const consoleSpy = spyOn(console, 'error'); + const consoleSpy = vi.spyOn(console, 'error'); // Open Advanced Filtering dialog GridFunctions.clickAdvancedFilteringButton(fixture); @@ -1254,7 +1245,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { expect(grid.advancedFilteringExpressionsTree.filteringOperands.length).toEqual(3); expect(numberOfFilters).toEqual(3); })); - }) + }); describe('Localization - ', () => { it('Should correctly change resource strings for Advanced Filtering dialog.', fakeAsync(() => { @@ -1333,7 +1324,8 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { }); describe('Column groups - ', () => { - let fix; let grid: IgxGridComponent; + let fix; + let grid: IgxGridComponent; beforeEach(fakeAsync(() => { fix = TestBed.createComponent(IgxGridAdvancedFilteringColumnGroupComponent); grid = fix.componentInstance.grid; @@ -1362,7 +1354,8 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { }); describe('External - ', () => { - let fix; let grid: IgxGridComponent; + let fix; + let grid: IgxGridComponent; beforeEach(fakeAsync(() => { fix = TestBed.createComponent(IgxGridExternalAdvancedFilteringComponent); grid = fix.componentInstance.grid; @@ -1415,7 +1408,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { fix = TestBed.createComponent(IgxHierGridExternalAdvancedFilteringComponent); const hgrid: IgxHierarchicalGridComponent = fix.componentInstance.hgrid; fix.detectChanges(); - spyOn(console, 'error'); + vi.spyOn(console, 'error'); const advFilterDialog = fix.nativeElement.querySelector('.igx-advanced-filter'); const applyFilterButton: any = Array.from(advFilterDialog.querySelectorAll('button')) @@ -1425,8 +1418,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { tick(100); fix.detectChanges(); - UIInteractions.simulatePointerEvent('pointerenter', - hgrid.nativeElement.querySelectorAll('igx-hierarchical-grid-cell')[0], 5, 5); + UIInteractions.simulatePointerEvent('pointerenter', hgrid.nativeElement.querySelectorAll('igx-hierarchical-grid-cell')[0], 5, 5); fix.detectChanges(); expect(console.error).not.toHaveBeenCalled(); @@ -1435,7 +1427,8 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { }); describe('Expression tree bindings - ', () => { - let fix; let grid: IgxGridComponent; + let fix; + let grid: IgxGridComponent; beforeEach(fakeAsync(() => { fix = TestBed.createComponent(IgxGridAdvancedFilteringBindingComponent); fix.detectChanges(); @@ -1493,7 +1486,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { })); it('should correctly filter with a deserialized expression tree.', fakeAsync(() => { - const errorSpy = spyOn(console, 'error'); + const errorSpy = vi.spyOn(console, 'error'); expect(errorSpy).not.toHaveBeenCalled(); @@ -1503,7 +1496,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { })); it('should correctly filter with a declared IFilteringExpressionsTree object.', fakeAsync(() => { - const errorSpy = spyOn(console, 'error'); + const errorSpy = vi.spyOn(console, 'error'); fix.componentInstance.grid.advancedFilteringExpressionsTree = fix.componentInstance.filterTreeObject; fix.detectChanges(); expect(errorSpy).not.toHaveBeenCalled(); @@ -1514,7 +1507,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { })); it('should correctly filter when binding to a declared IFilteringExpressionsTree object.', fakeAsync(() => { - const errorSpy = spyOn(console, 'error'); + const errorSpy = vi.spyOn(console, 'error'); fix.componentInstance.filterTree = fix.componentInstance.filterTreeObject; fix.detectChanges(); @@ -1556,7 +1549,8 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}`))[0].nativeElement; const dropdownValues: string[] = QueryBuilderFunctions.getQueryBuilderSelectDropdownItems(queryBuilderElement).map((x: any) => x.innerText); const expectedValues = ['Contains', 'Does Not Contain', 'Starts With', 'Ends With', 'Equals', - 'Does Not Equal', 'Empty', 'Not Empty', 'Null', 'Not Null', 'In', 'Not In'];; + 'Does Not Equal', 'Empty', 'Not Empty', 'Null', 'Not Null', 'In', 'Not In']; + ; expect(dropdownValues).toEqual(expectedValues); // Close Advanced Filtering dialog. @@ -1585,7 +1579,8 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}`))[2].nativeElement; const dropdownValues: string[] = QueryBuilderFunctions.getQueryBuilderSelectDropdownItems(queryBuilderElement).map((x: any) => x.innerText); const expectedValues = ['Contains', 'Does Not Contain', 'Starts With', 'Ends With', 'Equals', - 'Does Not Equal', 'Empty', 'Not Empty', 'Null', 'Not Null'];; + 'Does Not Equal', 'Empty', 'Not Empty', 'Null', 'Not Null']; + ; expect(dropdownValues).toEqual(expectedValues); // Close Advanced Filtering dialog. @@ -1688,7 +1683,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { tick(200); fix.detectChanges(); // Spy for error messages in the console - const consoleSpy = spyOn(console, 'error'); + const consoleSpy = vi.spyOn(console, 'error'); // Apply advanced filter through API. const innerTree = new FilteringExpressionsTree(0, undefined, 'childData', ['ID']); innerTree.filteringOperands.push({ @@ -1720,7 +1715,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { tick(200); fix.detectChanges(); // Spy for error messages in the console - const consoleSpy = spyOn(console, 'error'); + const consoleSpy = vi.spyOn(console, 'error'); const innerTree = new FilteringExpressionsTree(0, undefined, 'childData', ['ID']); innerTree.filteringOperands.push({ @@ -1780,7 +1775,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { } ] } - ] + ]; fixture.detectChanges(); hierarchicalGrid.openAdvancedFilteringDialog(); @@ -1915,8 +1910,8 @@ const verifyElementIsInExpressionsContainerView = (fix, element: HTMLElement) => const elementRect = element.getBoundingClientRect(); const exprContainer: HTMLElement = QueryBuilderFunctions.getQueryBuilderExpressionsContainer(fix) as HTMLElement; const exprContainerRect = exprContainer.getBoundingClientRect(); - expect(elementRect.top >= exprContainerRect.top).toBe(true, 'top is not in view'); - expect(elementRect.bottom <= exprContainerRect.bottom).toBe(true, 'bottom is not in view'); - expect(elementRect.left >= exprContainerRect.left).toBe(true, 'left is not in view'); - expect(elementRect.right <= exprContainerRect.right).toBe(true, 'right is not in view'); + expect(elementRect.top >= exprContainerRect.top, 'top is not in view').toBe(true); + expect(elementRect.bottom <= exprContainerRect.bottom, 'bottom is not in view').toBe(true); + expect(elementRect.left >= exprContainerRect.left, 'left is not in view').toBe(true); + expect(elementRect.right <= exprContainerRect.right, 'right is not in view').toBe(true); }; diff --git a/projects/igniteui-angular/grids/grid/src/grid-filtering-ui.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-filtering-ui.spec.ts index 543cd2df029..936c44f2861 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-filtering-ui.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-filtering-ui.spec.ts @@ -16,22 +16,7 @@ import localeDe from '@angular/common/locales/de'; import localeFr from '@angular/common/locales/fr'; import localeBg from '@angular/common/locales/bg'; import { SampleTestData } from '../../../test-utils/sample-test-data.spec'; -import { - IgxGridFilteringComponent, - IgxGridFilteringScrollComponent, - IgxGridFilteringMCHComponent, - IgxGridFilteringTemplateComponent, - IgxGridFilteringESFEmptyTemplatesComponent, - IgxGridFilteringESFTemplatesComponent, - IgxGridFilteringESFLoadOnDemandComponent, - CustomFilteringStrategyComponent, - IgxGridExternalESFComponent, - IgxGridExternalESFTemplateComponent, - IgxGridDatesFilteringComponent, - LoadOnDemandFilterStrategy, - IgxGridFilteringNumericComponent, - IgxGridConditionalFilteringComponent -} from '../../../test-utils/grid-samples.spec'; +import { IgxGridFilteringComponent, IgxGridFilteringScrollComponent, IgxGridFilteringMCHComponent, IgxGridFilteringTemplateComponent, IgxGridFilteringESFEmptyTemplatesComponent, IgxGridFilteringESFTemplatesComponent, IgxGridFilteringESFLoadOnDemandComponent, CustomFilteringStrategyComponent, IgxGridExternalESFComponent, IgxGridExternalESFTemplateComponent, IgxGridDatesFilteringComponent, LoadOnDemandFilterStrategy, IgxGridFilteringNumericComponent, IgxGridConditionalFilteringComponent } from '../../../test-utils/grid-samples.spec'; import { GridSelectionMode, FilterMode } from 'igniteui-angular/grids/core'; import { ControlsFunction } from '../../../test-utils/controls-functions.spec'; import { setElementSize } from '../../../test-utils/helper-utils.spec'; @@ -40,6 +25,7 @@ import { IgxDateTimeEditorDirective } from 'igniteui-angular/directives'; import { IgxTimePickerComponent } from 'igniteui-angular/time-picker'; import { IgxChipComponent, IgxBadgeComponent, IgxDatePickerComponent, IgxCalendarComponent, IgxIconComponent } from 'igniteui-angular'; import { HelperTestFunctions } from '../../../test-utils/calendar-helper-utils'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const DEBOUNCE_TIME = 30; const FILTER_UI_ROW = 'igx-grid-filtering-row'; @@ -701,80 +687,78 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { expect(input.nativeElement.value).toMatch(''); })); - it('should render Filter chip for filterable columns and render empty cell for a column when filterable is set to false', - fakeAsync(() => { - grid.width = '1500px'; - fix.detectChanges(); + it('should render Filter chip for filterable columns and render empty cell for a column when filterable is set to false', fakeAsync(() => { + grid.width = '1500px'; + fix.detectChanges(); - const filteringCells = GridFunctions.getFilteringCells(fix); - const filteringChips = GridFunctions.getFilteringChips(fix); - expect(filteringCells.length).toBe(8); - expect(filteringChips.length).toBe(7); + const filteringCells = GridFunctions.getFilteringCells(fix); + const filteringChips = GridFunctions.getFilteringChips(fix); + expect(filteringCells.length).toBe(8); + expect(filteringChips.length).toBe(7); - let idCellChips = GridFunctions.getFilteringChipPerIndex(fix, 0); - expect(idCellChips.length).toBe(0); + let idCellChips = GridFunctions.getFilteringChipPerIndex(fix, 0); + expect(idCellChips.length).toBe(0); - grid.getColumnByName('ID').filterable = true; - fix.detectChanges(); - // tick(100); - - idCellChips = GridFunctions.getFilteringChipPerIndex(fix, 0); - expect(idCellChips.length).toBe(1); - })); - - it('should render correct input and dropdown in filter row for different column types', - fakeAsync(/** showHideArrowButtons rAF */() => { - pending('This should be tested in the e2e test'); - const filteringCells = fix.debugElement.queryAll(By.css(FILTER_UI_CELL)); - const stringCellChip = filteringCells[1].query(By.css('igx-chip')); - const numberCellChip = filteringCells[2].query(By.css('igx-chip')); - const boolCellChip = filteringCells[3].query(By.css('igx-chip')); - const dateCellChip = filteringCells[4].query(By.css('igx-chip')); - // open for string - stringCellChip.triggerEventHandler('click', null); - fix.detectChanges(); + grid.getColumnByName('ID').filterable = true; + fix.detectChanges(); + // tick(100); - checkUIForType('string', fix.debugElement); + idCellChips = GridFunctions.getFilteringChipPerIndex(fix, 0); + expect(idCellChips.length).toBe(1); + })); - // close - let filterUIRow = fix.debugElement.query(By.css(FILTER_UI_ROW)); - let close = filterUIRow.queryAll(By.css('button'))[1]; - close.nativeElement.click(); - fix.detectChanges(); + it('should render correct input and dropdown in filter row for different column types', fakeAsync(/** showHideArrowButtons rAF */ () => { + pending('This should be tested in the e2e test'); + const filteringCells = fix.debugElement.queryAll(By.css(FILTER_UI_CELL)); + const stringCellChip = filteringCells[1].query(By.css('igx-chip')); + const numberCellChip = filteringCells[2].query(By.css('igx-chip')); + const boolCellChip = filteringCells[3].query(By.css('igx-chip')); + const dateCellChip = filteringCells[4].query(By.css('igx-chip')); + // open for string + stringCellChip.triggerEventHandler('click', null); + fix.detectChanges(); - // open for number - numberCellChip.nativeElement.click(); - fix.detectChanges(); - checkUIForType('number', fix.debugElement); + checkUIForType('string', fix.debugElement); - // close - filterUIRow = fix.debugElement.query(By.css(FILTER_UI_ROW)); - close = filterUIRow.queryAll(By.css('button'))[1]; - close.nativeElement.click(); - fix.detectChanges(); + // close + let filterUIRow = fix.debugElement.query(By.css(FILTER_UI_ROW)); + let close = filterUIRow.queryAll(By.css('button'))[1]; + close.nativeElement.click(); + fix.detectChanges(); - // open for date - dateCellChip.nativeElement.click(); - fix.detectChanges(); - checkUIForType('date', fix.debugElement); + // open for number + numberCellChip.nativeElement.click(); + fix.detectChanges(); + checkUIForType('number', fix.debugElement); - // close - filterUIRow = fix.debugElement.query(By.css(FILTER_UI_ROW)); - close = filterUIRow.queryAll(By.css('button'))[1]; - close.nativeElement.click(); - fix.detectChanges(); + // close + filterUIRow = fix.debugElement.query(By.css(FILTER_UI_ROW)); + close = filterUIRow.queryAll(By.css('button'))[1]; + close.nativeElement.click(); + fix.detectChanges(); - // open for bool - boolCellChip.nativeElement.click(); - fix.detectChanges(); - checkUIForType('bool', fix.debugElement); + // open for date + dateCellChip.nativeElement.click(); + fix.detectChanges(); + checkUIForType('date', fix.debugElement); - // close - filterUIRow = fix.debugElement.query(By.css(FILTER_UI_ROW)); - close = filterUIRow.queryAll(By.css('button'))[1]; - close.nativeElement.click(); - fix.detectChanges(); - })); + // close + filterUIRow = fix.debugElement.query(By.css(FILTER_UI_ROW)); + close = filterUIRow.queryAll(By.css('button'))[1]; + close.nativeElement.click(); + fix.detectChanges(); + + // open for bool + boolCellChip.nativeElement.click(); + fix.detectChanges(); + checkUIForType('bool', fix.debugElement); + + // close + filterUIRow = fix.debugElement.query(By.css(FILTER_UI_ROW)); + close = filterUIRow.queryAll(By.css('button'))[1]; + close.nativeElement.click(); + fix.detectChanges(); + })); it('should apply multiple conditions to grid immediately while the filter row is still open', fakeAsync(() => { pending('This should be tested in the e2e test'); @@ -871,30 +855,29 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { expect(grid.rowList.length).toEqual(8); })); - it('should not render chip in header if condition that requires value is applied and then value is cleared in filter row.', - fakeAsync(() => { - grid.filter('ProductName', 'I', IgxStringFilteringOperand.instance().condition('startsWith')); - fix.detectChanges(); + it('should not render chip in header if condition that requires value is applied and then value is cleared in filter row.', fakeAsync(() => { + grid.filter('ProductName', 'I', IgxStringFilteringOperand.instance().condition('startsWith')); + fix.detectChanges(); - GridFunctions.clickFilterCellChip(fix, 'ProductName'); - tick(100); - fix.detectChanges(); + GridFunctions.clickFilterCellChip(fix, 'ProductName'); + tick(100); + fix.detectChanges(); - const clearButton = GridFunctions.getFilterRowInputClearIcon(fix); - clearButton.triggerEventHandler('click', null); - tick(100); - fix.detectChanges(); + const clearButton = GridFunctions.getFilterRowInputClearIcon(fix); + clearButton.triggerEventHandler('click', null); + tick(100); + fix.detectChanges(); - GridFunctions.closeFilterRow(fix); - tick(100); - fix.detectChanges(); + GridFunctions.closeFilterRow(fix); + tick(100); + fix.detectChanges(); - // check no condition is applied - expect(grid.rowList.length).toEqual(8); + // check no condition is applied + expect(grid.rowList.length).toEqual(8); - const filteringChips = GridFunctions.getFilteringChips(fix); - expect(GridFunctions.getChipText(filteringChips[1])).toEqual('Filter'); - })); + const filteringChips = GridFunctions.getFilteringChips(fix); + expect(GridFunctions.getChipText(filteringChips[1])).toEqual('Filter'); + })); it('should reset the filter chips area when changing grid width', fakeAsync(() => { grid.width = '300px'; @@ -1481,7 +1464,7 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const chipArea = filteringRow.query(By.css('igx-chip-area')); expect(GridFunctions.getFilterRowLeftArrowButton(fix)).toBeNull(); expect(GridFunctions.getFilterRowRightArrowButton(fix)).toBeNull(); - expect(chipArea).toBeNull('chipArea is present'); + expect(chipArea, 'chipArea is present').toBeNull(); })); it('Should remove first chip and filter by the remaining ones.', fakeAsync(() => { @@ -1546,8 +1529,7 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { let chip = GridFunctions.getFilterChipsForColumn('ReleaseDate', fix)[0].nativeElement; let chipRect = chip.getBoundingClientRect(); let gridRect = grid.nativeElement.getBoundingClientRect(); - expect(chipRect.right > gridRect.right).toBe(true, - 'chip should not be fully visible and thus not within grid'); + expect(chipRect.right > gridRect.right, 'chip should not be fully visible and thus not within grid').toBe(true); GridFunctions.clickFilterCellChipUI(fix, 'ReleaseDate'); await wait(100); @@ -1561,8 +1543,7 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { chip = GridFunctions.getFilterChipsForColumn('ReleaseDate', fix)[0].nativeElement; chipRect = chip.getBoundingClientRect(); gridRect = grid.nativeElement.getBoundingClientRect(); - expect(chipRect.left > gridRect.left && chipRect.right < gridRect.right).toBe(true, - 'chip should be fully visible and within grid'); + expect(chipRect.left > gridRect.left && chipRect.right < gridRect.right, 'chip should be fully visible and within grid').toBe(true); }); it('Verify condition chips are scrolled into/(out of) view by using arrow buttons.', (async () => { @@ -1727,34 +1708,33 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { expect(conditionChips.length).toBe(0); })); - it(`Should open/close filterRow for respective column when pressing 'ctrl + shift + l' on its filterCell chip.`, - fakeAsync(() => { - // Verify filterRow is not opened. - let filterUIRow = grid.theadRow.filterRow; - expect(filterUIRow).toBeUndefined(); + it(`Should open/close filterRow for respective column when pressing 'ctrl + shift + l' on its filterCell chip.`, fakeAsync(() => { + // Verify filterRow is not opened. + let filterUIRow = grid.theadRow.filterRow; + expect(filterUIRow).toBeUndefined(); - const releaseDateColumn = GridFunctions.getColumnHeader('ReleaseDate', fix); - UIInteractions.simulateClickAndSelectEvent(releaseDateColumn); - fix.detectChanges(); + const releaseDateColumn = GridFunctions.getColumnHeader('ReleaseDate', fix); + UIInteractions.simulateClickAndSelectEvent(releaseDateColumn); + fix.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem('l', releaseDateColumn.nativeElement, true, false, true, true); - tick(200); - fix.detectChanges(); + UIInteractions.triggerKeyDownEvtUponElem('l', releaseDateColumn.nativeElement, true, false, true, true); + tick(200); + fix.detectChanges(); - // Verify filterRow is opened for the 'ReleaseDate' column. - filterUIRow = grid.theadRow.filterRow; - expect(filterUIRow).toBeDefined(); - const headerGroupsFiltering = grid.headerGroupsList.filter(group => group.isFiltered); - expect(headerGroupsFiltering.length).toBe(1); - expect(headerGroupsFiltering[0].column.field).toMatch('ReleaseDate'); + // Verify filterRow is opened for the 'ReleaseDate' column. + filterUIRow = grid.theadRow.filterRow; + expect(filterUIRow).toBeDefined(); + const headerGroupsFiltering = grid.headerGroupsList.filter(group => group.isFiltered); + expect(headerGroupsFiltering.length).toBe(1); + expect(headerGroupsFiltering[0].column.field).toMatch('ReleaseDate'); - UIInteractions.triggerKeyDownEvtUponElem('l', filterUIRow.nativeElement, true, false, true, true); - tick(200); - fix.detectChanges(); + UIInteractions.triggerKeyDownEvtUponElem('l', filterUIRow.nativeElement, true, false, true, true); + tick(200); + fix.detectChanges(); - filterUIRow = grid.theadRow.filterRow; - expect(filterUIRow).toBeUndefined(); - })); + filterUIRow = grid.theadRow.filterRow; + expect(filterUIRow).toBeUndefined(); + })); it('Should navigate to first cell of grid when pressing \'Tab\' on the last filterCell chip.', fakeAsync(() => { pending('Should be fixed with headers navigation'); @@ -1857,7 +1837,7 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { fix.detectChanges(); // Verify chips count. - expect(GridFunctions.getFilterChipsForColumn('ProductName', fix).length).toBe(3, 'incorrect chips count'); + expect(GridFunctions.getFilterChipsForColumn('ProductName', fix).length, 'incorrect chips count').toBe(3); // Verify last chip text. let lastFilterCellChip = GridFunctions.getFilterChipsForColumn('ProductName', fix)[2]; @@ -1869,7 +1849,7 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { fix.detectChanges(); // Verify chips count. - expect(GridFunctions.getFilterChipsForColumn('ProductName', fix).length).toBe(2, 'incorrect chips count'); + expect(GridFunctions.getFilterChipsForColumn('ProductName', fix).length, 'incorrect chips count').toBe(2); // Verify new last chip text. lastFilterCellChip = GridFunctions.getFilterChipsForColumn('ProductName', fix)[1]; expect(GridFunctions.getChipText(lastFilterCellChip)).toBe('e'); @@ -1905,7 +1885,7 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { // Verify first chip is selected (in edit mode). const chipDiv = GridFunctions.getFilterConditionChip(fix, 0).querySelector('.igx-chip__item'); - expect(chipDiv.classList.contains('igx-chip__item--selected')).toBe(true, 'chip is not selected'); + expect(chipDiv.classList.contains('igx-chip__item--selected'), 'chip is not selected').toBe(true); })); it('Should not throw error when deleting the last chip', (async () => { @@ -1943,10 +1923,10 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { expect(chips.length).toBe(4); const leftArrowButton = GridFunctions.getFilterRowLeftArrowButton(fix).nativeElement; - expect(leftArrowButton).toBeTruthy('Left scroll arrow should be visible'); + expect(leftArrowButton, 'Left scroll arrow should be visible').toBeTruthy(); const rightArrowButton = GridFunctions.getFilterRowRightArrowButton(fix).nativeElement; - expect(rightArrowButton).toBeTruthy('Right scroll arrow should be visible'); + expect(rightArrowButton, 'Right scroll arrow should be visible').toBeTruthy(); expect(grid.rowList.length).toBe(2); let chipToRemove = filterUIRow.componentInstance.expressionsList[3]; @@ -2049,17 +2029,17 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { // Verify the the filterRow is closed. const filterUIRow = fix.debugElement.query(By.css(FILTER_UI_ROW)); - expect(filterUIRow).toBeNull('filterRow is visible'); + expect(filterUIRow, 'filterRow is visible').toBeNull(); // Verify the ESF icons are visible. const thead = grid.theadRow.nativeElement; const filterIcons = thead.querySelectorAll('.igx-excel-filter__icon'); - expect(filterIcons.length).toEqual(6, 'incorrect esf filter icons count'); + expect(filterIcons.length, 'incorrect esf filter icons count').toEqual(6); // Verify the condition was submitted. const header = GridFunctions.getColumnHeader('ProductName', fix); const activeFilterIcon = header.nativeElement.querySelector('.igx-excel-filter__icon--filtered'); - expect(activeFilterIcon).toBeDefined('no active filter icon was found'); + expect(activeFilterIcon, 'no active filter icon was found').toBeDefined(); })); it('Should clear non-unary conditions with null searchVal when close', fakeAsync(() => { @@ -2107,7 +2087,7 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const chip = GridFunctions.getFilterConditionChip(fix, 0); const chipDiv = chip.querySelector('.igx-chip__item'); - expect(chipDiv.classList.contains('igx-chip__item--selected')).toBe(true, 'initial chip is committed'); + expect(chipDiv.classList.contains('igx-chip__item--selected'), 'initial chip is committed').toBe(true); // Focus out grid.nativeElement.focus(); @@ -2115,8 +2095,8 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { tick(200); fix.detectChanges(); - expect(chipDiv.classList.contains('igx-chip__item--selected')).toBe(false, 'initial chip is not committed'); - expect(input.value).toBe('', 'initial input value is present and not committed'); + expect(chipDiv.classList.contains('igx-chip__item--selected'), 'initial chip is not committed').toBe(false); + expect(input.value, 'initial input value is present and not committed').toBe(''); chip.click(); tick(200); @@ -2155,21 +2135,21 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { tick(200); fix.detectChanges(); - expect(chipDiv.classList.contains('igx-chip__item--selected')).toBe(true, 'chip is committed'); + expect(chipDiv.classList.contains('igx-chip__item--selected'), 'chip is committed').toBe(true); // Focus out grid.nativeElement.focus(); grid.filteringRow.onInputGroupFocusout(); tick(200); fix.detectChanges(); - expect(chipDiv.classList.contains('igx-chip__item--selected')).toBe(false, 'chip is selected'); + expect(chipDiv.classList.contains('igx-chip__item--selected'), 'chip is selected').toBe(false); // Check if we still have only one committed chip const chipsLength = GridFunctions.getAllFilterConditionChips(fix).length; - expect(chipsLength).toBe(1, 'there is more than one chip'); - expect(chipDiv.classList.contains('igx-chip__item--selected')).toBe(false, 'chip is not committed'); - expect(input.value).toBe('', 'input value is present and not committed'); + expect(chipsLength, 'there is more than one chip').toBe(1); + expect(chipDiv.classList.contains('igx-chip__item--selected'), 'chip is not committed').toBe(false); + expect(input.value, 'input value is present and not committed').toBe(''); })); it('should not retain expression values in cell filter after calling grid clearFilter() method.', fakeAsync(() => { @@ -2336,11 +2316,11 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { fix.detectChanges(); const chips = filterRow.queryAll(By.directive(IgxChipComponent)); - expect(chips.length).toEqual(0, 'No chips should be present'); + expect(chips.length, 'No chips should be present').toEqual(0); })); it('Should not throw error when pressing Backspace in empty dateTime filter.', fakeAsync(() => { - spyOn(console, 'error'); + vi.spyOn(console, 'error'); GridFunctions.clickFilterCellChipUI(fix, 'ReleaseDateTime'); tick(DEBOUNCE_TIME); @@ -2359,7 +2339,7 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { })); it('Should not throw error when pressing Arrow keys in filter when focus is outside of input.', fakeAsync(() => { - spyOn(console, 'error'); + vi.spyOn(console, 'error'); GridFunctions.clickFilterCellChipUI(fix, 'ProductName'); fix.detectChanges(); @@ -2399,24 +2379,23 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { })); // Filtering + Moving - it('should move chip under the correct column when column is moved and filter row should open for correct column.', - fakeAsync(() => { - grid.filter('ProductName', 'Angular', IgxStringFilteringOperand.instance().condition('contains')); - fix.detectChanges(); + it('should move chip under the correct column when column is moved and filter row should open for correct column.', fakeAsync(() => { + grid.filter('ProductName', 'Angular', IgxStringFilteringOperand.instance().condition('contains')); + fix.detectChanges(); - // swap columns - const stringCol = grid.getColumnByName('ProductName'); - const numberCol = grid.getColumnByName('Downloads'); - grid.moveColumn(stringCol, numberCol); - tick(); - fix.detectChanges(); + // swap columns + const stringCol = grid.getColumnByName('ProductName'); + const numberCol = grid.getColumnByName('Downloads'); + grid.moveColumn(stringCol, numberCol); + tick(); + fix.detectChanges(); - // check UI in filter cell is correct after moving - const filteringCells = GridFunctions.getFilteringCells(fix); + // check UI in filter cell is correct after moving + const filteringCells = GridFunctions.getFilteringCells(fix); - expect(GridFunctions.getChipText(filteringCells[2])).toEqual('Angular'); - expect(GridFunctions.getChipText(filteringCells[1])).toEqual('Filter'); - })); + expect(GridFunctions.getChipText(filteringCells[2])).toEqual('Angular'); + expect(GridFunctions.getChipText(filteringCells[1])).toEqual('Filter'); + })); // Filtering + Hiding it('should not display filter cell for hidden columns and chips should show under correct column.', fakeAsync(() => { @@ -2464,7 +2443,7 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { // Check that the filterRow is closed filterUIRow = fix.debugElement.query(By.css(FILTER_UI_ROW)); expect(filterUIRow).toBeNull(); - expect(grid.rowList.length).toBe(3, 'filter is not applied'); + expect(grid.rowList.length, 'filter is not applied').toBe(3); })); it('Should keep existing column filter after hiding another column.', fakeAsync(() => { @@ -2682,7 +2661,7 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { })); it('UI focusing grid\'s body content does not throw a console error after filtering. (issue 8930)', fakeAsync(() => { - spyOn(console, 'error'); + vi.spyOn(console, 'error'); GridFunctions.clickFilterCellChipUI(fix, 'ProductName'); fix.detectChanges(); @@ -2754,48 +2733,47 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { expect(frElem.offsetTop + frElem.clientHeight + 1).toEqual(thead.clientHeight); })); - it('should position filter row and chips correctly when grid has column groups and one is hidden.', - fakeAsync(() => { - const filteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And, 'ProductName'); - const expression = { - fieldName: 'ProductName', - searchVal: 'Ignite', - condition: IgxStringFilteringOperand.instance().condition('startsWith'), - conditionName: 'startsWith' - }; - filteringExpressionsTree.filteringOperands.push(expression); - grid.filteringExpressionsTree = filteringExpressionsTree; - fix.detectChanges(); - let filteringCells = GridFunctions.getFilteringCells(fix); - expect(filteringCells.length).toEqual(6); + it('should position filter row and chips correctly when grid has column groups and one is hidden.', fakeAsync(() => { + const filteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And, 'ProductName'); + const expression = { + fieldName: 'ProductName', + searchVal: 'Ignite', + condition: IgxStringFilteringOperand.instance().condition('startsWith'), + conditionName: 'startsWith' + }; + filteringExpressionsTree.filteringOperands.push(expression); + grid.filteringExpressionsTree = filteringExpressionsTree; + fix.detectChanges(); + let filteringCells = GridFunctions.getFilteringCells(fix); + expect(filteringCells.length).toEqual(6); - const groupCol = grid.getColumnByName('General'); - groupCol.hidden = true; - fix.detectChanges(); + const groupCol = grid.getColumnByName('General'); + groupCol.hidden = true; + fix.detectChanges(); - filteringCells = GridFunctions.getFilteringCells(fix); - expect(filteringCells.length).toEqual(1); + filteringCells = GridFunctions.getFilteringCells(fix); + expect(filteringCells.length).toEqual(1); - GridFunctions.clickFilterCellChip(fix, 'AnotherField'); - fix.detectChanges(); - grid.cdr.detectChanges(); + GridFunctions.clickFilterCellChip(fix, 'AnotherField'); + fix.detectChanges(); + grid.cdr.detectChanges(); - // check if it is positioned at the bottom of the thead. - const theadWrapper = grid.theadRow.nativeElement.firstElementChild; - const filteringRow = fix.debugElement.query(By.directive(IgxGridFilteringRowComponent)); - const frElem = filteringRow.nativeElement; - expect(frElem.offsetTop + frElem.clientHeight).toEqual(theadWrapper.clientHeight); + // check if it is positioned at the bottom of the thead. + const theadWrapper = grid.theadRow.nativeElement.firstElementChild; + const filteringRow = fix.debugElement.query(By.directive(IgxGridFilteringRowComponent)); + const frElem = filteringRow.nativeElement; + expect(frElem.offsetTop + frElem.clientHeight).toEqual(theadWrapper.clientHeight); - GridFunctions.closeFilterRow(fix); + GridFunctions.closeFilterRow(fix); - groupCol.hidden = false; - fix.detectChanges(); + groupCol.hidden = false; + fix.detectChanges(); - filteringCells = GridFunctions.getFilteringCells(fix); - expect(filteringCells.length).toEqual(6); + filteringCells = GridFunctions.getFilteringCells(fix); + expect(filteringCells.length).toEqual(6); - expect(GridFunctions.getChipText(filteringCells[1])).toEqual('Ignite'); - })); + expect(GridFunctions.getChipText(filteringCells[1])).toEqual('Ignite'); + })); it('Should size grid correctly if enable/disable filtering in run time - MCH.', fakeAsync(() => { const head = grid.theadRow.nativeElement; @@ -2816,7 +2794,8 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { }); describe(null, () => { - let fix; let grid; + let fix; + let grid; beforeEach(fakeAsync(() => { fix = TestBed.createComponent(IgxGridFilteringScrollComponent); grid = fix.componentInstance.grid; @@ -2854,24 +2833,16 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { it('Should render custom filter template instead of default one.', fakeAsync(() => { // Verify default filter template is not present. - expect(GridFunctions.getFilterCell(fix, 'ProductName').query(By.css('.igx-filtering-chips'))).toBeNull( - '\'ProductName\' default filter chips area template was found.'); - expect(GridFunctions.getFilterCell(fix, 'Downloads').query(By.css('.igx-filtering-chips'))).toBeNull( - '\'Downloads\' default filter chips area template was found.'); - expect(GridFunctions.getFilterCell(fix, 'Released').query(By.css('.igx-filtering-chips'))).toBeNull( - '\'Released\' default filter chips area template was found.'); - expect(GridFunctions.getFilterCell(fix, 'ReleaseDate').query(By.css('.igx-filtering-chips'))).toBeNull( - '\'ReleaseDate\' default filter chips area template was found.'); + expect(GridFunctions.getFilterCell(fix, 'ProductName').query(By.css('.igx-filtering-chips')), '\'ProductName\' default filter chips area template was found.').toBeNull(); + expect(GridFunctions.getFilterCell(fix, 'Downloads').query(By.css('.igx-filtering-chips')), '\'Downloads\' default filter chips area template was found.').toBeNull(); + expect(GridFunctions.getFilterCell(fix, 'Released').query(By.css('.igx-filtering-chips')), '\'Released\' default filter chips area template was found.').toBeNull(); + expect(GridFunctions.getFilterCell(fix, 'ReleaseDate').query(By.css('.igx-filtering-chips')), '\'ReleaseDate\' default filter chips area template was found.').toBeNull(); // Verify the custom filter template is present. - expect(GridFunctions.getFilterCell(fix, 'ProductName').query(By.css('.custom-filter'))).not.toBeNull( - '\'ProductName\' customer filter template was not found.'); - expect(GridFunctions.getFilterCell(fix, 'Downloads').query(By.css('.custom-filter'))).not.toBeNull( - '\'Downloads\' customer filter template was not found.'); - expect(GridFunctions.getFilterCell(fix, 'Released').query(By.css('.custom-filter'))).not.toBeNull( - '\'Released\' customer filter template was not found.'); - expect(GridFunctions.getFilterCell(fix, 'ReleaseDate').query(By.css('.custom-filter'))).not.toBeNull( - '\'ReleaseDate\' customer filter template was not found.'); + expect(GridFunctions.getFilterCell(fix, 'ProductName').query(By.css('.custom-filter'))).not.toBeNull('\'ProductName\' customer filter template was not found.'); + expect(GridFunctions.getFilterCell(fix, 'Downloads').query(By.css('.custom-filter'))).not.toBeNull('\'Downloads\' customer filter template was not found.'); + expect(GridFunctions.getFilterCell(fix, 'Released').query(By.css('.custom-filter'))).not.toBeNull('\'Released\' customer filter template was not found.'); + expect(GridFunctions.getFilterCell(fix, 'ReleaseDate').query(By.css('.custom-filter'))).not.toBeNull('\'ReleaseDate\' customer filter template was not found.'); })); it('Should close default filter template when clicking on a column with custom one.', fakeAsync(() => { @@ -2890,7 +2861,7 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { // Expect the filter row is closed filterUIRow = fix.debugElement.query(By.css(FILTER_UI_ROW)); - expect(filterUIRow).toBeNull('Default filter template was found on a column with custom filtering.'); + expect(filterUIRow, 'Default filter template was found on a column with custom filtering.').toBeNull(); })); it('Should not prevent mousedown event when target is within the filter cell template', fakeAsync(() => { @@ -2898,7 +2869,7 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const input = filterCell.query(By.css('input')).nativeElement; const mousedownEvent = new MouseEvent('mousedown', { bubbles: true }); - const preventDefaultSpy = spyOn(mousedownEvent, 'preventDefault'); + const preventDefaultSpy = vi.spyOn(mousedownEvent, 'preventDefault'); input.dispatchEvent(mousedownEvent, { bubbles: true }); fix.detectChanges(); @@ -2910,7 +2881,7 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { const firstCell = filteringCells[0].nativeElement; const mousedownEvent = new MouseEvent('mousedown', { bubbles: true }); - const preventDefaultSpy = spyOn(mousedownEvent, 'preventDefault'); + const preventDefaultSpy = vi.spyOn(mousedownEvent, 'preventDefault'); firstCell.dispatchEvent(mousedownEvent); fix.detectChanges(); @@ -3007,180 +2978,72 @@ describe('IgxGrid - Filtering Row UI actions #grid', () => { fix.detectChanges(); grid = fix.componentInstance.grid; - spyOn(grid.filtering, 'emit'); - spyOn(grid.filteringDone, 'emit'); + vi.spyOn(grid.filtering, 'emit'); + vi.spyOn(grid.filteringDone, 'emit'); })); it('Should emit filteringDone when we clicked reset - Date column type', fakeAsync(() => { - emitFilteringDoneOnResetClick( - fix, - grid, - cal.timedelta(today, 'day', 15), - 'ReleaseDate', - IgxDateFilteringOperand.instance().condition('equals') - ); + emitFilteringDoneOnResetClick(fix, grid, cal.timedelta(today, 'day', 15), 'ReleaseDate', IgxDateFilteringOperand.instance().condition('equals')); })); it('Should emit filteringDone when we clicked reset - String column type', fakeAsync(() => { - emitFilteringDoneOnResetClick( - fix, - grid, - 'search', - 'ProductName', - IgxStringFilteringOperand.instance().condition('contains') - ); + emitFilteringDoneOnResetClick(fix, grid, 'search', 'ProductName', IgxStringFilteringOperand.instance().condition('contains')); })); it('Should emit filteringDone when we clicked reset - Number column type', fakeAsync(() => { - emitFilteringDoneOnResetClick( - fix, - grid, - 100, - 'Downloads', - IgxNumberFilteringOperand.instance().condition('equals') - ); + emitFilteringDoneOnResetClick(fix, grid, 100, 'Downloads', IgxNumberFilteringOperand.instance().condition('equals')); })); it('Should emit filteringDone when we clicked reset - Currency column type', fakeAsync(() => { - emitFilteringDoneOnResetClick( - fix, - grid, - 100000, - 'Revenue', - IgxNumberFilteringOperand.instance().condition('equals') - ); + emitFilteringDoneOnResetClick(fix, grid, 100000, 'Revenue', IgxNumberFilteringOperand.instance().condition('equals')); })); it('Should emit filteringDone when we clicked reset - DateTime column type', fakeAsync(() => { - emitFilteringDoneOnResetClick( - fix, - grid, - cal.timedelta(today, 'hour', 1), - 'ReleaseTime', - IgxDateTimeFilteringOperand.instance().condition('equals') - ); + emitFilteringDoneOnResetClick(fix, grid, cal.timedelta(today, 'hour', 1), 'ReleaseTime', IgxDateTimeFilteringOperand.instance().condition('equals')); })); it('Should emit filteringDone when clear the input of filteringUI - Date column type', fakeAsync(() => { - emitFilteringDoneOnInputClear( - fix, - grid, - cal.timedelta(today, 'day', 15), - 'ReleaseDate', - IgxDateFilteringOperand.instance().condition('equals') - ); + emitFilteringDoneOnInputClear(fix, grid, cal.timedelta(today, 'day', 15), 'ReleaseDate', IgxDateFilteringOperand.instance().condition('equals')); })); it('Should emit filteringDone when clear the input of filteringUI - String column type', fakeAsync(() => { - emitFilteringDoneOnInputClear( - fix, - grid, - 'search', - 'ProductName', - IgxStringFilteringOperand.instance().condition('contains') - ); + emitFilteringDoneOnInputClear(fix, grid, 'search', 'ProductName', IgxStringFilteringOperand.instance().condition('contains')); })); it('Should emit filteringDone when clear the input of filteringUI - Number column type', fakeAsync(() => { - emitFilteringDoneOnInputClear( - fix, - grid, - 3, - 'Downloads', - IgxNumberFilteringOperand.instance().condition('equals') - ); + emitFilteringDoneOnInputClear(fix, grid, 3, 'Downloads', IgxNumberFilteringOperand.instance().condition('equals')); })); it('Should emit filteringDone when clear the input of filteringUI - Currency column type', fakeAsync(() => { - emitFilteringDoneOnInputClear( - fix, - grid, - 100000, - 'Revenue', - IgxNumberFilteringOperand.instance().condition('equals') - ); + emitFilteringDoneOnInputClear(fix, grid, 100000, 'Revenue', IgxNumberFilteringOperand.instance().condition('equals')); })); it('Should emit filteringDone when clear the input of filteringUI - DateTime column type', fakeAsync(() => { - emitFilteringDoneOnInputClear( - fix, - grid, - cal.timedelta(today, 'hour', 1), - 'ReleaseTime', - IgxDateTimeFilteringOperand.instance().condition('equals') - ); + emitFilteringDoneOnInputClear(fix, grid, cal.timedelta(today, 'hour', 1), 'ReleaseTime', IgxDateTimeFilteringOperand.instance().condition('equals')); })); it('should update UI when chip is removed from header cell - Date column type.', fakeAsync(() => { - verifyRemoveChipFromHeader( - fix, - grid, - cal.timedelta(today, 'day', 15), - 'ReleaseDate', - IgxDateFilteringOperand.instance().condition('equals'), - 1, - 4 - ); + verifyRemoveChipFromHeader(fix, grid, cal.timedelta(today, 'day', 15), 'ReleaseDate', IgxDateFilteringOperand.instance().condition('equals'), 1, 4); })); it('should update UI when chip is removed from header cell - String column type.', fakeAsync(() => { - verifyRemoveChipFromHeader( - fix, - grid, - 'I', - 'ProductName', - IgxStringFilteringOperand.instance().condition('startsWith'), - 2, - 1 - ); + verifyRemoveChipFromHeader(fix, grid, 'I', 'ProductName', IgxStringFilteringOperand.instance().condition('startsWith'), 2, 1); })); it('should update UI when chip is removed from header cell - Number column type.', fakeAsync(() => { - verifyRemoveChipFromHeader( - fix, - grid, - 100, - 'Downloads', - IgxNumberFilteringOperand.instance().condition('equals'), - 1, - 2 - ); + verifyRemoveChipFromHeader(fix, grid, 100, 'Downloads', IgxNumberFilteringOperand.instance().condition('equals'), 1, 2); })); it('should update UI when chip is removed from header cell - Currency column type.', fakeAsync(() => { - verifyRemoveChipFromHeader( - fix, - grid, - 100000, - 'Revenue', - IgxNumberFilteringOperand.instance().condition('equals'), - 1, - 7 - ); + verifyRemoveChipFromHeader(fix, grid, 100000, 'Revenue', IgxNumberFilteringOperand.instance().condition('equals'), 1, 7); })); it('should update UI when chip is removed from header cell - Boolean column type.', fakeAsync(() => { - verifyRemoveChipFromHeader( - fix, - grid, - true, - 'Released', - IgxBooleanFilteringOperand.instance().condition('true'), - 3, - 3 - ); + verifyRemoveChipFromHeader(fix, grid, true, 'Released', IgxBooleanFilteringOperand.instance().condition('true'), 3, 3); })); it('should update UI when chip is removed from header cell - DateTime column type.', fakeAsync(() => { - verifyRemoveChipFromHeader( - fix, - grid, - cal.timedelta(today, 'hour', 1), - 'ReleaseTime', - IgxDateTimeFilteringOperand.instance().condition('equals'), - 3, - 6 - ); + verifyRemoveChipFromHeader(fix, grid, cal.timedelta(today, 'hour', 1), 'ReleaseTime', IgxDateTimeFilteringOperand.instance().condition('equals'), 3, 6); })); it('should emit filteringDone after chip is close from filtering row - Date column type', fakeAsync(() => { @@ -3436,8 +3299,8 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { it('Should hide column when click on button.', fakeAsync(() => { GridFunctions.clickExcelFilterIconFromCode(fix, grid, 'Downloads'); - spyOn(grid.columnVisibilityChanged, 'emit'); - spyOn(grid.columnVisibilityChanging, 'emit'); + vi.spyOn(grid.columnVisibilityChanged, 'emit'); + vi.spyOn(grid.columnVisibilityChanging, 'emit'); GridFunctions.getExcelFilteringHideContainer(fix).click(); fix.detectChanges(); @@ -3931,8 +3794,8 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { setElementSize(grid.nativeElement, ɵSize.Small); tick(200); fix.detectChanges(); - spyOn(grid.columnVisibilityChanging, 'emit'); - spyOn(grid.columnVisibilityChanged, 'emit'); + vi.spyOn(grid.columnVisibilityChanging, 'emit'); + vi.spyOn(grid.columnVisibilityChanged, 'emit'); const column = grid.columnList.find((col) => col.field === 'ProductName'); GridFunctions.verifyColumnIsHidden(column, false, 8); @@ -4030,7 +3893,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { await wait(100); const searchComponent = GridFunctions.getExcelStyleSearchComponent(fix); let listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix, searchComponent); - expect(listItems.length).toBe(6, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(6); // Type string in search box. const inputNativeElement = GridFunctions.getExcelStyleSearchComponentInput(fix, searchComponent); @@ -4039,7 +3902,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { await wait(100); listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix, searchComponent); - expect(listItems.length).toBe(4, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(4); // Clear filtering of ESF search. const clearIcon: any = Array.from(searchComponent.querySelectorAll('igx-icon')) @@ -4048,7 +3911,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { fix.detectChanges(); listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix, searchComponent); - expect(listItems.length).toBe(6, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(6); }); it('Should allow to input commas in excel search component input field when column dataType is number.', async () => { @@ -4065,7 +3928,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { await wait(100); listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix, searchComponent); - expect(listItems.length).toBe(3, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(3); // Type non-numerical symbol in search box. UIInteractions.clickAndSendInputElementValue(inputNativeElement, 'a', fix); @@ -4073,8 +3936,8 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { await wait(100); listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix, searchComponent); - expect(inputNativeElement.value).toBe('', 'incorrect rendered list items count'); - expect(listItems.length).toBe(8, 'incorrect rendered list items count'); + expect(inputNativeElement.value, 'incorrect rendered list items count').toBe(''); + expect(listItems.length, 'incorrect rendered list items count').toBe(8); }); it('Should enable/disable the apply button correctly.', async () => { @@ -4084,7 +3947,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Verify there are filtered-in results and that apply button is enabled. const listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix); let applyButton = GridFunctions.getApplyButtonExcelStyleFiltering(fix) as HTMLElement; - expect(listItems.length).toBe(6, 'ESF search result should NOT be empty'); + expect(listItems.length, 'ESF search result should NOT be empty').toBe(6); ControlsFunction.verifyButtonIsDisabled(applyButton, false); // Verify the apply button is disabled when all items are unchecked (when unchecking 'Select All'). @@ -4247,93 +4110,91 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { verifyGridSubmenuSize(gridNativeElement, ɵSize.Small); })); - it('size is properly applied on the excel custom dialog\'s default expression dropdown', - fakeAsync(() => { - const gridNativeElement = fix.debugElement.query(By.css('igx-grid')).nativeElement; + it('size is properly applied on the excel custom dialog\'s default expression dropdown', fakeAsync(() => { + const gridNativeElement = fix.debugElement.query(By.css('igx-grid')).nativeElement; - // Open excel style custom filtering dialog. - GridFunctions.clickExcelFilterIconFromCode(fix, grid, 'ProductName'); + // Open excel style custom filtering dialog. + GridFunctions.clickExcelFilterIconFromCode(fix, grid, 'ProductName'); - GridFunctions.clickExcelFilterCascadeButton(fix); - fix.detectChanges(); - GridFunctions.clickOperatorFromCascadeMenu(fix, 0); - tick(200); + GridFunctions.clickExcelFilterCascadeButton(fix); + fix.detectChanges(); + GridFunctions.clickOperatorFromCascadeMenu(fix, 0); + tick(200); - // Click the left input to open the operators dropdown and verify its size. - let conditionsInput = GridFunctions.getExcelFilteringDDInput(fix, 0); - conditionsInput.click(); - tick(100); - fix.detectChanges(); + // Click the left input to open the operators dropdown and verify its size. + let conditionsInput = GridFunctions.getExcelFilteringDDInput(fix, 0); + conditionsInput.click(); + tick(100); + fix.detectChanges(); - verifyGridSubmenuSize(gridNativeElement, ɵSize.Large); - GridFunctions.clickCancelExcelStyleCustomFiltering(fix); - tick(100); - fix.detectChanges(); + verifyGridSubmenuSize(gridNativeElement, ɵSize.Large); + GridFunctions.clickCancelExcelStyleCustomFiltering(fix); + tick(100); + fix.detectChanges(); - // Change size - setElementSize(grid.nativeElement, ɵSize.Medium); - tick(200); - fix.detectChanges(); + // Change size + setElementSize(grid.nativeElement, ɵSize.Medium); + tick(200); + fix.detectChanges(); - // Open excel style custom filtering dialog. - GridFunctions.clickExcelFilterIconFromCode(fix, grid, 'ProductName'); + // Open excel style custom filtering dialog. + GridFunctions.clickExcelFilterIconFromCode(fix, grid, 'ProductName'); - GridFunctions.clickExcelFilterCascadeButton(fix); - fix.detectChanges(); - GridFunctions.clickOperatorFromCascadeMenu(fix, 0); - tick(200); + GridFunctions.clickExcelFilterCascadeButton(fix); + fix.detectChanges(); + GridFunctions.clickOperatorFromCascadeMenu(fix, 0); + tick(200); - // Click the left input to open the operators dropdown and verify its size. - conditionsInput = GridFunctions.getExcelFilteringDDInput(fix, 0); - conditionsInput.click(); - tick(100); - fix.detectChanges(); + // Click the left input to open the operators dropdown and verify its size. + conditionsInput = GridFunctions.getExcelFilteringDDInput(fix, 0); + conditionsInput.click(); + tick(100); + fix.detectChanges(); - verifyGridSubmenuSize(gridNativeElement, ɵSize.Medium); - })); + verifyGridSubmenuSize(gridNativeElement, ɵSize.Medium); + })); - it('size is properly applied on the excel custom dialog\'s date expression dropdown', - fakeAsync(() => { - const gridNativeElement = fix.debugElement.query(By.css('igx-grid')).nativeElement; - GridFunctions.clickExcelFilterIconFromCode(fix, grid, 'ReleaseDate'); + it('size is properly applied on the excel custom dialog\'s date expression dropdown', fakeAsync(() => { + const gridNativeElement = fix.debugElement.query(By.css('igx-grid')).nativeElement; + GridFunctions.clickExcelFilterIconFromCode(fix, grid, 'ReleaseDate'); - GridFunctions.clickExcelFilterCascadeButton(fix); - fix.detectChanges(); - GridFunctions.clickOperatorFromCascadeMenu(fix, 0); - tick(200); + GridFunctions.clickExcelFilterCascadeButton(fix); + fix.detectChanges(); + GridFunctions.clickOperatorFromCascadeMenu(fix, 0); + tick(200); - // Click the left input to open the operators dropdown and verify its size. - let conditionsInput = GridFunctions.getExcelFilteringDDInput(fix, 0, true); - conditionsInput.click(); - tick(100); - fix.detectChanges(); + // Click the left input to open the operators dropdown and verify its size. + let conditionsInput = GridFunctions.getExcelFilteringDDInput(fix, 0, true); + conditionsInput.click(); + tick(100); + fix.detectChanges(); - verifyGridSubmenuSize(gridNativeElement, ɵSize.Large); + verifyGridSubmenuSize(gridNativeElement, ɵSize.Large); - GridFunctions.clickCancelExcelStyleCustomFiltering(fix); - tick(100); - fix.detectChanges(); + GridFunctions.clickCancelExcelStyleCustomFiltering(fix); + tick(100); + fix.detectChanges(); - // Change size - setElementSize(grid.nativeElement, ɵSize.Medium); - tick(200); - fix.detectChanges(); + // Change size + setElementSize(grid.nativeElement, ɵSize.Medium); + tick(200); + fix.detectChanges(); - // Open excel style custom filtering dialog. - GridFunctions.clickExcelFilterIconFromCode(fix, grid, 'ReleaseDate'); + // Open excel style custom filtering dialog. + GridFunctions.clickExcelFilterIconFromCode(fix, grid, 'ReleaseDate'); - GridFunctions.clickExcelFilterCascadeButton(fix); - fix.detectChanges(); - GridFunctions.clickOperatorFromCascadeMenu(fix, 0); - tick(200); + GridFunctions.clickExcelFilterCascadeButton(fix); + fix.detectChanges(); + GridFunctions.clickOperatorFromCascadeMenu(fix, 0); + tick(200); - // Click the left input to open the operators dropdown and verify its size. - conditionsInput = GridFunctions.getExcelFilteringDDInput(fix, 0, true); - conditionsInput.click(); - tick(100); - fix.detectChanges(); - verifyGridSubmenuSize(gridNativeElement, ɵSize.Medium); - })); + // Click the left input to open the operators dropdown and verify its size. + conditionsInput = GridFunctions.getExcelFilteringDDInput(fix, 0, true); + conditionsInput.click(); + tick(100); + fix.detectChanges(); + verifyGridSubmenuSize(gridNativeElement, ɵSize.Medium); + })); it('Should include \'false\' value in results when searching.', fakeAsync(() => { // Open excel style custom filtering dialog. @@ -4348,7 +4209,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Verify that the first item is 'Select All' and the third item is 'false'. const listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix, searchComponent); - expect(listItems.length).toBe(3, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(3); expect(listItems[0].innerText).toBe('Select all search results'); expect(listItems[2].innerText).toBe('False'); })); @@ -4385,17 +4246,16 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { fix.detectChanges(); // Verify scrollbar's scrollTop. - expect(scrollbar.scrollTop >= 660 && scrollbar.scrollTop <= 700).toBe(true, - 'search scrollbar has incorrect scrollTop: ' + scrollbar.scrollTop); + expect(scrollbar.scrollTop >= 660 && scrollbar.scrollTop <= 700).toBe(true, 'search scrollbar has incorrect scrollTop: ' + scrollbar.scrollTop); // Verify display container height. const displayContainer = searchComponent.querySelector('igx-display-container'); const displayContainerRect = displayContainer.getBoundingClientRect(); const listHeight = searchComponent.querySelector('igx-list').getBoundingClientRect().height; const itemHeight = displayContainer.querySelector('igx-list-item').getBoundingClientRect().height; - expect(displayContainerRect.height > listHeight + itemHeight && displayContainerRect.height < listHeight + (itemHeight * 2)).toBe(true, 'incorrect search display container height'); + expect(displayContainerRect.height > listHeight + itemHeight && displayContainerRect.height < listHeight + (itemHeight * 2), 'incorrect search display container height').toBe(true); // Verify rendered list items count. const listItems = displayContainer.querySelectorAll('igx-list-item'); - expect(listItems.length).toBe(Math.ceil(listHeight / itemHeight) + 1, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(Math.ceil(listHeight / itemHeight) + 1); })); it('should correctly display all items in search list after filtering it', (async () => { @@ -4437,8 +4297,8 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const displayContainerRect = displayContainer.getBoundingClientRect(); const listNativeElement = searchComponent.querySelector('.igx-list'); const listRect = listNativeElement.getBoundingClientRect(); - expect(displayContainerRect.top >= listRect.top).toBe(true, 'displayContainer starts above list'); - expect(displayContainerRect.bottom <= listRect.bottom).toBe(true, 'displayContainer ends below list'); + expect(displayContainerRect.top >= listRect.top, 'displayContainer starts above list').toBe(true); + expect(displayContainerRect.bottom <= listRect.bottom, 'displayContainer ends below list').toBe(true); })); it('Should not treat \'Select All\' as a search result.', async () => { @@ -4499,18 +4359,14 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const lastExpression = expressions[expressions.length - 1]; const lastExpressionRect = lastExpression.getBoundingClientRect(); const expressionsContainerRect = expressionsContainer.getBoundingClientRect(); - expect(lastExpressionRect.top >= expressionsContainerRect.top).toBe(true, - 'lastExpression starts above expressionsContainer'); - expect(lastExpressionRect.bottom <= expressionsContainerRect.bottom).toBe(true, - 'lastExpression ends below expressionsContainer'); + expect(lastExpressionRect.top >= expressionsContainerRect.top, 'lastExpression starts above expressionsContainer').toBe(true); + expect(lastExpressionRect.bottom <= expressionsContainerRect.bottom, 'lastExpression ends below expressionsContainer').toBe(true); // Verify addFilter button is currently in view beneath the last expression. const addFilterButton = GridFunctions.getAddFilterExcelStyleCustomFiltering(fix); const addFilterButtonRect = addFilterButton.getBoundingClientRect(); - expect(addFilterButtonRect.top >= lastExpressionRect.bottom).toBe(true, - 'addFilterButton overlaps lastExpression'); - expect(addFilterButtonRect.bottom <= expressionsContainerRect.bottom).toBe(true, - 'addFilterButton ends below expressionsContainer'); + expect(addFilterButtonRect.top >= lastExpressionRect.bottom, 'addFilterButton overlaps lastExpression').toBe(true); + expect(addFilterButtonRect.bottom <= expressionsContainerRect.bottom, 'addFilterButton ends below expressionsContainer').toBe(true); })); it('Should generate "equals" conditions when selecting two values.', fakeAsync(() => { @@ -4533,9 +4389,8 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { fix.detectChanges(); expect(grid.rowList.length).toBe(2); - const operands = - (grid.filteringExpressionsTree.filteringOperands[0] as IFilteringExpressionsTree) - .filteringOperands as IFilteringExpression[]; + const operands = (grid.filteringExpressionsTree.filteringOperands[0] as IFilteringExpressionsTree) + .filteringOperands as IFilteringExpression[]; expect(operands.length).toBe(2); verifyFilteringExpression(operands[0], 'ProductName', 'equals', 'Ignite UI for Angular'); verifyFilteringExpression(operands[1], 'ProductName', 'equals', 'Ignite UI for JavaScript'); @@ -4562,12 +4417,10 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { fix.detectChanges(); expect(grid.rowList.length).toBe(3); - const operands = - (grid.filteringExpressionsTree.filteringOperands[0] as IFilteringExpressionsTree) - .filteringOperands as IFilteringExpression[]; + const operands = (grid.filteringExpressionsTree.filteringOperands[0] as IFilteringExpressionsTree) + .filteringOperands as IFilteringExpression[]; expect(operands.length).toBe(1); - verifyFilteringExpression(operands[0], 'ProductName', 'in', - new Set(['Ignite UI for Angular', 'Ignite UI for JavaScript', 'NetAdvantage'])); + verifyFilteringExpression(operands[0], 'ProductName', 'in', new Set(['Ignite UI for Angular', 'Ignite UI for JavaScript', 'NetAdvantage'])); })); it('Should not throw error when selecting more than two values and column dataType is date.', fakeAsync(() => { @@ -4613,12 +4466,10 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { fix.detectChanges(); expect(grid.rowList.length).toBe(6); - const operands = - (grid.filteringExpressionsTree.filteringOperands[0] as IFilteringExpressionsTree) - .filteringOperands as IFilteringExpression[]; + const operands = (grid.filteringExpressionsTree.filteringOperands[0] as IFilteringExpressionsTree) + .filteringOperands as IFilteringExpression[]; expect(operands.length).toBe(2); - verifyFilteringExpression(operands[0], 'ProductName', 'in', - new Set(['Ignite UI for Angular', 'Ignite UI for JavaScript'])); + verifyFilteringExpression(operands[0], 'ProductName', 'in', new Set(['Ignite UI for Angular', 'Ignite UI for JavaScript'])); verifyFilteringExpression(operands[1], 'ProductName', 'empty', null); })); @@ -4634,7 +4485,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { await wait(DEBOUNCE_TIME); fix.detectChanges(); - expect(isExcelSearchScrollBarVisible(fix)).toBe(true, 'excel search scrollbar should be visible'); + expect(isExcelSearchScrollBarVisible(fix), 'excel search scrollbar should be visible').toBe(true); GridFunctions.clickApplyExcelStyleFiltering(fix); fix.detectChanges(); @@ -4647,7 +4498,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { await wait(DEBOUNCE_TIME); fix.detectChanges(); - expect(isExcelSearchScrollBarVisible(fix)).toBe(false, 'excel search scrollbar should NOT be visible'); + expect(isExcelSearchScrollBarVisible(fix), 'excel search scrollbar should NOT be visible').toBe(false); GridFunctions.clickApplyExcelStyleFiltering(fix); fix.detectChanges(); @@ -4660,7 +4511,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { await wait(DEBOUNCE_TIME); fix.detectChanges(); - expect(isExcelSearchScrollBarVisible(fix)).toBe(false, 'excel search scrollbar should NOT be visible'); + expect(isExcelSearchScrollBarVisible(fix), 'excel search scrollbar should NOT be visible').toBe(false); })); it('Should cascade filter the available filter options.', fakeAsync(() => { @@ -4668,24 +4519,18 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', '(Blanks)', '0', '20', '100', '127', '254'], - [true, true, true, true, true, true, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', '(Blanks)', '0', '20', '100', '127', '254'], [true, true, true, true, true, true, true]); GridFunctions.clickExcelFilterIcon(fix, 'ProductName'); tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', '(Blanks)', 'Ignite UI for Angular', 'Ignite UI for JavaScript', - 'NetAdvantage', 'Some other item with Script'], - [true, true, true, true, true, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', '(Blanks)', 'Ignite UI for Angular', 'Ignite UI for JavaScript', + 'NetAdvantage', 'Some other item with Script'], [true, true, true, true, true, true]); GridFunctions.clickExcelFilterIcon(fix, 'Released'); tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', '(Blanks)', 'False', 'True'], - [true, true, true, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', '(Blanks)', 'False', 'True'], [true, true, true, true]); toggleExcelStyleFilteringItems(fix, true, 3); @@ -4694,23 +4539,17 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { GridFunctions.clickExcelFilterIcon(fix, 'Released'); tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', '(Blanks)', 'False', 'True'], - [null, true, true, false]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', '(Blanks)', 'False', 'True'], [null, true, true, false]); GridFunctions.clickExcelFilterIcon(fix, 'Downloads'); tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', '20', '100', '254', '702', '1,000'], - [true, true, true, true, true, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', '20', '100', '254', '702', '1,000'], [true, true, true, true, true, true]); GridFunctions.clickExcelFilterIcon(fix, 'ProductName'); tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', '(Blanks)', 'Ignite UI for Angular', 'Ignite UI for JavaScript', 'Some other item with Script'], - [true, true, true, true, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', '(Blanks)', 'Ignite UI for Angular', 'Ignite UI for JavaScript', 'Some other item with Script'], [true, true, true, true, true]); toggleExcelStyleFilteringItems(fix, false, 0); toggleExcelStyleFilteringItems(fix, true, 2, 3); @@ -4720,111 +4559,85 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { GridFunctions.clickExcelFilterIcon(fix, 'Released'); tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', '(Blanks)', 'False'], - [true, true, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', '(Blanks)', 'False'], [true, true, true]); GridFunctions.clickExcelFilterIcon(fix, 'ProductName'); tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', '(Blanks)', 'Ignite UI for Angular', 'Ignite UI for JavaScript', 'Some other item with Script'], - [null, false, true, true, false]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', '(Blanks)', 'Ignite UI for Angular', 'Ignite UI for JavaScript', 'Some other item with Script'], [null, false, true, true, false]); GridFunctions.clickExcelFilterIcon(fix, 'Downloads'); tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', '20', '254'], - [true, true, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', '20', '254'], [true, true, true]); })); it('Should correctly modify existing filters.', fakeAsync(() => { GridFunctions.clickExcelFilterIcon(fix, 'ProductName'); tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', '(Blanks)', 'Ignite UI for Angular', 'Ignite UI for JavaScript', - 'NetAdvantage', 'Some other item with Script'], - [true, true, true, true, true, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', '(Blanks)', 'Ignite UI for Angular', 'Ignite UI for JavaScript', + 'NetAdvantage', 'Some other item with Script'], [true, true, true, true, true, true]); toggleExcelStyleFilteringItems(fix, true, 1, 5); expect(grid.rowList.length).toBe(3); GridFunctions.clickExcelFilterIcon(fix, 'Downloads'); tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', '20', '127', '254'], - [true, true, true, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', '20', '127', '254'], [true, true, true, true]); toggleExcelStyleFilteringItems(fix, true, 2); expect(grid.rowList.length).toBe(2); GridFunctions.clickExcelFilterIcon(fix, 'ProductName'); tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', 'Ignite UI for Angular', 'Ignite UI for JavaScript'], - [true, true, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', 'Ignite UI for Angular', 'Ignite UI for JavaScript'], [true, true, true]); GridFunctions.clickExcelFilterIcon(fix, 'Downloads'); tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', '20', '127', '254'], - [null, true, false, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', '20', '127', '254'], [null, true, false, true]); toggleExcelStyleFilteringItems(fix, true, 1, 2, 3); expect(grid.rowList.length).toBe(1); GridFunctions.clickExcelFilterIcon(fix, 'Downloads'); tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', '20', '127', '254'], - [null, false, true, false]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', '20', '127', '254'], [null, false, true, false]); })); it('Should correctly modify the first one of the existing filters.', fakeAsync(() => { GridFunctions.clickExcelFilterIcon(fix, 'ProductName'); tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', '(Blanks)', 'Ignite UI for Angular', 'Ignite UI for JavaScript', - 'NetAdvantage', 'Some other item with Script'], - [true, true, true, true, true, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', '(Blanks)', 'Ignite UI for Angular', 'Ignite UI for JavaScript', + 'NetAdvantage', 'Some other item with Script'], [true, true, true, true, true, true]); toggleExcelStyleFilteringItems(fix, true, 1, 5); expect(grid.rowList.length).toBe(3); GridFunctions.clickExcelFilterIcon(fix, 'Downloads'); tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', '20', '127', '254'], - [true, true, true, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', '20', '127', '254'], [true, true, true, true]); toggleExcelStyleFilteringItems(fix, true, 2); expect(grid.rowList.length).toBe(2); GridFunctions.clickExcelFilterIcon(fix, 'ProductName'); tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', 'Ignite UI for Angular', 'Ignite UI for JavaScript'], - [true, true, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', 'Ignite UI for Angular', 'Ignite UI for JavaScript'], [true, true, true]); toggleExcelStyleFilteringItems(fix, true, 1); expect(grid.rowList.length).toBe(1); GridFunctions.clickExcelFilterIcon(fix, 'Downloads'); tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', '254'], - [true, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', '254'], [true, true]); GridFunctions.clickExcelFilterIcon(fix, 'ProductName'); tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', 'Ignite UI for Angular', 'Ignite UI for JavaScript'], - [null, false, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', 'Ignite UI for Angular', 'Ignite UI for JavaScript'], [null, false, true]); })); it('Should display the ESF based on the filterIcon within the grid', async () => { @@ -4849,9 +4662,9 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const gridRect = gridNativeElement.getBoundingClientRect(); const excelMenu = GridFunctions.getExcelStyleFilteringComponent(fix); const excelMenuRect = excelMenu.getBoundingClientRect(); - expect(excelMenuRect.left >= gridRect.left).toBe(true, 'ESF spans outside the grid on the left'); - expect(excelMenuRect.top >= gridRect.top).toBe(true, 'ESF spans outside the grid on the top'); - expect(excelMenuRect.right <= gridRect.right).toBe(true, 'ESF spans outside the grid on the right'); + expect(excelMenuRect.left >= gridRect.left, 'ESF spans outside the grid on the left').toBe(true); + expect(excelMenuRect.top >= gridRect.top, 'ESF spans outside the grid on the top').toBe(true); + expect(excelMenuRect.right <= gridRect.right, 'ESF spans outside the grid on the right').toBe(true); }); it('Should add/remove expressions in custom filter dialog through UI correctly.', fakeAsync(() => { @@ -5104,23 +4917,11 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { UIInteractions.simulateClickEvent(input); fix.detectChanges(); - const prevMonthButton = fix.debugElement.queryAll( - By.css(HelperTestFunctions.CALENDAR_PREV_BUTTON_CSSCLASS), - )[0].nativeElement; + const prevMonthButton = fix.debugElement.queryAll(By.css(HelperTestFunctions.CALENDAR_PREV_BUTTON_CSSCLASS))[0].nativeElement; prevMonthButton.focus(); - UIInteractions.simulateMouseEvent( - "mousedown", - prevMonthButton, - 0, - 0, - ); + UIInteractions.simulateMouseEvent("mousedown", prevMonthButton, 0, 0); tick(); - UIInteractions.simulateMouseEvent( - "mouseup", - prevMonthButton, - 0, - 0, - ); + UIInteractions.simulateMouseEvent("mouseup", prevMonthButton, 0, 0); fix.detectChanges(); // Verify the calendar is scrolled to previous month. @@ -5269,7 +5070,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const column = grid.getColumnByName('ReleaseDateTime'); column.editorOptions = { dateTimeFormat: 'dd-MM-yyyy HH:mm aaaaa' - } + }; fix.detectChanges(); GridFunctions.clickExcelFilterIcon(fix, 'ReleaseDateTime'); @@ -5295,7 +5096,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const column = grid.getColumnByName('ReleaseDateTime'); column.pipeArgs = { format: 'dd-MM-yyyy' - } + }; fix.detectChanges(); GridFunctions.clickExcelFilterIcon(fix, 'ReleaseDateTime'); @@ -5338,7 +5139,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const column = grid.getColumnByName('ReleaseTime'); column.editorOptions = { dateTimeFormat: 'HH:mm' - } + }; fix.detectChanges(); GridFunctions.clickExcelFilterIcon(fix, 'ReleaseTime'); @@ -5359,7 +5160,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const column = grid.getColumnByName('ReleaseTime'); column.pipeArgs = { format: 'HH:mm' - } + }; fix.detectChanges(); GridFunctions.clickExcelFilterIcon(fix, 'ReleaseTime'); @@ -5612,32 +5413,31 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { expect(excelMenu).toBeNull(); })); - it('Should open/close ESF menu for respective column when pressing \'ctrl + shift + l\' on its filterCell chip.', - fakeAsync(() => { - let excelMenu = GridFunctions.getExcelStyleFilteringComponent(fix); - // Verify ESF is not visible. - expect(excelMenu).toBeNull(); + it('Should open/close ESF menu for respective column when pressing \'ctrl + shift + l\' on its filterCell chip.', fakeAsync(() => { + let excelMenu = GridFunctions.getExcelStyleFilteringComponent(fix); + // Verify ESF is not visible. + expect(excelMenu).toBeNull(); - const downloadsColumn = GridFunctions.getColumnHeader('Downloads', fix); - UIInteractions.simulateClickAndSelectEvent(downloadsColumn); - fix.detectChanges(); + const downloadsColumn = GridFunctions.getColumnHeader('Downloads', fix); + UIInteractions.simulateClickAndSelectEvent(downloadsColumn); + fix.detectChanges(); - UIInteractions.triggerKeyDownEvtUponElem('l', downloadsColumn.nativeElement, true, false, true, true); - tick(200); - fix.detectChanges(); + UIInteractions.triggerKeyDownEvtUponElem('l', downloadsColumn.nativeElement, true, false, true, true); + tick(200); + fix.detectChanges(); - // Verify ESF menu is opened for the 'Downloads' column. - excelMenu = GridFunctions.getExcelStyleFilteringComponent(fix); - expect(excelMenu).not.toBeNull(); + // Verify ESF menu is opened for the 'Downloads' column. + excelMenu = GridFunctions.getExcelStyleFilteringComponent(fix); + expect(excelMenu).not.toBeNull(); - // Press the combination again. - UIInteractions.triggerKeyDownEvtUponElem('l', excelMenu, true, false, true, true); - tick(200); - fix.detectChanges(); + // Press the combination again. + UIInteractions.triggerKeyDownEvtUponElem('l', excelMenu, true, false, true, true); + tick(200); + fix.detectChanges(); - excelMenu = GridFunctions.getExcelStyleFilteringComponent(fix); - expect(excelMenu).toBeNull(); - })); + excelMenu = GridFunctions.getExcelStyleFilteringComponent(fix); + expect(excelMenu).toBeNull(); + })); it('Should filter ISO 8601 dates for date column ignoring the time portion - issue #14643', fakeAsync(() => { // Add hours part to the ReleaseDate so some records differ only by the time portion @@ -5680,7 +5480,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const cell1 = GridFunctions.getRowCells(fix, 0)[4].nativeElement; const cell2 = GridFunctions.getRowCells(fix, 3)[4].nativeElement; expect(cell1.textContent.toString()).toEqual(cell2.textContent.toString()); - expect(rows.length).toBe(6, 'incorrect number of rows'); + expect(rows.length, 'incorrect number of rows').toBe(6); //Check if checkboxes have correct state on ESF menu reopening GridFunctions.clickExcelFilterIcon(fix, 'ReleaseDate'); @@ -5688,8 +5488,8 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { fix.detectChanges(); const checkboxes: any[] = Array.from(GridFunctions.getExcelStyleFilteringCheckboxes(fix)); - expect(checkboxes[0].indeterminate).toBeTrue(); - expect(checkboxes[1].checked).toBeFalse(); + expect(checkboxes[0].indeterminate).toBe(true); + expect(checkboxes[1].checked).toBe(false); const listItemsCheckboxes = checkboxes.slice(2, checkboxes.length - 1); for (const checkboxItem of listItemsCheckboxes) { ControlsFunction.verifyCheckboxState(checkboxItem.parentElement); @@ -5724,7 +5524,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { fix.detectChanges(); listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix, searchComponent); - expect(listItems.length).toBe(0, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(0); })); it('Should filter ISO 8601 date by input string', fakeAsync(() => { @@ -5762,7 +5562,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { fix.detectChanges(); listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix, searchComponent); - expect(listItems.length).toBe(0, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(0); })); it('Should filter milliseconds date by input string', fakeAsync(() => { @@ -5800,34 +5600,30 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { fix.detectChanges(); listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix, searchComponent); - expect(listItems.length).toBe(0, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(0); })); it('Should ignore duplicate records when column\'s filteringIgnoreCase is true', fakeAsync(() => { const column = grid.getColumnByName('AnotherField'); - expect(column.filteringIgnoreCase).toBeTrue(); + expect(column.filteringIgnoreCase).toBe(true); GridFunctions.clickExcelFilterIcon(fix, 'AnotherField'); tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', 'a', 'Custom'], - [true, true, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', 'a', 'Custom'], [true, true, true]); })); it('Should not ignore duplicate records when column\'s filteringIgnoreCase is false', fakeAsync(() => { const column = grid.getColumnByName('AnotherField'); column.filteringIgnoreCase = false; - expect(column.filteringIgnoreCase).toBeFalse(); + expect(column.filteringIgnoreCase).toBe(false); GridFunctions.clickExcelFilterIcon(fix, 'AnotherField'); tick(100); fix.detectChanges(); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', 'a', 'Custom', 'custoM', 'custom'], - [true, true, true, true, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', 'a', 'Custom', 'custoM', 'custom'], [true, true, true, true, true]); })); it('Should display "Add to current filter selection" button on typing in input', fakeAsync(() => { @@ -5842,7 +5638,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Verify that the second item is 'Add to current filter selection'. const listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix, searchComponent); - expect(listItems.length).toBe(6, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(6); expect(listItems[1].innerText).toBe('Add current selection to filter'); })); @@ -5954,41 +5750,41 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const listItems = list.querySelectorAll('igx-list-item'); // we expect only the first list item to be active when the list is focused - expect(listItems[0].classList.contains("igx-list__item-base--active")).toBeTrue(); - expect(listItems[1].classList.contains("igx-list__item-base--active")).toBeFalse(); + expect(listItems[0].classList.contains("igx-list__item-base--active")).toBe(true); + expect(listItems[1].classList.contains("igx-list__item-base--active")).toBe(false); // on arrow down the second item should be active UIInteractions.triggerKeyDownEvtUponElem('arrowdown', list, true); fix.detectChanges(); - expect(listItems[0].classList.contains("igx-list__item-base--active")).toBeFalse(); - expect(listItems[1].classList.contains("igx-list__item-base--active")).toBeTrue(); + expect(listItems[0].classList.contains("igx-list__item-base--active")).toBe(false); + expect(listItems[1].classList.contains("igx-list__item-base--active")).toBe(true); // on arrow up the first item should be active again UIInteractions.triggerKeyDownEvtUponElem('arrowup', list, true); fix.detectChanges(); - expect(listItems[0].classList.contains("igx-list__item-base--active")).toBeTrue(); - expect(listItems[1].classList.contains("igx-list__item-base--active")).toBeFalse(); + expect(listItems[0].classList.contains("igx-list__item-base--active")).toBe(true); + expect(listItems[1].classList.contains("igx-list__item-base--active")).toBe(false); // on home the first item should be active UIInteractions.triggerKeyDownEvtUponElem('arrowdown', list, true); fix.detectChanges(); - expect(listItems[1].classList.contains("igx-list__item-base--active")).toBeTrue(); + expect(listItems[1].classList.contains("igx-list__item-base--active")).toBe(true); UIInteractions.triggerKeyDownEvtUponElem('home', list, true); fix.detectChanges(); - expect(listItems[0].classList.contains("igx-list__item-base--active")).toBeTrue(); + expect(listItems[0].classList.contains("igx-list__item-base--active")).toBe(true); // on space key on the first item (select all) all the checkbox should deselect let checkboxes = list.querySelectorAll('igx-checkbox'); let checkboxesStatus = Array.from(checkboxes).map((checkbox: Element) => checkbox.querySelector('input').checked); checkboxesStatus.forEach(status => { - expect(status).toBeTrue(); + expect(status).toBe(true); }); UIInteractions.triggerKeyDownEvtUponElem('space', list, true); fix.detectChanges(); checkboxes = list.querySelectorAll('igx-checkbox'); checkboxesStatus = Array.from(checkboxes).map((checkbox: Element) => checkbox.querySelector('input').checked); checkboxesStatus.forEach(status => { - expect(status).toBeFalse(); + expect(status).toBe(false); }); })); @@ -6002,13 +5798,13 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const listItems = list.querySelectorAll('igx-list-item'); // we expect only the first list item to be active when the list is focused - expect(listItems[0].classList.contains("igx-list__item-base--active")).toBeTrue(); - expect(listItems[1].classList.contains("igx-list__item-base--active")).toBeFalse(); + expect(listItems[0].classList.contains("igx-list__item-base--active")).toBe(true); + expect(listItems[1].classList.contains("igx-list__item-base--active")).toBe(false); // on arrow up the focus should stay on the first element and not on the search input UIInteractions.triggerKeyDownEvtUponElem('arrowup', list, true); fix.detectChanges(); - expect(listItems[0].classList.contains("igx-list__item-base--active")).toBeTrue(); + expect(listItems[0].classList.contains("igx-list__item-base--active")).toBe(true); })); it('Should add list items to current filtered items when "Add to current filter selection" is selected.', fakeAsync(() => { @@ -6087,7 +5883,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Get checkboxes and verify 'Select All' is indeterminate. const excelMenu = GridFunctions.getExcelStyleFilteringComponent(fix); const checkboxes: any[] = Array.from(GridFunctions.getExcelStyleFilteringCheckboxes(fix, excelMenu)); - expect(checkboxes[0].indeterminate).toBeTrue(); + expect(checkboxes[0].indeterminate).toBe(true); })); it('Should enable the `Apply` button & filter properly when "Add to current filter selection" is the only selected option.', fakeAsync(() => { @@ -6111,7 +5907,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Click 'apply' button to apply filter. const applyButton = GridFunctions.getApplyButtonExcelStyleFiltering(fix, excelMenu); - expect(applyButton.disabled).toBeFalse(); + expect(applyButton.disabled).toBe(false); applyButton.click(); fix.detectChanges(); tick(); @@ -6192,7 +5988,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { excelMenu = GridFunctions.getExcelStyleFilteringComponent(fix); expect(excelMenu).not.toBeNull(); - expect(inputNativeElement.value).toBe('', 'input isn\'t cleared correctly'); + expect(inputNativeElement.value, 'input isn\'t cleared correctly').toBe(''); })); it('Should clear search criteria when selecting clear column filters option.', fakeAsync(() => { @@ -6221,14 +6017,14 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { UIInteractions.clickAndSendInputElementValue(inputNativeElement, 'Net', fix); const listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix); - expect(listItems.length).toBe(3, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(3); GridFunctions.clickClearFilterInExcelStyleFiltering(fix); flush(); expect(grid.filteredData).toBeNull(); inputNativeElement = GridFunctions.getExcelStyleSearchComponentInput(fix); - expect(inputNativeElement.value).toBe('', 'search criteria is not cleared'); + expect(inputNativeElement.value, 'search criteria is not cleared').toBe(''); checkboxes = GridFunctions.getExcelStyleFilteringCheckboxes(fix); const listItemsCheckboxes = checkboxes.slice(1, checkboxes.length); @@ -6270,9 +6066,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { fix.detectChanges(); items = GridFunctions.getExcelStyleSearchComponentListItems(fix); expect(items.length).toBe(3); - verifyExcelStyleFilterAvailableOptions(fix, - ['Select all search results', 'Add current selection to filter', 'Web'], - [true, false, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select all search results', 'Add current selection to filter', 'Web'], [true, false, true]); inputNativeElement.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true })); await wait(100); @@ -6289,9 +6083,9 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const searchComponent = GridFunctions.getExcelStyleSearchComponent(fix); const listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix, searchComponent); - expect(listItems.length).toBe(4, 'incorrect rendered list items count'); - expect(listItems[2].innerText).toBe('False', 'incorrect list item label'); - expect(listItems[3].innerText).toBe('True', 'incorrect list item label'); + expect(listItems.length, 'incorrect rendered list items count').toBe(4); + expect(listItems[2].innerText, 'incorrect list item label').toBe('False'); + expect(listItems[3].innerText, 'incorrect list item label').toBe('True'); const checkboxes = GridFunctions.getExcelStyleFilteringCheckboxes(fix); checkboxes[3].click(); @@ -6317,9 +6111,9 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const searchComponent = GridFunctions.getExcelStyleSearchComponent(fix); const listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix, searchComponent); - expect(listItems.length).toBe(4, 'incorrect rendered list items count'); - expect(listItems[2].innerText).toBe('No', 'incorrect list item label'); - expect(listItems[3].innerText).toBe('Yes', 'incorrect list item label'); + expect(listItems.length, 'incorrect rendered list items count').toBe(4); + expect(listItems[2].innerText, 'incorrect list item label').toBe('No'); + expect(listItems[3].innerText, 'incorrect list item label').toBe('Yes'); }); it('Should sort items in excel style search correctly', fakeAsync(() => { @@ -6367,9 +6161,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { fix.detectChanges(); // Verify items order is case INsensitive - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', 'aWord', 'BWord'], - [true, true, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', 'aWord', 'BWord'], [true, true, true]); // Open excel style custom filtering dialog for time column GridFunctions.clickExcelFilterIcon(fix, 'ReleaseTime'); @@ -6377,9 +6169,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { fix.detectChanges(); // Verify items order is based only on time and not date - verifyExcelStyleFilterAvailableOptions(fix, - ['Select All', '1:00:00 AM', '12:00:00 PM', '11:00:00 PM'], - [true, true, true, true]); + verifyExcelStyleFilterAvailableOptions(fix, ['Select All', '1:00:00 AM', '12:00:00 PM', '11:00:00 PM'], [true, true, true, true]); })); it('should clear all filters in the custom dialog when clicking "Clear Filter" button', fakeAsync(() => { @@ -6468,7 +6258,8 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { }); describe('Templates: ', () => { - let fix; let grid; + let fix; + let grid; beforeEach(fakeAsync(() => { fix = TestBed.createComponent(IgxGridFilteringESFTemplatesComponent); fix.detectChanges(); @@ -6517,7 +6308,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { const searchComponent = GridFunctions.getExcelStyleSearchComponent(fix); let listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix, searchComponent); - expect(listItems.length).toBe(6, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(6); // Type string in search box. const inputNativeElement = GridFunctions.getExcelStyleSearchComponentInput(fix, searchComponent); @@ -6526,7 +6317,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { fix.detectChanges(); listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix, searchComponent); - expect(listItems.length).toBe(4, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(4); // Clear filtering of ESF search. const clearIcon: any = Array.from(searchComponent.querySelectorAll('igx-icon')) @@ -6535,7 +6326,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { fix.detectChanges(); listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix, searchComponent); - expect(listItems.length).toBe(6, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(6); tick(100); })); @@ -6581,7 +6372,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { grid.columnSelection = GridSelectionMode.multiple; fix.detectChanges(); - spyOn(grid.columnSelectionChanging, 'emit'); + vi.spyOn(grid.columnSelectionChanging, 'emit'); const column = grid.getColumnByName('Downloads'); fix.componentInstance.esf.column = column; fix.detectChanges(); @@ -6625,13 +6416,13 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { UIInteractions.clickAndSendInputElementValue(inputNativeElement, 20, fix); const listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix); - expect(listItems.length).toBe(3, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(3); GridFunctions.clickExcelFilterIconFromCode(fix, grid, 'ProductName'); flush(); inputNativeElement = GridFunctions.getExcelStyleSearchComponentInput(fix); - expect(inputNativeElement.value).toBe('', 'input value didn\'t reset'); + expect(inputNativeElement.value, 'input value didn\'t reset').toBe(''); })); it('Should reset blank items on column change.', fakeAsync(() => { @@ -6707,7 +6498,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Update scrollbar scrollbar = GridFunctions.getExcelStyleSearchComponentScrollbar(fix); - expect(scrollbar.scrollTop).toBe(0, 'search scrollbar did not reset'); + expect(scrollbar.scrollTop, 'search scrollbar did not reset').toBe(0); }); }); @@ -6728,7 +6519,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Verify items in search have not loaded yet and that the loading indicator is visible. let listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix); - expect(listItems.length).toBe(0, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(0); let loadingIndicator = GridFunctions.getExcelFilteringLoadingIndicator(fix); expect(loadingIndicator).not.toBeNull('esf loading indicator is not visible'); @@ -6737,9 +6528,9 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Verify items in search have loaded and that the loading indicator is not visible. listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix); - expect(listItems.length).toBe(6, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(6); loadingIndicator = GridFunctions.getExcelFilteringLoadingIndicator(fix); - expect(loadingIndicator).toBeNull('esf loading indicator is visible'); + expect(loadingIndicator, 'esf loading indicator is visible').toBeNull(); })); it('Verify unique values are loaded correctly in ESF search component when using filtering strategy.', fakeAsync(() => { @@ -6754,7 +6545,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Verify items in search have not loaded yet and that the loading indicator is visible. let listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix); - expect(listItems.length).toBe(0, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(0); let loadingIndicator = GridFunctions.getExcelFilteringLoadingIndicator(fix); expect(loadingIndicator).not.toBeNull('esf loading indicator is not visible'); @@ -6763,9 +6554,9 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Verify items in search have loaded and that the loading indicator is not visible. listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix); - expect(listItems.length).toBe(6, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(6); loadingIndicator = GridFunctions.getExcelFilteringLoadingIndicator(fix); - expect(loadingIndicator).toBeNull('esf loading indicator is visible'); + expect(loadingIndicator, 'esf loading indicator is visible').toBeNull(); })); it('Verify unique date values are loaded correctly in ESF search component.', fakeAsync(() => { @@ -6776,7 +6567,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Verify items in search have not loaded yet and that the loading indicator is visible. let listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix); - expect(listItems.length).toBe(0, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(0); let loadingIndicator = GridFunctions.getExcelFilteringLoadingIndicator(fix); expect(loadingIndicator).not.toBeNull('esf loading indicator is not visible'); @@ -6785,9 +6576,9 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Verify items in search have loaded and that the loading indicator is not visible. listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix); - expect(listItems.length).toBe(7, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(7); loadingIndicator = GridFunctions.getExcelFilteringLoadingIndicator(fix); - expect(loadingIndicator).toBeNull('esf loading indicator is visible'); + expect(loadingIndicator, 'esf loading indicator is visible').toBeNull(); })); it('Verify unique ISO 8601 date values are loaded correctly in ESF search component.', fakeAsync(() => { @@ -6805,7 +6596,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Verify items in search have not loaded yet and that the loading indicator is visible. let listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix); - expect(listItems.length).toBe(0, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(0); let loadingIndicator = GridFunctions.getExcelFilteringLoadingIndicator(fix); expect(loadingIndicator).not.toBeNull('esf loading indicator is not visible'); @@ -6814,9 +6605,9 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Verify items in search have loaded and that the loading indicator is not visible. listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix); - expect(listItems.length).toBe(7, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(7); loadingIndicator = GridFunctions.getExcelFilteringLoadingIndicator(fix); - expect(loadingIndicator).toBeNull('esf loading indicator is visible'); + expect(loadingIndicator, 'esf loading indicator is visible').toBeNull(); })); it('Verify unique milliseconds date values are loaded correctly in ESF search component.', fakeAsync(() => { @@ -6834,7 +6625,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Verify items in search have not loaded yet and that the loading indicator is visible. let listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix); - expect(listItems.length).toBe(0, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(0); let loadingIndicator = GridFunctions.getExcelFilteringLoadingIndicator(fix); expect(loadingIndicator).not.toBeNull('esf loading indicator is not visible'); @@ -6843,9 +6634,9 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Verify items in search have loaded and that the loading indicator is not visible. listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix); - expect(listItems.length).toBe(7, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(7); loadingIndicator = GridFunctions.getExcelFilteringLoadingIndicator(fix); - expect(loadingIndicator).toBeNull('esf loading indicator is visible'); + expect(loadingIndicator, 'esf loading indicator is visible').toBeNull(); })); it('Verify date values are displayed in correct format according to column pipeArgs', fakeAsync(() => { @@ -6873,7 +6664,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Verify items in search have loaded and that the loading indicator is not visible. let listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix); - expect(listItems.length).toBe(7, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(7); for (let i = 2; i < listItems.length; i++) { const label = datePipe.transform(dates[i - 2], formatOptions.format); @@ -6881,7 +6672,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { } const loadingIndicator = GridFunctions.getExcelFilteringLoadingIndicator(fix); - expect(loadingIndicator).toBeNull('esf loading indicator is visible'); + expect(loadingIndicator, 'esf loading indicator is visible').toBeNull(); // Open excel style custom filtering dialog and wait a bit. GridFunctions.clickExcelFilterIcon(fix, 'Downloads'); @@ -6890,7 +6681,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Verify items in search have loaded and that the loading indicator is not visible. listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix); - expect(listItems.length).toBe(7, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(7); listItems.forEach((item, ind) => { expect(item.innerText).toBe(downloads[ind]); @@ -6921,7 +6712,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Verify items in search have loaded and that the loading indicator is not visible. const listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix); - expect(listItems.length).toBe(7, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(7); expect(listItems[1].innerText).toBe('(Blanks)'); for (let i = 2; i < listItems.length; i++) { @@ -6931,7 +6722,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { } const loadingIndicator = GridFunctions.getExcelFilteringLoadingIndicator(fix); - expect(loadingIndicator).toBeNull('esf loading indicator is visible'); + expect(loadingIndicator, 'esf loading indicator is visible').toBeNull(); })); it('Verify date values are displayed in correct format according to column formatter after filtering', fakeAsync(() => { @@ -6954,7 +6745,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Verify items in search have loaded and that the loading indicator is not visible. let listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix); - expect(listItems.length).toBe(7, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(7); const checkboxElements = GridFunctions.getExcelStyleFilteringCheckboxes(fix); checkboxElements[2].click(); @@ -6970,7 +6761,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { fix.detectChanges(); listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix); - expect(listItems.length).toBe(7, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(7); expect(listItems[1].innerText).toBe('(Blanks)'); for (let i = 2; i < listItems.length; i++) { @@ -6980,7 +6771,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { } const loadingIndicator = GridFunctions.getExcelFilteringLoadingIndicator(fix); - expect(loadingIndicator).toBeNull('esf loading indicator is visible'); + expect(loadingIndicator, 'esf loading indicator is visible').toBeNull(); })); it('Done callback should be executed only once per column', fakeAsync(() => { @@ -6991,20 +6782,20 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { fix.detectChanges(); // Verify items in search have loaded and that the loading indicator is not visible. - expect(compInstance.doneCallbackCounter).toBe(1, 'Incorrect done callback execution count'); + expect(compInstance.doneCallbackCounter, 'Incorrect done callback execution count').toBe(1); let listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix); - expect(listItems.length).toBe(6, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(6); let loadingIndicator = GridFunctions.getExcelFilteringLoadingIndicator(fix); - expect(loadingIndicator).toBeNull('esf loading indicator is visible'); + expect(loadingIndicator, 'esf loading indicator is visible').toBeNull(); GridFunctions.clickExcelFilterIcon(fix, 'Downloads'); tick(1000); fix.detectChanges(); - expect(compInstance.doneCallbackCounter).toBe(2, 'Incorrect done callback execution count'); + expect(compInstance.doneCallbackCounter, 'Incorrect done callback execution count').toBe(2); listItems = GridFunctions.getExcelStyleSearchComponentListItems(fix); - expect(listItems.length).toBe(7, 'incorrect rendered list items count'); + expect(listItems.length, 'incorrect rendered list items count').toBe(7); loadingIndicator = GridFunctions.getExcelFilteringLoadingIndicator(fix); - expect(loadingIndicator).toBeNull('esf loading indicator is visible'); + expect(loadingIndicator, 'esf loading indicator is visible').toBeNull(); })); it('Should not execute done callback for null column', fakeAsync(() => { @@ -7069,7 +6860,8 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { }); describe('External Excel Style Filtering', () => { - let fix; let grid; + let fix; + let grid; beforeEach(fakeAsync(() => { fix = TestBed.createComponent(IgxGridExternalESFComponent); grid = fix.componentInstance.grid; @@ -7090,8 +6882,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // filter verifyExcelStyleFilterAvailableOptions(fix, ['Select All', '(Blanks)', 'Ignite UI for Angular', - 'Ignite UI for JavaScript', 'NetAdvantage', 'Some other item with Script'], - [true, true, true, true, true, true]); + 'Ignite UI for JavaScript', 'NetAdvantage', 'Some other item with Script'], [true, true, true, true, true, true]); toggleExcelStyleFilteringItems(fix, true, 1, 4); expect(grid.rowList.length).toBe(3); @@ -7129,7 +6920,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { grid.columnSelection = GridSelectionMode.multiple; fix.detectChanges(); - spyOn(grid.columnSelectionChanging, 'emit'); + vi.spyOn(grid.columnSelectionChanging, 'emit'); const column = grid.getColumnByName('Downloads'); fix.componentInstance.esf.column = column; tick(); @@ -7204,7 +6995,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { })); it('Should not throw console error on opening the drop-down.', async () => { - spyOn(console, 'error'); + vi.spyOn(console, 'error'); GridFunctions.clickExcelFilterIconFromCodeAsync(fix, grid, 'Downloads'); fix.detectChanges(); await wait(100); @@ -7269,8 +7060,7 @@ describe('IgxGrid - Custom Filtering Strategy #grid', () => { GridFunctions.submitFilterRowInput(fix); fix.detectChanges(); - expect(grid.filteredData).toEqual( - [{ ID: 1, Name: { FirstName: 'Casey', LastName: 'Houston' }, JobTitle: 'Vice President', Company: 'Company A' }]); + expect(grid.filteredData).toEqual([{ ID: 1, Name: { FirstName: 'Casey', LastName: 'Houston' }, JobTitle: 'Vice President', Company: 'Company A' }]); })); it('Should be able to override findMatchByExpression method', fakeAsync(() => { @@ -7286,7 +7076,8 @@ describe('IgxGrid - Custom Filtering Strategy #grid', () => { expect(grid.filteredData).toEqual([ { ID: 2, Name: { FirstName: 'Gilberto', LastName: 'Todd' }, JobTitle: 'Director', Company: 'Company C' }, - { ID: 3, Name: { FirstName: 'Tanya', LastName: 'Bennett' }, JobTitle: 'Director', Company: 'Company A' }]); + { ID: 3, Name: { FirstName: 'Tanya', LastName: 'Bennett' }, JobTitle: 'Director', Company: 'Company A' } + ]); GridFunctions.resetFilterRow(fix); GridFunctions.closeFilterRow(fix); fix.detectChanges(); @@ -7319,7 +7110,8 @@ describe('IgxGrid - Custom Filtering Strategy #grid', () => { ID: 7, Name: { FirstName: 'Debra', LastName: 'Morton' }, JobTitle: 'Associate Software Developer', Company: 'Company B' }, - { ID: 10, Name: { FirstName: 'Eduardo', LastName: 'Ramirez' }, JobTitle: 'Manager', Company: 'Company E' }]); + { ID: 10, Name: { FirstName: 'Eduardo', LastName: 'Ramirez' }, JobTitle: 'Manager', Company: 'Company E' } + ]); })); }); @@ -7424,12 +7216,9 @@ const verifyPinningHidingSize = (fix: ComponentFixture, expectedSize: ɵSiz // Get column pinning and column hiding icons from header (if present at all) const headerTitle = excelMenu.querySelector('h4'); const headerIcons: DebugElement[] = GridFunctions.getExcelFilteringHeaderIconsDebugElements(fix, excelMenu); - const headerAreaPinIcon: HTMLElement = - headerIcons.find((buttonIcon: DebugElement) => buttonIcon.query(By.directive(IgxIconComponent)).componentInstance.name === "pin")?.nativeElement; - const headerAreaUnpinIcon: HTMLElement - = headerIcons.find((buttonIcon: DebugElement) => buttonIcon.query(By.directive(IgxIconComponent)).componentInstance.name === "unpin")?.nativeElement; - const headerAreaColumnHidingIcon: HTMLElement = - headerIcons.find((buttonIcon: DebugElement) => buttonIcon.query(By.directive(IgxIconComponent)).componentInstance.name === 'hide')?.nativeElement; + const headerAreaPinIcon: HTMLElement = headerIcons.find((buttonIcon: DebugElement) => buttonIcon.query(By.directive(IgxIconComponent)).componentInstance.name === "pin")?.nativeElement; + const headerAreaUnpinIcon: HTMLElement = headerIcons.find((buttonIcon: DebugElement) => buttonIcon.query(By.directive(IgxIconComponent)).componentInstance.name === "unpin")?.nativeElement; + const headerAreaColumnHidingIcon: HTMLElement = headerIcons.find((buttonIcon: DebugElement) => buttonIcon.query(By.directive(IgxIconComponent)).componentInstance.name === 'hide')?.nativeElement; // Get column pinning and column hiding icons from actionsArea (if present at all) const actionsPinArea = GridFunctions.getExcelFilteringPinContainer(fix, excelMenu); @@ -7437,32 +7226,26 @@ const verifyPinningHidingSize = (fix: ComponentFixture, expectedSize: ɵSiz if (expectedSize === ɵSize.Large) { // Verify icons in header are not present. - expect(headerAreaPinIcon === null || headerAreaPinIcon === undefined).toBe(true, - 'headerArea pin icon is present'); - expect(headerAreaUnpinIcon === null || headerAreaUnpinIcon === undefined).toBe(true, - 'headerArea unpin icon is present'); - expect(headerAreaColumnHidingIcon === null || headerAreaColumnHidingIcon === undefined).toBe(true, - 'headerArea column hiding icon is present'); + expect(headerAreaPinIcon === null || headerAreaPinIcon === undefined, 'headerArea pin icon is present').toBe(true); + expect(headerAreaUnpinIcon === null || headerAreaUnpinIcon === undefined, 'headerArea unpin icon is present').toBe(true); + expect(headerAreaColumnHidingIcon === null || headerAreaColumnHidingIcon === undefined, 'headerArea column hiding icon is present').toBe(true); // Verify icons in actions area are present. - expect(actionsPinArea !== null).toBe(true, 'actionsArea pin/unpin icon is NOT present'); + expect(actionsPinArea !== null, 'actionsArea pin/unpin icon is NOT present').toBe(true); expect(actionsAreaColumnHidingIcon).not.toBeNull('actionsArea column hiding icon is NOT present'); } else { // Verify icons in header are present. - expect((headerAreaPinIcon !== null) || (headerAreaUnpinIcon !== null)).toBe(true, - 'headerArea pin/unpin icon is NOT present'); + expect((headerAreaPinIcon !== null) || (headerAreaUnpinIcon !== null), 'headerArea pin/unpin icon is NOT present').toBe(true); expect(headerAreaColumnHidingIcon).not.toBeNull('headerArea column hiding icon is NOT present'); // Verify icons in actions area are not present. - expect(actionsPinArea).toBeNull('actionsArea pin icon is present'); - expect(actionsAreaColumnHidingIcon).toBeNull('headerArea column hiding icon is present'); + expect(actionsPinArea, 'actionsArea pin icon is present').toBeNull(); + expect(actionsAreaColumnHidingIcon, 'headerArea column hiding icon is present').toBeNull(); // Verify icons are on right of the title const headerTitleRect = headerTitle.getBoundingClientRect(); const pinUnpinIconRect = ((headerAreaPinIcon !== null) ? headerAreaPinIcon : headerAreaUnpinIcon).getBoundingClientRect(); const columnHidingRect = headerAreaColumnHidingIcon.getBoundingClientRect(); - expect(pinUnpinIconRect.left >= headerTitleRect.right).toBe(true, - 'pinUnpin icon is NOT on the right of top header'); - expect(columnHidingRect.left > headerTitleRect.right).toBe(true, - 'columnHiding icon is NOT on the right of top header'); + expect(pinUnpinIconRect.left >= headerTitleRect.right, 'pinUnpin icon is NOT on the right of top header').toBe(true); + expect(columnHidingRect.left > headerTitleRect.right, 'columnHiding icon is NOT on the right of top header').toBe(true); } }; @@ -7483,24 +7266,16 @@ const verifySortMoveSize = (fix: ComponentFixture, expectedSize: ɵSize) => const isSmall = expectedSize === ɵSize.Small; // Verify sort buttons are on right of the sort title if size is 'small' // or that they are under the sort title if size is not 'small'. - expect(sortHeaderRect.right <= sortButtons[0].getBoundingClientRect().left).toBe(isSmall, - 'incorrect sort button horizontal position based on the sort title'); - expect(sortHeaderRect.right <= sortButtons[1].getBoundingClientRect().left).toBe(isSmall, - 'incorrect sort button horizontal position based on the sort title'); - expect(sortHeaderRect.bottom <= sortButtons[0].getBoundingClientRect().top).toBe(!isSmall, - 'incorrect sort button vertical position based on the sort title'); - expect(sortHeaderRect.bottom <= sortButtons[1].getBoundingClientRect().top).toBe(!isSmall, - 'incorrect sort button vertical position based on the sort title'); + expect(sortHeaderRect.right <= sortButtons[0].getBoundingClientRect().left, 'incorrect sort button horizontal position based on the sort title').toBe(isSmall); + expect(sortHeaderRect.right <= sortButtons[1].getBoundingClientRect().left, 'incorrect sort button horizontal position based on the sort title').toBe(isSmall); + expect(sortHeaderRect.bottom <= sortButtons[0].getBoundingClientRect().top, 'incorrect sort button vertical position based on the sort title').toBe(!isSmall); + expect(sortHeaderRect.bottom <= sortButtons[1].getBoundingClientRect().top, 'incorrect sort button vertical position based on the sort title').toBe(!isSmall); // Verify move buttons are on right of the move title if size is 'small' // or that they are under the sort title if size is not 'small'. - expect(moveHeaderRect.right < moveButtons[0].getBoundingClientRect().left).toBe(isSmall, - 'incorrect move button horizontal position based on the sort title'); - expect(moveHeaderRect.right < moveButtons[1].getBoundingClientRect().left).toBe(isSmall, - 'incorrect move button horizontal position based on the sort title'); - expect(moveHeaderRect.bottom <= moveButtons[0].getBoundingClientRect().top).toBe(!isSmall, - 'incorrect move button vertical position based on the sort title'); - expect(moveHeaderRect.bottom <= moveButtons[1].getBoundingClientRect().top).toBe(!isSmall, - 'incorrect move button vertical position based on the sort title'); + expect(moveHeaderRect.right < moveButtons[0].getBoundingClientRect().left, 'incorrect move button horizontal position based on the sort title').toBe(isSmall); + expect(moveHeaderRect.right < moveButtons[1].getBoundingClientRect().left, 'incorrect move button horizontal position based on the sort title').toBe(isSmall); + expect(moveHeaderRect.bottom <= moveButtons[0].getBoundingClientRect().top, 'incorrect move button vertical position based on the sort title').toBe(!isSmall); + expect(moveHeaderRect.bottom <= moveButtons[1].getBoundingClientRect().top, 'incorrect move button vertical position based on the sort title').toBe(!isSmall); }; const verifyExcelCustomFilterSize = (fix: ComponentFixture, expectedSize: ɵSize) => { @@ -7520,7 +7295,7 @@ const verifyExcelCustomFilterSize = (fix: ComponentFixture, expectedSize: // Verify size of all input groups in custom filter dialog. const inputGroups = customFilterMenu.querySelectorAll('igx-input-group'); inputGroups.forEach((inputGroup) => { - expect(getComponentSize(inputGroup)).toBe(expectedSize, 'incorrect inputGroup size in custom filter dialog'); + expect(getComponentSize(inputGroup), 'incorrect inputGroup size in custom filter dialog').toBe(expectedSize); }); }; @@ -7531,7 +7306,7 @@ const verifyGridSubmenuSize = (gridNativeElement: HTMLElement, expectedSize: ɵS const dropdownItems = visibleDropdown.querySelectorAll('igx-drop-down-item'); dropdownItems.forEach((dropdownItem) => { - expect(getComponentSize(dropdownItem)).toBe(expectedSize, 'incorrect dropdown item size'); + expect(getComponentSize(dropdownItem), 'incorrect dropdown item size').toBe(expectedSize); }); }; @@ -7546,7 +7321,7 @@ const verifyExcelStyleFilterAvailableOptions = (fix, labels: string[], checked: const labelElements: any[] = Array.from(GridFunctions.getExcelStyleSearchComponentListItems(fix, excelMenu)); const checkboxElements: any[] = Array.from(GridFunctions.getExcelStyleFilteringCheckboxes(fix, excelMenu)); - expect(labelElements.length).toBe(labels.length, 'incorrect rendered list items count'); + expect(labelElements.length, 'incorrect rendered list items count').toBe(labels.length); labels.forEach((l, index) => { expect(l).toEqual(labelElements[index].innerText.normalize("NFKD")); }); @@ -7594,8 +7369,7 @@ const verifyChipVisibility = (fix, index: number, shouldBeFullyVisible: boolean) const chip = GridFunctions.getFilterConditionChip(fix, index); const chipRect = chip.getBoundingClientRect(); - expect(chipRect.left >= visibleChipAreaRect.left && chipRect.right <= visibleChipAreaRect.right) - .toBe(shouldBeFullyVisible, 'chip[' + index + '] visibility is incorrect'); + expect(chipRect.left >= visibleChipAreaRect.left && chipRect.right <= visibleChipAreaRect.right, 'chip[' + index + '] visibility is incorrect').toBe(shouldBeFullyVisible); }; const emitFilteringDoneOnResetClick = (fix, grid, filterVal: any, columnName: string, condition) => { diff --git a/projects/igniteui-angular/grids/grid/src/grid-filtering.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-filtering.spec.ts index 3b583c90567..ef2f3f56f80 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-filtering.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-filtering.spec.ts @@ -1,6 +1,6 @@ import { TestBed, fakeAsync, tick, waitForAsync } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; -import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxGridComponent } from './grid.component'; import { SampleTestData } from '../../../test-utils/sample-test-data.spec'; import { GridFunctions, GridSummaryFunctions } from '../../../test-utils/grid-functions.spec'; @@ -8,6 +8,7 @@ import { IgxGridFilteringComponent, CustomFilter, IgxGridFilteringBindingCompone import { FilteringExpressionsTree, FilteringLogic, IFilteringExpression, IgxBooleanFilteringOperand, IgxDateFilteringOperand, IgxDateTimeFilteringOperand, IgxNumberFilteringOperand, IgxStringFilteringOperand, IgxTimeFilteringOperand, NoopFilteringStrategy } from 'igniteui-angular/core'; import { IgxChipComponent } from 'igniteui-angular/chips'; import { ExpressionUI } from 'igniteui-angular/grids/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxGrid - Filtering actions #grid', () => { beforeEach(waitForAsync(() => { @@ -18,7 +19,8 @@ describe('IgxGrid - Filtering actions #grid', () => { }).compileComponents(); })); - let fix; let grid; + let fix; + let grid; beforeEach(fakeAsync(() => { fix = TestBed.createComponent(IgxGridFilteringComponent); fix.detectChanges(); @@ -237,8 +239,7 @@ describe('IgxGrid - Filtering actions #grid', () => { const expectedResults = GridFunctions.createDateFilterConditions(grid, today); // After filter - grid.filter('ReleaseDate', cal.timedelta(today, 'day', 4), - IgxDateFilteringOperand.instance().condition('after')); + grid.filter('ReleaseDate', cal.timedelta(today, 'day', 4), IgxDateFilteringOperand.instance().condition('after')); fix.detectChanges(); expect(grid.rowList.length).toEqual(1); @@ -246,24 +247,21 @@ describe('IgxGrid - Filtering actions #grid', () => { grid.clearFilter('ReleaseDate'); fix.detectChanges(); expect(grid.rowList.length).toEqual(8); - grid.filter('ReleaseDate', cal.timedelta(today, 'day', 4), - IgxDateFilteringOperand.instance().condition('before')); + grid.filter('ReleaseDate', cal.timedelta(today, 'day', 4), IgxDateFilteringOperand.instance().condition('before')); fix.detectChanges(); expect(grid.rowList.length).toEqual(5); // DoesNotEqual filter grid.clearFilter('ReleaseDate'); fix.detectChanges(); - grid.filter('ReleaseDate', today, - IgxDateFilteringOperand.instance().condition('doesNotEqual')); + grid.filter('ReleaseDate', today, IgxDateFilteringOperand.instance().condition('doesNotEqual')); fix.detectChanges(); expect(grid.rowList.length).toEqual(7); // Equals filter grid.clearFilter('ReleaseDate'); fix.detectChanges(); - grid.filter('ReleaseDate', today, - IgxDateFilteringOperand.instance().condition('equals')); + grid.filter('ReleaseDate', today, IgxDateFilteringOperand.instance().condition('equals')); fix.detectChanges(); expect(grid.rowList.length).toEqual(1); @@ -353,8 +351,7 @@ describe('IgxGrid - Filtering actions #grid', () => { // At or After, Empty, Not Empty, Null, Not Null // At 11:15:35 - grid.filter('ReleaseTime', cal.timedelta(today, 'hour', 1), - IgxTimeFilteringOperand.instance().condition('at')); + grid.filter('ReleaseTime', cal.timedelta(today, 'hour', 1), IgxTimeFilteringOperand.instance().condition('at')); fix.detectChanges(); expect(grid.rowList.length).toEqual(1); @@ -362,8 +359,7 @@ describe('IgxGrid - Filtering actions #grid', () => { grid.clearFilter('ReleaseTime'); fix.detectChanges(); expect(grid.rowList.length).toEqual(8); - grid.filter('ReleaseTime', cal.timedelta(today, 'hour', -1), - IgxTimeFilteringOperand.instance().condition('not_at')); + grid.filter('ReleaseTime', cal.timedelta(today, 'hour', -1), IgxTimeFilteringOperand.instance().condition('not_at')); fix.detectChanges(); expect(grid.rowList.length).toEqual(7); @@ -371,8 +367,7 @@ describe('IgxGrid - Filtering actions #grid', () => { grid.clearFilter('ReleaseTime'); fix.detectChanges(); expect(grid.rowList.length).toEqual(8); - grid.filter('ReleaseTime', cal.timedelta(today, 'minute', +10), - IgxTimeFilteringOperand.instance().condition('before')); + grid.filter('ReleaseTime', cal.timedelta(today, 'minute', +10), IgxTimeFilteringOperand.instance().condition('before')); fix.detectChanges(); expect(grid.rowList.length).toEqual(4); @@ -380,8 +375,7 @@ describe('IgxGrid - Filtering actions #grid', () => { grid.clearFilter('ReleaseTime'); fix.detectChanges(); expect(grid.rowList.length).toEqual(8); - grid.filter('ReleaseTime', cal.timedelta(today, 'second', +20), - IgxTimeFilteringOperand.instance().condition('after')); + grid.filter('ReleaseTime', cal.timedelta(today, 'second', +20), IgxTimeFilteringOperand.instance().condition('after')); fix.detectChanges(); expect(grid.rowList.length).toEqual(2); @@ -389,8 +383,7 @@ describe('IgxGrid - Filtering actions #grid', () => { grid.clearFilter('ReleaseTime'); fix.detectChanges(); expect(grid.rowList.length).toEqual(8); - grid.filter('ReleaseTime', cal.timedelta(today, 'minute', +10), - IgxTimeFilteringOperand.instance().condition('at_before')); + grid.filter('ReleaseTime', cal.timedelta(today, 'minute', +10), IgxTimeFilteringOperand.instance().condition('at_before')); fix.detectChanges(); expect(grid.rowList.length).toEqual(5); @@ -398,8 +391,7 @@ describe('IgxGrid - Filtering actions #grid', () => { grid.clearFilter('ReleaseTime'); fix.detectChanges(); expect(grid.rowList.length).toEqual(8); - grid.filter('ReleaseTime', cal.timedelta(today, 'second', +20), - IgxTimeFilteringOperand.instance().condition('at_after')); + grid.filter('ReleaseTime', cal.timedelta(today, 'second', +20), IgxTimeFilteringOperand.instance().condition('at_after')); fix.detectChanges(); expect(grid.rowList.length).toEqual(3); @@ -441,21 +433,19 @@ describe('IgxGrid - Filtering actions #grid', () => { const today = SampleTestData.todayFullDate; // Equals 11:15:35 - grid.filter('ReleaseDateTime', cal.timedelta(today, 'hour', 1), - IgxDateTimeFilteringOperand.instance().condition('equals')); + grid.filter('ReleaseDateTime', cal.timedelta(today, 'hour', 1), IgxDateTimeFilteringOperand.instance().condition('equals')); fix.detectChanges(); expect(grid.rowList.length).toEqual(1); // Does not equal 11:15:35 - grid.filter('ReleaseDateTime', cal.timedelta(today, 'hour', 1), - IgxDateTimeFilteringOperand.instance().condition('doesNotEqual')); + grid.filter('ReleaseDateTime', cal.timedelta(today, 'hour', 1), IgxDateTimeFilteringOperand.instance().condition('doesNotEqual')); fix.detectChanges(); expect(grid.rowList.length).toEqual(7); })); it('should correctly filter with earliest/latest \'date\' values', fakeAsync(() => { const earliest = new Date(SampleTestData.timeGenerator.timedelta(SampleTestData.today, 'month', -1).getTime() + 7200 * 1000); - const latest = new Date(SampleTestData.timeGenerator.timedelta(SampleTestData.today, 'month', 1).getTime() - 7200 * 1000); + const latest = new Date(SampleTestData.timeGenerator.timedelta(SampleTestData.today, 'month', 1).getTime() - 7200 * 1000); // Before filter expect(grid.rowList.length).toEqual(8); @@ -503,7 +493,7 @@ describe('IgxGrid - Filtering actions #grid', () => { const cal = SampleTestData.timeGenerator; const today = SampleTestData.today; - grid.data = grid.data.map(rec => { + grid.data = grid.data.map(rec => { const newRec = Object.assign({}, rec) as any; newRec.ReleaseDate = rec.ReleaseDate ? rec.ReleaseDate.toISOString() : rec.ReleaseDate; return newRec; @@ -513,8 +503,7 @@ describe('IgxGrid - Filtering actions #grid', () => { const expectedResults = GridFunctions.createDateFilterConditions(grid, today); // After filter - grid.filter('ReleaseDate', cal.timedelta(today, 'day', 4), - IgxDateFilteringOperand.instance().condition('after')); + grid.filter('ReleaseDate', cal.timedelta(today, 'day', 4), IgxDateFilteringOperand.instance().condition('after')); fix.detectChanges(); expect(grid.rowList.length).toEqual(1); @@ -522,24 +511,21 @@ describe('IgxGrid - Filtering actions #grid', () => { grid.clearFilter('ReleaseDate'); fix.detectChanges(); expect(grid.rowList.length).toEqual(8); - grid.filter('ReleaseDate', cal.timedelta(today, 'day', 4), - IgxDateFilteringOperand.instance().condition('before')); + grid.filter('ReleaseDate', cal.timedelta(today, 'day', 4), IgxDateFilteringOperand.instance().condition('before')); fix.detectChanges(); expect(grid.rowList.length).toEqual(5); // DoesNotEqual filter grid.clearFilter('ReleaseDate'); fix.detectChanges(); - grid.filter('ReleaseDate', today, - IgxDateFilteringOperand.instance().condition('doesNotEqual')); + grid.filter('ReleaseDate', today, IgxDateFilteringOperand.instance().condition('doesNotEqual')); fix.detectChanges(); expect(grid.rowList.length).toEqual(7); // Equals filter grid.clearFilter('ReleaseDate'); fix.detectChanges(); - grid.filter('ReleaseDate', today, - IgxDateFilteringOperand.instance().condition('equals')); + grid.filter('ReleaseDate', today, IgxDateFilteringOperand.instance().condition('equals')); fix.detectChanges(); expect(grid.rowList.length).toEqual(1); @@ -625,7 +611,7 @@ describe('IgxGrid - Filtering actions #grid', () => { const cal = SampleTestData.timeGenerator; const today = SampleTestData.today; - grid.data = grid.data.map(rec => { + grid.data = grid.data.map(rec => { const newRec = Object.assign({}, rec) as any; newRec.ReleaseDate = rec.ReleaseDate ? rec.ReleaseDate.getTime() : rec.ReleaseDate; return newRec; @@ -635,8 +621,7 @@ describe('IgxGrid - Filtering actions #grid', () => { const expectedResults = GridFunctions.createDateFilterConditions(grid, today); // After filter - grid.filter('ReleaseDate', cal.timedelta(today, 'day', 4), - IgxDateFilteringOperand.instance().condition('after')); + grid.filter('ReleaseDate', cal.timedelta(today, 'day', 4), IgxDateFilteringOperand.instance().condition('after')); fix.detectChanges(); expect(grid.rowList.length).toEqual(1); @@ -644,24 +629,21 @@ describe('IgxGrid - Filtering actions #grid', () => { grid.clearFilter('ReleaseDate'); fix.detectChanges(); expect(grid.rowList.length).toEqual(8); - grid.filter('ReleaseDate', cal.timedelta(today, 'day', 4), - IgxDateFilteringOperand.instance().condition('before')); + grid.filter('ReleaseDate', cal.timedelta(today, 'day', 4), IgxDateFilteringOperand.instance().condition('before')); fix.detectChanges(); expect(grid.rowList.length).toEqual(5); // DoesNotEqual filter grid.clearFilter('ReleaseDate'); fix.detectChanges(); - grid.filter('ReleaseDate', today, - IgxDateFilteringOperand.instance().condition('doesNotEqual')); + grid.filter('ReleaseDate', today, IgxDateFilteringOperand.instance().condition('doesNotEqual')); fix.detectChanges(); expect(grid.rowList.length).toEqual(7); // Equals filter grid.clearFilter('ReleaseDate'); fix.detectChanges(); - grid.filter('ReleaseDate', today, - IgxDateFilteringOperand.instance().condition('equals')); + grid.filter('ReleaseDate', today, IgxDateFilteringOperand.instance().condition('equals')); fix.detectChanges(); expect(grid.rowList.length).toEqual(1); @@ -754,8 +736,8 @@ describe('IgxGrid - Filtering actions #grid', () => { })); it('should correctly apply multiple filtering through API', fakeAsync(() => { - spyOn(grid.filtering, 'emit'); - spyOn(grid.filteringDone, 'emit'); + vi.spyOn(grid.filtering, 'emit'); + vi.spyOn(grid.filteringDone, 'emit'); const gridExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And); gridExpressionsTree.filteringOperands = [ @@ -786,8 +768,8 @@ describe('IgxGrid - Filtering actions #grid', () => { })); it('should correctly apply global filtering', fakeAsync(() => { - spyOn(grid.filtering, 'emit'); - spyOn(grid.filteringDone, 'emit'); + vi.spyOn(grid.filtering, 'emit'); + vi.spyOn(grid.filteringDone, 'emit'); grid.filteringLogic = FilteringLogic.Or; grid.filterGlobal('some', IgxStringFilteringOperand.instance().condition('contains')); @@ -1029,8 +1011,8 @@ describe('IgxGrid - Filtering actions #grid', () => { })); it('Should always emit filteringDone with proper eventArgs, even when column does not exist', fakeAsync(() => { - spyOn(grid.filtering, 'emit'); - spyOn(grid.filteringDone, 'emit'); + vi.spyOn(grid.filtering, 'emit'); + vi.spyOn(grid.filteringDone, 'emit'); grid.filteringLogic = FilteringLogic.Or; grid.filter('Nonexisting', 'ignite', IgxStringFilteringOperand.instance().condition('contains'), true); @@ -1043,8 +1025,8 @@ describe('IgxGrid - Filtering actions #grid', () => { })); it('Should emit filteringDone when filtering globally', fakeAsync(() => { - spyOn(grid.filtering, 'emit'); - spyOn(grid.filteringDone, 'emit'); + vi.spyOn(grid.filtering, 'emit'); + vi.spyOn(grid.filteringDone, 'emit'); grid.filteringLogic = FilteringLogic.Or; grid.filterGlobal('some', IgxStringFilteringOperand.instance().condition('contains')); @@ -1057,8 +1039,8 @@ describe('IgxGrid - Filtering actions #grid', () => { })); it('Should keep existing expressionTree when filtering with a null expressionTree.', fakeAsync(() => { - spyOn(grid.filtering, 'emit'); - spyOn(grid.filteringDone, 'emit'); + vi.spyOn(grid.filtering, 'emit'); + vi.spyOn(grid.filteringDone, 'emit'); const expression1 = new FilteringExpressionsTree(FilteringLogic.Or, 'ProductName'); const expression11 = { @@ -1099,8 +1081,8 @@ describe('IgxGrid - Filtering actions #grid', () => { })); it('Should not clear previous filtering when filterGlobal() is called with invalid condition', fakeAsync(() => { - spyOn(grid.filtering, 'emit'); - spyOn(grid.filteringDone, 'emit'); + vi.spyOn(grid.filtering, 'emit'); + vi.spyOn(grid.filteringDone, 'emit'); grid.filter('Downloads', 100, IgxNumberFilteringOperand.instance().condition('greaterThan'), true); tick(30); @@ -1124,8 +1106,8 @@ describe('IgxGrid - Filtering actions #grid', () => { })); it('Should disable filtering feature when using NoopFilteringStrategy.', fakeAsync(() => { - spyOn(grid.filtering, 'emit'); - spyOn(grid.filteringDone, 'emit'); + vi.spyOn(grid.filtering, 'emit'); + vi.spyOn(grid.filteringDone, 'emit'); // Use the NoopFilteringStrategy. grid.filterStrategy = NoopFilteringStrategy.instance(); @@ -1157,7 +1139,8 @@ describe('IgxGrid - Filtering expression tree bindings #grid', () => { }).compileComponents(); })); - let fix; let grid: IgxGridComponent; + let fix; + let grid: IgxGridComponent; beforeEach(fakeAsync(() => { fix = TestBed.createComponent(IgxGridFilteringBindingComponent); fix.detectChanges(); @@ -1165,8 +1148,8 @@ describe('IgxGrid - Filtering expression tree bindings #grid', () => { })); it('should correctly filter with \'filteringExpressionsTree\' binding', fakeAsync(() => { - spyOn(grid.filtering, 'emit'); - spyOn(grid.filteringDone, 'emit'); + vi.spyOn(grid.filtering, 'emit'); + vi.spyOn(grid.filteringDone, 'emit'); // Verify initially filtered 'Downloads > 200' expect(grid.rowList.length).toEqual(3); @@ -1189,8 +1172,7 @@ describe('IgxGrid - Filtering expression tree bindings #grid', () => { })); }); -const verifyExpressionUI = (expressionUI: ExpressionUI, expression: IFilteringExpression, - afterOperator: FilteringLogic, beforeOperator: FilteringLogic) => { +const verifyExpressionUI = (expressionUI: ExpressionUI, expression: IFilteringExpression, afterOperator: FilteringLogic, beforeOperator: FilteringLogic) => { expect(expressionUI.expression).toBe(expression); expect(expressionUI.afterOperator).toBe(afterOperator); expect(expressionUI.beforeOperator).toBe(beforeOperator); diff --git a/projects/igniteui-angular/grids/grid/src/grid-keyBoardNav-headers.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-keyBoardNav-headers.spec.ts index 6514e85712d..e0b4586ee80 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-keyBoardNav-headers.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-keyBoardNav-headers.spec.ts @@ -4,16 +4,13 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxGridComponent } from './grid.component'; import { UIInteractions, wait } from '../../../test-utils/ui-interactions.spec'; import { clearGridSubs, setupGridScrollDetection } from '../../../test-utils/helper-utils.spec'; -import { - SelectionWithScrollsComponent, - MRLTestComponent, - ColumnGroupsNavigationTestComponent -} from '../../../test-utils/grid-samples.spec'; +import { SelectionWithScrollsComponent, MRLTestComponent, ColumnGroupsNavigationTestComponent } from '../../../test-utils/grid-samples.spec'; import { GridFunctions, GridSelectionFunctions } from '../../../test-utils/grid-functions.spec'; import { GridSelectionMode, FilterMode, IgxGridMRLNavigationService } from 'igniteui-angular/grids/core'; import { IActiveNodeChangeEventArgs } from 'igniteui-angular/grids/core'; import { IgxGridHeaderRowComponent } from 'igniteui-angular/grids/core'; import { IgxStringFilteringOperand, ISortingStrategy, SortingDirection } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; const DEBOUNCETIME = 30; @@ -79,7 +76,7 @@ describe('IgxGrid - Headers Keyboard navigation #grid', () => { }); it('should emit when activeNode ref is changed', () => { - spyOn(grid.activeNodeChange, 'emit').and.callThrough(); + vi.spyOn(grid.activeNodeChange, 'emit'); const args: IActiveNodeChangeEventArgs = { row: -1, @@ -288,9 +285,9 @@ describe('IgxGrid - Headers Keyboard navigation #grid', () => { expect(grid.headerContainer.getScroll().scrollLeft).toEqual(hScroll); }); - it('Sorting: Should be able to sort a column with the keyboard', fakeAsync (() => { - spyOn(grid.sorting, 'emit').and.callThrough(); - spyOn(grid.sortingDone, 'emit').and.callThrough(); + it('Sorting: Should be able to sort a column with the keyboard', fakeAsync(() => { + vi.spyOn(grid.sorting, 'emit'); + vi.spyOn(grid.sortingDone, 'emit'); grid.getColumnByName('ID').sortable = true; fix.detectChanges(); @@ -427,7 +424,7 @@ describe('IgxGrid - Headers Keyboard navigation #grid', () => { grid.getColumnByName('ID').filterable = false; fix.detectChanges(); - let header = GridFunctions.getColumnHeader('ID', fix); + let header = GridFunctions.getColumnHeader('ID', fix); UIInteractions.simulateClickAndSelectEvent(header); fix.detectChanges(); @@ -435,7 +432,7 @@ describe('IgxGrid - Headers Keyboard navigation #grid', () => { UIInteractions.triggerEventHandlerKeyDown('L', gridHeader, false, true, true); fix.detectChanges(); - let filterDialog = GridFunctions.getExcelStyleFilteringComponent(fix); + let filterDialog = GridFunctions.getExcelStyleFilteringComponent(fix); expect(filterDialog).toBeNull(); UIInteractions.triggerEventHandlerKeyDown('ArrowRight', gridHeader); @@ -447,7 +444,7 @@ describe('IgxGrid - Headers Keyboard navigation #grid', () => { UIInteractions.triggerEventHandlerKeyDown('L', gridHeader, false, true, true); fix.detectChanges(); - filterDialog = GridFunctions.getExcelStyleFilteringComponent(fix); + filterDialog = GridFunctions.getExcelStyleFilteringComponent(fix); expect(filterDialog).toBeDefined(); }); @@ -477,7 +474,7 @@ describe('IgxGrid - Headers Keyboard navigation #grid', () => { expect(GridFunctions.getAdvancedFilteringComponent(fix)).not.toBeNull(); }); - it('Advanced Filtering: Should be able to close Advanced filtering with "escape"', fakeAsync(() => { + it('Advanced Filtering: Should be able to close Advanced filtering with "escape"', fakeAsync(() => { // Enable Advanced Filtering grid.allowAdvancedFiltering = true; fix.detectChanges(); @@ -567,7 +564,7 @@ describe('IgxGrid - Headers Keyboard navigation #grid', () => { }); it('Column selection: Should be able to select columns when columnSelection is single', () => { - spyOn(grid.columnSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.columnSelectionChanging, 'emit'); const columnID = grid.getColumnByName('ID'); const columnParentID = grid.getColumnByName('ParentID'); const columnName = grid.getColumnByName('Name'); @@ -614,7 +611,7 @@ describe('IgxGrid - Headers Keyboard navigation #grid', () => { }); it('Group by: Should be able group columns with keyboard', () => { - spyOn(grid.groupingDone, 'emit').and.callThrough(); + vi.spyOn(grid.groupingDone, 'emit'); grid.getColumnByName('ID').groupable = true; grid.getColumnByName('Name').groupable = true; @@ -755,7 +752,7 @@ describe('IgxGrid - Headers Keyboard navigation #grid', () => { header = GridFunctions.getColumnHeader('ParentID', fix); - GridFunctions.verifyHeaderIsFocused(header.parent) + GridFunctions.verifyHeaderIsFocused(header.parent); GridFunctions.verifyHeaderActiveDescendant(gridHeader, header.nativeElement.id); }); }); @@ -1349,8 +1346,9 @@ describe('IgxGrid - Headers Keyboard navigation #grid', () => { it('Features Integration: should nor be possible to sort, filter or groupBy column group', () => { grid.allowAdvancedFiltering = true; grid.columns.forEach(c => { -c.sortable = true; c.groupable = true; -}); + c.sortable = true; + c.groupable = true; + }); fix.detectChanges(); const header = GridFunctions.getColumnGroupHeaderCell('General Information', fix); @@ -1370,28 +1368,28 @@ c.sortable = true; c.groupable = true; expect(grid.sortingExpressions.length).toEqual(0); - // Press Shift + Alt + Arrow left on group to groupBy it - UIInteractions.triggerEventHandlerKeyDown('ArrowRight', gridHeader, true, true); - fix.detectChanges(); + // Press Shift + Alt + Arrow left on group to groupBy it + UIInteractions.triggerEventHandlerKeyDown('ArrowRight', gridHeader, true, true); + fix.detectChanges(); - expect(grid.groupingExpressions.length).toEqual(0); + expect(grid.groupingExpressions.length).toEqual(0); - // Press Ctrl + Shift + L on group to open filter row - UIInteractions.triggerEventHandlerKeyDown('L', gridHeader, false, true, true); - fix.detectChanges(); + // Press Ctrl + Shift + L on group to open filter row + UIInteractions.triggerEventHandlerKeyDown('L', gridHeader, false, true, true); + fix.detectChanges(); - expect(GridFunctions.getFilterRow(fix)).toBeNull(); + expect(GridFunctions.getFilterRow(fix)).toBeNull(); - // Change filter mode to be excel style filter - grid.filterMode = FilterMode.excelStyleFilter; - fix.detectChanges(); + // Change filter mode to be excel style filter + grid.filterMode = FilterMode.excelStyleFilter; + fix.detectChanges(); - // Press Ctrl + Shift + L on group to open excel style filter - UIInteractions.triggerEventHandlerKeyDown('L', gridHeader, false, true, true); - fix.detectChanges(); + // Press Ctrl + Shift + L on group to open excel style filter + UIInteractions.triggerEventHandlerKeyDown('L', gridHeader, false, true, true); + fix.detectChanges(); - expect(GridFunctions.getExcelStyleFilteringComponent(fix)).toBeNull(); + expect(GridFunctions.getExcelStyleFilteringComponent(fix)).toBeNull(); }); it('MCH Grid with no data: should be able to navigate with arrow keys in the headers', () => { diff --git a/projects/igniteui-angular/grids/grid/src/grid-keyBoardNav.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-keyBoardNav.spec.ts index 8b48210269f..2506f281b7d 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-keyBoardNav.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-keyBoardNav.spec.ts @@ -4,17 +4,14 @@ import { IgxGridComponent } from './grid.component'; import { IGridCellEventArgs, IActiveNodeChangeEventArgs } from 'igniteui-angular/grids/core'; import { UIInteractions, wait } from '../../../test-utils/ui-interactions.spec'; import { clearGridSubs, setupGridScrollDetection } from '../../../test-utils/helper-utils.spec'; -import { - VirtualGridComponent, - NoScrollsComponent, - IgxGridGroupByComponent -} from '../../../test-utils/grid-samples.spec'; +import { VirtualGridComponent, NoScrollsComponent, IgxGridGroupByComponent } from '../../../test-utils/grid-samples.spec'; import { GridFunctions, GridSelectionFunctions } from '../../../test-utils/grid-functions.spec'; import { DebugElement, QueryList } from '@angular/core'; import { IgxGridGroupByRowComponent } from './groupby-row.component'; import { CellType } from 'igniteui-angular/grids/core'; import { DefaultSortingStrategy, SortingDirection } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; const DEBOUNCETIME = 30; @@ -126,7 +123,7 @@ describe('IgxGrid - Keyboard navigation #grid', () => { }); it('Should emit when activeNode ref is changed', () => { - spyOn(grid.activeNodeChange, 'emit').and.callThrough(); + vi.spyOn(grid.activeNodeChange, 'emit'); const args: IActiveNodeChangeEventArgs = { row: 0, @@ -164,7 +161,7 @@ describe('IgxGrid - Keyboard navigation #grid', () => { it('should emit activeNodeChange once when you click over the same element', () => { - spyOn(grid.activeNodeChange, 'emit').and.callThrough(); + vi.spyOn(grid.activeNodeChange, 'emit'); gridContent.triggerEventHandler('focus', null); fix.detectChanges(); @@ -667,8 +664,8 @@ describe('IgxGrid - Keyboard navigation #grid', () => { GridFunctions.focusFirstCell(fix, grid); grid.navigateTo(50, 50, (args) => { - args.target.activate(null); -}); + args.target.activate(null); + }); await wait(DEBOUNCETIME); fix.detectChanges(); await wait(DEBOUNCETIME); @@ -684,7 +681,7 @@ describe('IgxGrid - Keyboard navigation #grid', () => { fix.componentInstance.columns = fix.componentInstance.generateCols(25); fix.componentInstance.data = fix.componentInstance.generateData(25); fix.detectChanges(); - const gridKeydown = spyOn(grid.gridKeydown, 'emit').and.callThrough(); + const gridKeydown = vi.spyOn(grid.gridKeydown, 'emit'); const cell = grid.gridAPI.get_cell_by_index(1, '2'); UIInteractions.simulateClickAndSelectEvent(cell); @@ -867,7 +864,7 @@ describe('IgxGrid - Keyboard navigation #grid', () => { fix.detectChanges(); row = grid.gridAPI.get_row_by_index(1); - expect(row.focused).toBeTrue(); + expect(row.focused).toBe(true); })); it('should persist last selected cell column index when navigate through group rows.', async () => { @@ -999,8 +996,8 @@ describe('IgxGrid - Keyboard navigation #grid', () => { fix.detectChanges(); grid.navigateTo(9, -1, (args) => { - args.target.nativeElement.dispatchEvent(new Event('pointerdown')); -}); + args.target.nativeElement.dispatchEvent(new Event('pointerdown')); + }); await wait(100); fix.detectChanges(); await wait(100); @@ -1021,7 +1018,7 @@ describe('IgxGrid - Keyboard navigation #grid', () => { UIInteractions.simulateClickAndSelectEvent(rowEl); fix.detectChanges(); - const gridKeydown = spyOn(grid.gridKeydown, 'emit').and.callThrough(); + const gridKeydown = vi.spyOn(grid.gridKeydown, 'emit'); UIInteractions.triggerKeyDownEvtUponElem('Enter', rowEl.nativeElement, true); await wait(DEBOUNCETIME); fix.detectChanges(); diff --git a/projects/igniteui-angular/grids/grid/src/grid-mrl-keyboard-nav.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-mrl-keyboard-nav.spec.ts index 902c33ca6ff..1e86fe1cfc8 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-mrl-keyboard-nav.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-mrl-keyboard-nav.spec.ts @@ -1,4 +1,4 @@ -import { Component, ViewChild } from '@angular/core'; +import { Component, ViewChild } from '@angular/core'; import { TestBed, ComponentFixture, fakeAsync, tick, waitForAsync } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; @@ -11,6 +11,7 @@ import { GridFunctions, GRID_MRL_BLOCK } from '../../../test-utils/grid-function import { CellType, IGridCellEventArgs, IgxColumnComponent, IgxGridMRLNavigationService } from 'igniteui-angular/grids/core'; import { IgxColumnLayoutComponent } from 'igniteui-angular/grids/core'; import { DefaultSortingStrategy, SortingDirection } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach } from 'vitest'; const DEBOUNCE_TIME = 30; const CELL_CSS_CLASS = '.igx-grid__td'; @@ -78,17 +79,17 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should navigate between column layouts with right arrow key', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 1 } - ] - }, { - group: 'group2', - columns: [ - { field: 'Phone', rowStart: 1, colStart: 1, rowEnd: 3 } - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 1 } + ] + }, { + group: 'group2', + columns: [ + { field: 'Phone', rowStart: 1, colStart: 1, rowEnd: 3 } + ] + }]; fix.detectChanges(); const [_firstCell, secondCell, _thirdCell] = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS)); @@ -107,17 +108,17 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should navigate between column layouts with left key', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, rowEnd: 3 } - ] - }, { - group: 'group2', - columns: [ - { field: 'Phone', rowStart: 1, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 1 } - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, rowEnd: 3 } + ] + }, { + group: 'group2', + columns: [ + { field: 'Phone', rowStart: 1, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 1 } + ] + }]; fix.detectChanges(); const [_firstCell, _secondCell, thirdCell] = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS)); @@ -136,13 +137,13 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should navigate down and up to a cell from the same column layout from a cell with bigger col span', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'Phone', rowStart: 2, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 2 } - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'Phone', rowStart: 2, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 2 } + ] + }]; fix.detectChanges(); const [firstCell, _secondCell, _thirdCell] = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS)); @@ -164,13 +165,13 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should navigate down and up to a cell from the same column layout to a cell with bigger col span', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'Phone', rowStart: 1, colStart: 1 }, - { field: 'City', rowStart: 1, colStart: 2 }, - { field: 'ContactName', rowStart: 2, colStart: 1, colEnd: 3 } - ] - }]; + group: 'group1', + columns: [ + { field: 'Phone', rowStart: 1, colStart: 1 }, + { field: 'City', rowStart: 1, colStart: 2 }, + { field: 'ContactName', rowStart: 2, colStart: 1, colEnd: 3 } + ] + }]; fix.detectChanges(); const [_firstCell, secondCell, _thirdCell] = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS)); @@ -192,14 +193,14 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should navigate down and up to a cell from the same column layout according to its starting location', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'Phone', rowStart: 1, colStart: 1 }, - { field: 'City', rowStart: 1, colStart: 2, colEnd: 4 }, - { field: 'ContactName', rowStart: 2, colStart: 1, colEnd: 3 }, - { field: 'ContactTitle', rowStart: 2, colStart: 3 } - ] - }]; + group: 'group1', + columns: [ + { field: 'Phone', rowStart: 1, colStart: 1 }, + { field: 'City', rowStart: 1, colStart: 2, colEnd: 4 }, + { field: 'ContactName', rowStart: 2, colStart: 1, colEnd: 3 }, + { field: 'ContactTitle', rowStart: 2, colStart: 3 } + ] + }]; fix.detectChanges(); const [_firstCell, secondCell, _thirdCell] = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS)); @@ -221,13 +222,13 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should allow navigating down to a cell from the next row', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'Phone', rowStart: 1, colStart: 1 }, - { field: 'City', rowStart: 1, colStart: 2 }, - { field: 'ContactName', rowStart: 2, colStart: 1, colEnd: 3 } - ] - }]; + group: 'group1', + columns: [ + { field: 'Phone', rowStart: 1, colStart: 1 }, + { field: 'City', rowStart: 1, colStart: 2 }, + { field: 'ContactName', rowStart: 2, colStart: 1, colEnd: 3 } + ] + }]; fix.detectChanges(); const [_firstCell, _secondCell, thirdCell] = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS)); @@ -244,19 +245,19 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should allow navigating down to a cell from the next row with hidden column layout', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - hidden: true, - columns: [ - { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 3 } - ] - }, { - group: 'group2', - columns: [ - { field: 'Phone', rowStart: 1, colStart: 1 }, - { field: 'City', rowStart: 1, colStart: 2 }, - { field: 'ContactName', rowStart: 2, colStart: 1, colEnd: 3 } - ] - }]; + group: 'group1', + hidden: true, + columns: [ + { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 3 } + ] + }, { + group: 'group2', + columns: [ + { field: 'Phone', rowStart: 1, colStart: 1 }, + { field: 'City', rowStart: 1, colStart: 2 }, + { field: 'ContactName', rowStart: 2, colStart: 1, colEnd: 3 } + ] + }]; fix.detectChanges(); const [_firstCell, _secondCell, thirdCell] = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS)); @@ -273,13 +274,13 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should retain the focus when the first cell is reached', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'Phone', rowStart: 1, colStart: 1 }, - { field: 'City', rowStart: 1, colStart: 2 }, - { field: 'ContactName', rowStart: 2, colStart: 1, colEnd: 3 } - ] - }]; + group: 'group1', + columns: [ + { field: 'Phone', rowStart: 1, colStart: 1 }, + { field: 'City', rowStart: 1, colStart: 2 }, + { field: 'ContactName', rowStart: 2, colStart: 1, colEnd: 3 } + ] + }]; fix.detectChanges(); const [_firstCell, secondCell, _thirdCell] = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS)); @@ -299,13 +300,13 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should navigate up correctly', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'Phone', rowStart: 2, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 2 } - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'Phone', rowStart: 2, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 2 } + ] + }]; fix.detectChanges(); @@ -323,19 +324,19 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('navigate to right and left with hidden columns', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - hidden: true, - columns: [ - { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 3 } - ] - }, { - group: 'group2', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'Phone', rowStart: 2, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 2 } - ] - }]; + group: 'group1', + hidden: true, + columns: [ + { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 3 } + ] + }, { + group: 'group2', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'Phone', rowStart: 2, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 2 } + ] + }]; fix.detectChanges(); const [_firstCell, secondCell, _thirdCell] = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS)); @@ -359,34 +360,34 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it(`should navigate to the first cell from the layout by pressing Ctrl + Arrow Left and Right key and then Arrow Up + Down to same cell`, async () => { fix.componentInstance.colGroups = [{ - group: 'group1', - hidden: true, - columns: [ - { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 3 } - ] - }, { - group: 'group2', - columns: [ - { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'ContactName', rowStart: 2, colStart: 1 }, - { field: 'ContactTitle', rowStart: 2, colStart: 2 }, - { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } - ] - }, { - group: 'group3', - columns: [ - { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, - { field: 'Region', rowStart: 3, colStart: 1 }, - { field: 'PostalCode', rowStart: 3, colStart: 2 } - ] - }, { - group: 'group4', - columns: [ - { field: 'Country', rowStart: 1, colStart: 1 }, - { field: 'Phone', rowStart: 1, colStart: 2 }, - { field: 'Fax', rowStart: 2, colStart: 1, colEnd: 3, rowEnd: 4 } - ] - }]; + group: 'group1', + hidden: true, + columns: [ + { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 3 } + ] + }, { + group: 'group2', + columns: [ + { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'ContactName', rowStart: 2, colStart: 1 }, + { field: 'ContactTitle', rowStart: 2, colStart: 2 }, + { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } + ] + }, { + group: 'group3', + columns: [ + { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, + { field: 'Region', rowStart: 3, colStart: 1 }, + { field: 'PostalCode', rowStart: 3, colStart: 2 } + ] + }, { + group: 'group4', + columns: [ + { field: 'Country', rowStart: 1, colStart: 1 }, + { field: 'Phone', rowStart: 1, colStart: 2 }, + { field: 'Fax', rowStart: 2, colStart: 1, colEnd: 3, rowEnd: 4 } + ] + }]; fix.detectChanges(); const rows = fix.debugElement.queryAll(By.css(ROW_CSS_CLASS)); const firstRowCell = rows[1].queryAll(By.css(CELL_CSS_CLASS)); @@ -427,34 +428,34 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it(`should navigate to the first cell from the layout by pressing Ctrl + Arrow Right and Left key and then Arrow Up + Down to same cell`, async () => { fix.componentInstance.colGroups = [{ - group: 'group1', - hidden: true, - columns: [ - { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 3 } - ] - }, { - group: 'group2', - columns: [ - { field: 'Country', rowStart: 1, colStart: 1 }, - { field: 'Phone', rowStart: 1, colStart: 2 }, - { field: 'Fax', rowStart: 2, colStart: 1, colEnd: 3, rowEnd: 4 } - ] - }, { - group: 'group3', - columns: [ - { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, - { field: 'Region', rowStart: 3, colStart: 1 }, - { field: 'PostalCode', rowStart: 3, colStart: 2 } - ] - }, { - group: 'group4', - columns: [ - { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'ContactName', rowStart: 2, colStart: 1 }, - { field: 'ContactTitle', rowStart: 2, colStart: 2 }, - { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } - ] - }]; + group: 'group1', + hidden: true, + columns: [ + { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 3 } + ] + }, { + group: 'group2', + columns: [ + { field: 'Country', rowStart: 1, colStart: 1 }, + { field: 'Phone', rowStart: 1, colStart: 2 }, + { field: 'Fax', rowStart: 2, colStart: 1, colEnd: 3, rowEnd: 4 } + ] + }, { + group: 'group3', + columns: [ + { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, + { field: 'Region', rowStart: 3, colStart: 1 }, + { field: 'PostalCode', rowStart: 3, colStart: 2 } + ] + }, { + group: 'group4', + columns: [ + { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'ContactName', rowStart: 2, colStart: 1 }, + { field: 'ContactTitle', rowStart: 2, colStart: 2 }, + { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } + ] + }]; await wait(DEBOUNCE_TIME); fix.detectChanges(); const rows = fix.debugElement.queryAll(By.css(ROW_CSS_CLASS)); @@ -495,17 +496,17 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should navigate using Arrow Left through bigger cell with same rowStart but bigger row span', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ID', rowStart: 1, colStart: 1 }, - { field: 'CompanyName', rowStart: 1, colStart: 2, rowEnd: 3 }, - { field: 'ContactName', rowStart: 1, colStart: 3 }, - { field: 'ContactTitle', rowStart: 2, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 3 }, - { field: 'Country', rowStart: 3, colStart: 1 }, - { field: 'Address', rowStart: 3, colStart: 2, colEnd: 4 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ID', rowStart: 1, colStart: 1 }, + { field: 'CompanyName', rowStart: 1, colStart: 2, rowEnd: 3 }, + { field: 'ContactName', rowStart: 1, colStart: 3 }, + { field: 'ContactTitle', rowStart: 2, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 3 }, + { field: 'Country', rowStart: 3, colStart: 1 }, + { field: 'Address', rowStart: 3, colStart: 2, colEnd: 4 }, + ] + }]; fix.detectChanges(); const [_thirdCell, _secondCell, firstCell] = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS)); @@ -528,17 +529,17 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should navigate using Arrow Left through bigger cell with smaller rowStart and bigger rowEnd', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ID', rowStart: 1, colStart: 1 }, - { field: 'CompanyName', rowStart: 1, colStart: 2, rowEnd: 3 }, - { field: 'ContactName', rowStart: 1, colStart: 3 }, - { field: 'ContactTitle', rowStart: 2, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 3 }, - { field: 'Country', rowStart: 3, colStart: 1 }, - { field: 'Address', rowStart: 3, colStart: 2, colEnd: 4 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ID', rowStart: 1, colStart: 1 }, + { field: 'CompanyName', rowStart: 1, colStart: 2, rowEnd: 3 }, + { field: 'ContactName', rowStart: 1, colStart: 3 }, + { field: 'ContactTitle', rowStart: 2, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 3 }, + { field: 'Country', rowStart: 3, colStart: 1 }, + { field: 'Address', rowStart: 3, colStart: 2, colEnd: 4 }, + ] + }]; fix.detectChanges(); const firstCell = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS))[4]; @@ -561,17 +562,17 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should navigate using Arrow Right through bigger cell with same rowStart but bigger row', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ID', rowStart: 1, colStart: 1 }, - { field: 'CompanyName', rowStart: 1, colStart: 2, rowEnd: 3 }, - { field: 'ContactName', rowStart: 1, colStart: 3 }, - { field: 'ContactTitle', rowStart: 2, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 3 }, - { field: 'Country', rowStart: 3, colStart: 1 }, - { field: 'Address', rowStart: 3, colStart: 2, colEnd: 4 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ID', rowStart: 1, colStart: 1 }, + { field: 'CompanyName', rowStart: 1, colStart: 2, rowEnd: 3 }, + { field: 'ContactName', rowStart: 1, colStart: 3 }, + { field: 'ContactTitle', rowStart: 2, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 3 }, + { field: 'Country', rowStart: 3, colStart: 1 }, + { field: 'Address', rowStart: 3, colStart: 2, colEnd: 4 }, + ] + }]; fix.detectChanges(); const [firstCell, _secondCell, _thirdCell] = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS)); @@ -594,17 +595,17 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should navigate using Arrow Right through bigger cell with smaller rowStart and bigger rowEnd', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ID', rowStart: 1, colStart: 1 }, - { field: 'CompanyName', rowStart: 1, colStart: 2, rowEnd: 3 }, - { field: 'ContactName', rowStart: 1, colStart: 3 }, - { field: 'ContactTitle', rowStart: 2, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 3 }, - { field: 'Country', rowStart: 3, colStart: 1 }, - { field: 'Address', rowStart: 3, colStart: 2, colEnd: 4 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ID', rowStart: 1, colStart: 1 }, + { field: 'CompanyName', rowStart: 1, colStart: 2, rowEnd: 3 }, + { field: 'ContactName', rowStart: 1, colStart: 3 }, + { field: 'ContactTitle', rowStart: 2, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 3 }, + { field: 'Country', rowStart: 3, colStart: 1 }, + { field: 'Address', rowStart: 3, colStart: 2, colEnd: 4 }, + ] + }]; fix.detectChanges(); const firstCell = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS))[3]; @@ -627,17 +628,17 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should navigate using Arrow Down through cell with same colStart but bigger colEnd', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ID', rowStart: 1, colStart: 1 }, - { field: 'CompanyName', rowStart: 1, colStart: 2, rowEnd: 3 }, - { field: 'ContactName', rowStart: 1, colStart: 3 }, - { field: 'ContactTitle', rowStart: 2, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 3 }, - { field: 'Country', rowStart: 3, colStart: 1 }, - { field: 'Address', rowStart: 3, colStart: 2, colEnd: 4 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ID', rowStart: 1, colStart: 1 }, + { field: 'CompanyName', rowStart: 1, colStart: 2, rowEnd: 3 }, + { field: 'ContactName', rowStart: 1, colStart: 3 }, + { field: 'ContactTitle', rowStart: 2, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 3 }, + { field: 'Country', rowStart: 3, colStart: 1 }, + { field: 'Address', rowStart: 3, colStart: 2, colEnd: 4 }, + ] + }]; fix.detectChanges(); const firstCell = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS))[1]; @@ -669,17 +670,17 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should navigate using Arrow Down through cell with smaller colStart and bigger colEnd', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ID', rowStart: 1, colStart: 1 }, - { field: 'CompanyName', rowStart: 1, colStart: 2, rowEnd: 3 }, - { field: 'ContactName', rowStart: 1, colStart: 3 }, - { field: 'ContactTitle', rowStart: 2, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 3 }, - { field: 'Country', rowStart: 3, colStart: 1 }, - { field: 'Address', rowStart: 3, colStart: 2, colEnd: 4 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ID', rowStart: 1, colStart: 1 }, + { field: 'CompanyName', rowStart: 1, colStart: 2, rowEnd: 3 }, + { field: 'ContactName', rowStart: 1, colStart: 3 }, + { field: 'ContactTitle', rowStart: 2, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 3 }, + { field: 'Country', rowStart: 3, colStart: 1 }, + { field: 'Address', rowStart: 3, colStart: 2, colEnd: 4 }, + ] + }]; fix.detectChanges(); const firstCell = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS))[4]; @@ -711,17 +712,17 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should navigate using Arrow Up through cell with smaller colStart and bigger colEnd', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ID', rowStart: 1, colStart: 1 }, - { field: 'CompanyName', rowStart: 1, colStart: 2, rowEnd: 3 }, - { field: 'ContactName', rowStart: 1, colStart: 3 }, - { field: 'ContactTitle', rowStart: 2, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 3 }, - { field: 'Country', rowStart: 3, colStart: 1 }, - { field: 'Address', rowStart: 3, colStart: 2, colEnd: 4 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ID', rowStart: 1, colStart: 1 }, + { field: 'CompanyName', rowStart: 1, colStart: 2, rowEnd: 3 }, + { field: 'ContactName', rowStart: 1, colStart: 3 }, + { field: 'ContactTitle', rowStart: 2, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 3 }, + { field: 'Country', rowStart: 3, colStart: 1 }, + { field: 'Address', rowStart: 3, colStart: 2, colEnd: 4 }, + ] + }]; fix.detectChanges(); const firstCell = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS))[9]; @@ -753,29 +754,29 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should navigate correctly with column group is hidden.', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - // row span 3 - columns: [ - { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 4 } - ] - }, { - group: 'group2', - columns: [ - // col span 2 - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'Phone', rowStart: 2, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 2 }, - // col span 2 - { field: 'ContactTitle', rowStart: 3, colStart: 1, colEnd: 3 } - ] - }, { - group: 'group3', - columns: [ - // row span 2 - { field: 'Address', rowStart: 1, colStart: 1, rowEnd: 3 }, - { field: 'PostalCode', rowStart: 3, colStart: 1 } - ] - }]; + group: 'group1', + // row span 3 + columns: [ + { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 4 } + ] + }, { + group: 'group2', + columns: [ + // col span 2 + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'Phone', rowStart: 2, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 2 }, + // col span 2 + { field: 'ContactTitle', rowStart: 3, colStart: 1, colEnd: 3 } + ] + }, { + group: 'group3', + columns: [ + // row span 2 + { field: 'Address', rowStart: 1, colStart: 1, rowEnd: 3 }, + { field: 'PostalCode', rowStart: 3, colStart: 1 } + ] + }]; fix.detectChanges(); const grid = fix.componentInstance.grid; // hide second group @@ -817,41 +818,41 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { describe('GroupBy Integration', () => { it('should allow navigation through group rows with arrow keys starting from group row.', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - // row span 3 - columns: [ - { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 4 } - ] - }, { - group: 'group2', - columns: [ - // col span 2 - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'Phone', rowStart: 2, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 2 }, - // col span 2 - { field: 'ContactTitle', rowStart: 3, colStart: 1, colEnd: 3 } - ] - }, { - group: 'group3', - columns: [ - // row span 2 - { field: 'Address', rowStart: 1, colStart: 1, rowEnd: 3 }, - { field: 'PostalCode', rowStart: 3, colStart: 1 } - ] - }]; - fix.detectChanges(); - // group by city - const grid = fix.componentInstance.grid; - grid.groupBy({ - fieldName: 'City', - dir: SortingDirection.Asc, - ignoreCase: true, - strategy: DefaultSortingStrategy.instance() - }); - fix.detectChanges(); - - let groupRow = (grid.gridAPI.get_row_by_index(0) as any) as IgxGridGroupByRowComponent; + group: 'group1', + // row span 3 + columns: [ + { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 4 } + ] + }, { + group: 'group2', + columns: [ + // col span 2 + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'Phone', rowStart: 2, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 2 }, + // col span 2 + { field: 'ContactTitle', rowStart: 3, colStart: 1, colEnd: 3 } + ] + }, { + group: 'group3', + columns: [ + // row span 2 + { field: 'Address', rowStart: 1, colStart: 1, rowEnd: 3 }, + { field: 'PostalCode', rowStart: 3, colStart: 1 } + ] + }]; + fix.detectChanges(); + // group by city + const grid = fix.componentInstance.grid; + grid.groupBy({ + fieldName: 'City', + dir: SortingDirection.Asc, + ignoreCase: true, + strategy: DefaultSortingStrategy.instance() + }); + fix.detectChanges(); + + let groupRow = (grid.gridAPI.get_row_by_index(0) as any) as IgxGridGroupByRowComponent; UIInteractions.simulateClickAndSelectEvent(groupRow); fix.detectChanges(); @@ -889,29 +890,29 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should allow navigation through group rows with arrow keys starting from middle of grid row', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - // row span 3 - columns: [ - { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 4 } - ] - }, { - group: 'group2', - columns: [ - // col span 2 - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'Phone', rowStart: 2, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 2 }, - // col span 2 - { field: 'ContactTitle', rowStart: 3, colStart: 1, colEnd: 3 } - ] - }, { - group: 'group3', - columns: [ - // row span 2 - { field: 'Address', rowStart: 1, colStart: 1, rowEnd: 3 }, - { field: 'PostalCode', rowStart: 3, colStart: 1 } - ] - }]; + group: 'group1', + // row span 3 + columns: [ + { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 4 } + ] + }, { + group: 'group2', + columns: [ + // col span 2 + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'Phone', rowStart: 2, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 2 }, + // col span 2 + { field: 'ContactTitle', rowStart: 3, colStart: 1, colEnd: 3 } + ] + }, { + group: 'group3', + columns: [ + // row span 2 + { field: 'Address', rowStart: 1, colStart: 1, rowEnd: 3 }, + { field: 'PostalCode', rowStart: 3, colStart: 1 } + ] + }]; fix.detectChanges(); // group by city @@ -972,29 +973,29 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { describe('Column Moving Integration', () => { it('tab navigation should follow correct sequence if a column is moved.', fakeAsync(() => { fix.componentInstance.colGroups = [{ - group: 'group1', - // row span 3 - columns: [ - { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 4 } - ] - }, { - group: 'group2', - columns: [ - // col span 2 - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'Phone', rowStart: 2, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 2 }, - // col span 2 - { field: 'ContactTitle', rowStart: 3, colStart: 1, colEnd: 3 } - ] - }, { - group: 'group3', - columns: [ - // row span 2 - { field: 'Address', rowStart: 1, colStart: 1, rowEnd: 3 }, - { field: 'PostalCode', rowStart: 3, colStart: 1 } - ] - }]; + group: 'group1', + // row span 3 + columns: [ + { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 4 } + ] + }, { + group: 'group2', + columns: [ + // col span 2 + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'Phone', rowStart: 2, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 2 }, + // col span 2 + { field: 'ContactTitle', rowStart: 3, colStart: 1, colEnd: 3 } + ] + }, { + group: 'group3', + columns: [ + // row span 2 + { field: 'Address', rowStart: 1, colStart: 1, rowEnd: 3 }, + { field: 'PostalCode', rowStart: 3, colStart: 1 } + ] + }]; fix.detectChanges(); const grid = fix.componentInstance.grid; // move second group @@ -1018,29 +1019,29 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { describe('Pinning integration', () => { it('tab navigation should follow correct sequence if a column is pinned runtime.', () => { fix.componentInstance.colGroups = [{ - group: 'group1', - // row span 3 - columns: [ - { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 4 } - ] - }, { - group: 'group2', - columns: [ - // col span 2 - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'Phone', rowStart: 2, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 2 }, - // col span 2 - { field: 'ContactTitle', rowStart: 3, colStart: 1, colEnd: 3 } - ] - }, { - group: 'group3', - columns: [ - // row span 2 - { field: 'Address', rowStart: 1, colStart: 1, rowEnd: 3 }, - { field: 'PostalCode', rowStart: 3, colStart: 1 } - ] - }]; + group: 'group1', + // row span 3 + columns: [ + { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 4 } + ] + }, { + group: 'group2', + columns: [ + // col span 2 + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'Phone', rowStart: 2, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 2 }, + // col span 2 + { field: 'ContactTitle', rowStart: 3, colStart: 1, colEnd: 3 } + ] + }, { + group: 'group3', + columns: [ + // row span 2 + { field: 'Address', rowStart: 1, colStart: 1, rowEnd: 3 }, + { field: 'PostalCode', rowStart: 3, colStart: 1 } + ] + }]; fix.detectChanges(); const grid = fix.componentInstance.grid; // hide second group @@ -1423,13 +1424,13 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { describe('General', () => { it('should allow navigating down with scrolling', async () => { fix.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'Phone', rowStart: 1, colStart: 1 }, - { field: 'City', rowStart: 1, colStart: 2 }, - { field: 'ContactName', rowStart: 2, colStart: 1, colEnd: 3 } - ] - }]; + group: 'group1', + columns: [ + { field: 'Phone', rowStart: 1, colStart: 1 }, + { field: 'City', rowStart: 1, colStart: 2 }, + { field: 'ContactName', rowStart: 2, colStart: 1, colEnd: 3 } + ] + }]; await wait(DEBOUNCE_TIME); fix.detectChanges(); const rows = fix.debugElement.queryAll(By.css(ROW_CSS_CLASS)); @@ -1454,14 +1455,14 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should navigate correctly by pressing Ctrl + ArrowUp/ArrowDown key', async () => { fix.componentInstance.colGroups = [{ - group: 'group1', - pinned: true, - columns: [ - { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'ContactName', rowStart: 2, colStart: 1 }, - { field: 'ContactTitle', rowStart: 2, colStart: 2 } - ] - }]; + group: 'group1', + pinned: true, + columns: [ + { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'ContactName', rowStart: 2, colStart: 1 }, + { field: 'ContactTitle', rowStart: 2, colStart: 2 } + ] + }]; await wait(DEBOUNCE_TIME); fix.detectChanges(); setupGridScrollDetection(fix, fix.componentInstance.grid); @@ -1493,34 +1494,34 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should navigate to the last cell from the layout by pressing Home/End or Ctrl + ArrowLeft/ArrowRight key', async () => { fix.componentInstance.colGroups = [{ - group: 'group1', - hidden: true, - columns: [ - { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 3 } - ] - }, { - group: 'group2', - columns: [ - { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'ContactName', rowStart: 2, colStart: 1 }, - { field: 'ContactTitle', rowStart: 2, colStart: 2 }, - { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } - ] - }, { - group: 'group3', - columns: [ - { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, - { field: 'Region', rowStart: 3, colStart: 1 }, - { field: 'PostalCode', rowStart: 3, colStart: 2 } - ] - }, { - group: 'group4', - columns: [ - { field: 'Country', rowStart: 1, colStart: 1 }, - { field: 'Phone', rowStart: 1, colStart: 2 }, - { field: 'Fax', rowStart: 2, colStart: 1, colEnd: 3, rowEnd: 4 } - ] - }]; + group: 'group1', + hidden: true, + columns: [ + { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 3 } + ] + }, { + group: 'group2', + columns: [ + { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'ContactName', rowStart: 2, colStart: 1 }, + { field: 'ContactTitle', rowStart: 2, colStart: 2 }, + { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } + ] + }, { + group: 'group3', + columns: [ + { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, + { field: 'Region', rowStart: 3, colStart: 1 }, + { field: 'PostalCode', rowStart: 3, colStart: 2 } + ] + }, { + group: 'group4', + columns: [ + { field: 'Country', rowStart: 1, colStart: 1 }, + { field: 'Phone', rowStart: 1, colStart: 2 }, + { field: 'Fax', rowStart: 2, colStart: 1, colEnd: 3, rowEnd: 4 } + ] + }]; await wait(DEBOUNCE_TIME); fix.detectChanges(); const firstCell = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS))[0]; @@ -1559,34 +1560,34 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should navigate to the last cell from the first/last layout by pressing Ctrl + Home/End key', async () => { fix.componentInstance.colGroups = [{ - group: 'group1', - hidden: true, - columns: [ - { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 3 } - ] - }, { - group: 'group2', - columns: [ - { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'ContactName', rowStart: 2, colStart: 1 }, - { field: 'ContactTitle', rowStart: 2, colStart: 2 }, - { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } - ] - }, { - group: 'group3', - columns: [ - { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, - { field: 'Region', rowStart: 3, colStart: 1 }, - { field: 'PostalCode', rowStart: 3, colStart: 2 } - ] - }, { - group: 'group4', - columns: [ - { field: 'Country', rowStart: 1, colStart: 1 }, - { field: 'Phone', rowStart: 1, colStart: 2 }, - { field: 'Fax', rowStart: 2, colStart: 1, colEnd: 3, rowEnd: 4 } - ] - }]; + group: 'group1', + hidden: true, + columns: [ + { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 3 } + ] + }, { + group: 'group2', + columns: [ + { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'ContactName', rowStart: 2, colStart: 1 }, + { field: 'ContactTitle', rowStart: 2, colStart: 2 }, + { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } + ] + }, { + group: 'group3', + columns: [ + { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, + { field: 'Region', rowStart: 3, colStart: 1 }, + { field: 'PostalCode', rowStart: 3, colStart: 2 } + ] + }, { + group: 'group4', + columns: [ + { field: 'Country', rowStart: 1, colStart: 1 }, + { field: 'Phone', rowStart: 1, colStart: 2 }, + { field: 'Fax', rowStart: 2, colStart: 1, colEnd: 3, rowEnd: 4 } + ] + }]; await wait(DEBOUNCE_TIME); fix.detectChanges(); @@ -1621,34 +1622,34 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it(`should navigate to the last cell from the layout by pressing Home/End or Ctrl + ArrowLeft/ArrowRight key and keep same rowStart from the first selection when last cell spans more rows`, async () => { fix.componentInstance.colGroups = [{ - group: 'group1', - hidden: true, - columns: [ - { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 3 } - ] - }, { - group: 'group2', - columns: [ - { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'ContactName', rowStart: 2, colStart: 1 }, - { field: 'ContactTitle', rowStart: 2, colStart: 2 }, - { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } - ] - }, { - group: 'group3', - columns: [ - { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, - { field: 'Region', rowStart: 3, colStart: 1 }, - { field: 'PostalCode', rowStart: 3, colStart: 2 } - ] - }, { - group: 'group4', - columns: [ - { field: 'Country', rowStart: 1, colStart: 1 }, - { field: 'Phone', rowStart: 1, colStart: 2 }, - { field: 'Fax', rowStart: 2, colStart: 1, colEnd: 3, rowEnd: 4 } - ] - }]; + group: 'group1', + hidden: true, + columns: [ + { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 3 } + ] + }, { + group: 'group2', + columns: [ + { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'ContactName', rowStart: 2, colStart: 1 }, + { field: 'ContactTitle', rowStart: 2, colStart: 2 }, + { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } + ] + }, { + group: 'group3', + columns: [ + { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, + { field: 'Region', rowStart: 3, colStart: 1 }, + { field: 'PostalCode', rowStart: 3, colStart: 2 } + ] + }, { + group: 'group4', + columns: [ + { field: 'Country', rowStart: 1, colStart: 1 }, + { field: 'Phone', rowStart: 1, colStart: 2 }, + { field: 'Fax', rowStart: 2, colStart: 1, colEnd: 3, rowEnd: 4 } + ] + }]; await wait(DEBOUNCE_TIME); fix.detectChanges(); @@ -1690,34 +1691,34 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it(`should navigate to the last cell from the layout by pressing Home/End and Ctrl key and keep same rowStart from the first selection when last cell spans more rows`, async () => { fix.componentInstance.colGroups = [{ - group: 'group1', - hidden: true, - columns: [ - { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 3 } - ] - }, { - group: 'group2', - columns: [ - { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'ContactName', rowStart: 2, colStart: 1 }, - { field: 'ContactTitle', rowStart: 2, colStart: 2 }, - { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } - ] - }, { - group: 'group3', - columns: [ - { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, - { field: 'Region', rowStart: 3, colStart: 1 }, - { field: 'PostalCode', rowStart: 3, colStart: 2 } - ] - }, { - group: 'group4', - columns: [ - { field: 'Country', rowStart: 1, colStart: 1 }, - { field: 'Phone', rowStart: 1, colStart: 2 }, - { field: 'Fax', rowStart: 2, colStart: 1, colEnd: 3, rowEnd: 4 } - ] - }]; + group: 'group1', + hidden: true, + columns: [ + { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 3 } + ] + }, { + group: 'group2', + columns: [ + { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'ContactName', rowStart: 2, colStart: 1 }, + { field: 'ContactTitle', rowStart: 2, colStart: 2 }, + { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } + ] + }, { + group: 'group3', + columns: [ + { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, + { field: 'Region', rowStart: 3, colStart: 1 }, + { field: 'PostalCode', rowStart: 3, colStart: 2 } + ] + }, { + group: 'group4', + columns: [ + { field: 'Country', rowStart: 1, colStart: 1 }, + { field: 'Phone', rowStart: 1, colStart: 2 }, + { field: 'Fax', rowStart: 2, colStart: 1, colEnd: 3, rowEnd: 4 } + ] + }]; await wait(DEBOUNCE_TIME); fix.detectChanges(); @@ -1751,34 +1752,34 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it(`should navigate to the last cell from the layout by pressing Ctrl + Arrow Right key and then Arrow Down + Up to same cell`, async () => { fix.componentInstance.colGroups = [{ - group: 'group1', - hidden: true, - columns: [ - { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 3 } - ] - }, { - group: 'group2', - columns: [ - { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'ContactName', rowStart: 2, colStart: 1 }, - { field: 'ContactTitle', rowStart: 2, colStart: 2 }, - { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } - ] - }, { - group: 'group3', - columns: [ - { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, - { field: 'Region', rowStart: 3, colStart: 1 }, - { field: 'PostalCode', rowStart: 3, colStart: 2 } - ] - }, { - group: 'group4', - columns: [ - { field: 'Country', rowStart: 1, colStart: 1 }, - { field: 'Phone', rowStart: 1, colStart: 2 }, - { field: 'Fax', rowStart: 2, colStart: 1, colEnd: 3, rowEnd: 4 } - ] - }]; + group: 'group1', + hidden: true, + columns: [ + { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 3 } + ] + }, { + group: 'group2', + columns: [ + { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'ContactName', rowStart: 2, colStart: 1 }, + { field: 'ContactTitle', rowStart: 2, colStart: 2 }, + { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } + ] + }, { + group: 'group3', + columns: [ + { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, + { field: 'Region', rowStart: 3, colStart: 1 }, + { field: 'PostalCode', rowStart: 3, colStart: 2 } + ] + }, { + group: 'group4', + columns: [ + { field: 'Country', rowStart: 1, colStart: 1 }, + { field: 'Phone', rowStart: 1, colStart: 2 }, + { field: 'Fax', rowStart: 2, colStart: 1, colEnd: 3, rowEnd: 4 } + ] + }]; await wait(DEBOUNCE_TIME); fix.detectChanges(); setupGridScrollDetection(fix, fix.componentInstance.grid); @@ -1814,34 +1815,34 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it(`should navigate to the last cell from the layout by pressing Ctrl + Arrow Right key and then Arrow Up + Down to same cell`, async () => { fix.componentInstance.colGroups = [{ - group: 'group1', - hidden: true, - columns: [ - { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 3 } - ] - }, { - group: 'group2', - columns: [ - { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'ContactName', rowStart: 2, colStart: 1 }, - { field: 'ContactTitle', rowStart: 2, colStart: 2 }, - { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } - ] - }, { - group: 'group3', - columns: [ - { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, - { field: 'Region', rowStart: 3, colStart: 1 }, - { field: 'PostalCode', rowStart: 3, colStart: 2 } - ] - }, { - group: 'group4', - columns: [ - { field: 'Country', rowStart: 1, colStart: 1 }, - { field: 'Phone', rowStart: 1, colStart: 2 }, - { field: 'Fax', rowStart: 2, colStart: 1, colEnd: 3, rowEnd: 4 } - ] - }]; + group: 'group1', + hidden: true, + columns: [ + { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 3 } + ] + }, { + group: 'group2', + columns: [ + { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'ContactName', rowStart: 2, colStart: 1 }, + { field: 'ContactTitle', rowStart: 2, colStart: 2 }, + { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } + ] + }, { + group: 'group3', + columns: [ + { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, + { field: 'Region', rowStart: 3, colStart: 1 }, + { field: 'PostalCode', rowStart: 3, colStart: 2 } + ] + }, { + group: 'group4', + columns: [ + { field: 'Country', rowStart: 1, colStart: 1 }, + { field: 'Phone', rowStart: 1, colStart: 2 }, + { field: 'Fax', rowStart: 2, colStart: 1, colEnd: 3, rowEnd: 4 } + ] + }]; await wait(DEBOUNCE_TIME); fix.detectChanges(); setupGridScrollDetection(fix, fix.componentInstance.grid); @@ -1902,7 +1903,8 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { columns: [ { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 4 } ] - }]; + } + ]; await wait(DEBOUNCE_TIME); fix.detectChanges(); @@ -1987,18 +1989,18 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should scroll active cell fully in view when navigating with arrow keys and column is partially visible.', async () => { fix.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - // col span 2 - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 5 }, - { field: 'Phone', rowStart: 2, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 2 }, - { field: 'Address', rowStart: 2, colStart: 3 }, - { field: 'Country', rowStart: 2, colStart: 4 }, - // col span 2 - { field: 'ContactTitle', rowStart: 3, colStart: 1, colEnd: 5 } - ] - }]; + group: 'group1', + columns: [ + // col span 2 + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 5 }, + { field: 'Phone', rowStart: 2, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 2 }, + { field: 'Address', rowStart: 2, colStart: 3 }, + { field: 'Country', rowStart: 2, colStart: 4 }, + // col span 2 + { field: 'ContactTitle', rowStart: 3, colStart: 1, colEnd: 5 } + ] + }]; const grid = fix.componentInstance.grid; grid.columnWidth = '300px'; grid.width = '300px'; @@ -2033,29 +2035,29 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it(`should navigate to the last cell from the layout by pressing Ctrl + ArrowLeft/ArrowRight key in grid with horizontal virtualization`, async () => { fix.componentInstance.colGroups = [{ - group: 'group1', - // row span 3 - columns: [ - { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 4 } - ] - }, { - group: 'group2', - columns: [ - // col span 2 - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'Phone', rowStart: 2, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 2 }, - // col span 2 - { field: 'ContactTitle', rowStart: 3, colStart: 1, colEnd: 3 } - ] - }, { - group: 'group3', - columns: [ - // row span 2 - { field: 'Address', rowStart: 1, colStart: 1, rowEnd: 3 }, - { field: 'PostalCode', rowStart: 3, colStart: 1 } - ] - }]; + group: 'group1', + // row span 3 + columns: [ + { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 4 } + ] + }, { + group: 'group2', + columns: [ + // col span 2 + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'Phone', rowStart: 2, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 2 }, + // col span 2 + { field: 'ContactTitle', rowStart: 3, colStart: 1, colEnd: 3 } + ] + }, { + group: 'group3', + columns: [ + // row span 2 + { field: 'Address', rowStart: 1, colStart: 1, rowEnd: 3 }, + { field: 'PostalCode', rowStart: 3, colStart: 1 } + ] + }]; const grid = fix.componentInstance.grid; grid.columnWidth = '300px'; grid.width = '400px'; @@ -2095,22 +2097,22 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { describe('Pinning', () => { it('should navigate from pinned to unpinned area and backwards', async () => { fix.componentInstance.colGroups = [{ - group: 'group1', - pinned: true, - columns: [ - { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'ContactName', rowStart: 2, colStart: 1 }, - { field: 'ContactTitle', rowStart: 2, colStart: 2 }, - { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } - ] - }, { - group: 'group2', - columns: [ - { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, - { field: 'Region', rowStart: 3, colStart: 1 }, - { field: 'PostalCode', rowStart: 3, colStart: 2 } - ] - }]; + group: 'group1', + pinned: true, + columns: [ + { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'ContactName', rowStart: 2, colStart: 1 }, + { field: 'ContactTitle', rowStart: 2, colStart: 2 }, + { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } + ] + }, { + group: 'group2', + columns: [ + { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, + { field: 'Region', rowStart: 3, colStart: 1 }, + { field: 'PostalCode', rowStart: 3, colStart: 2 } + ] + }]; await wait(DEBOUNCE_TIME); fix.detectChanges(); const firstCell = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS))[0]; @@ -2136,29 +2138,29 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('when navigating from pinned to unpinned area cell should be fully scrolled in view.', async () => { //pending('This should be tested in the e2e test'); fix.componentInstance.colGroups = [{ - group: 'group1', - // row span 3 - columns: [ - { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 4 } - ] - }, { - group: 'group2', - columns: [ - // col span 2 - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'Phone', rowStart: 2, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 2 }, - // col span 2 - { field: 'ContactTitle', rowStart: 3, colStart: 1, colEnd: 3 } - ] - }, { - group: 'group3', - columns: [ - // row span 2 - { field: 'Address', rowStart: 1, colStart: 1, rowEnd: 3 }, - { field: 'PostalCode', rowStart: 3, colStart: 1 } - ] - }]; + group: 'group1', + // row span 3 + columns: [ + { field: 'ID', rowStart: 1, colStart: 1, rowEnd: 4 } + ] + }, { + group: 'group2', + columns: [ + // col span 2 + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'Phone', rowStart: 2, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 2 }, + // col span 2 + { field: 'ContactTitle', rowStart: 3, colStart: 1, colEnd: 3 } + ] + }, { + group: 'group3', + columns: [ + // row span 2 + { field: 'Address', rowStart: 1, colStart: 1, rowEnd: 3 }, + { field: 'PostalCode', rowStart: 3, colStart: 1 } + ] + }]; fix.detectChanges(); const grid = fix.componentInstance.grid; @@ -2221,22 +2223,22 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should navigate to unpinned area when the column layout is bigger than the display container', async () => { fix.componentInstance.colGroups = [{ - group: 'group1', - pinned: true, - columns: [ - { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3, width: '300px' }, - { field: 'ContactName', rowStart: 2, colStart: 1 }, - { field: 'ContactTitle', rowStart: 2, colStart: 2 }, - { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } - ] - }, { - group: 'group2', - columns: [ - { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3, width: '400px' }, - { field: 'Region', rowStart: 3, colStart: 1 }, - { field: 'PostalCode', rowStart: 3, colStart: 2 } - ] - }]; + group: 'group1', + pinned: true, + columns: [ + { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3, width: '300px' }, + { field: 'ContactName', rowStart: 2, colStart: 1 }, + { field: 'ContactTitle', rowStart: 2, colStart: 2 }, + { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } + ] + }, { + group: 'group2', + columns: [ + { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3, width: '400px' }, + { field: 'Region', rowStart: 3, colStart: 1 }, + { field: 'PostalCode', rowStart: 3, colStart: 2 } + ] + }]; fix.componentInstance.grid.width = '600px'; await wait(DEBOUNCE_TIME); fix.detectChanges(); @@ -2262,22 +2264,22 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should navigate from pinned to unpinned area and backwards using Home/End', async () => { fix.componentInstance.colGroups = [{ - group: 'group1', - pinned: true, - columns: [ - { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'ContactName', rowStart: 2, colStart: 1 }, - { field: 'ContactTitle', rowStart: 2, colStart: 2 }, - { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } - ] - }, { - group: 'group2', - columns: [ - { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, - { field: 'Region', rowStart: 3, colStart: 1 }, - { field: 'PostalCode', rowStart: 3, colStart: 2 } - ] - }]; + group: 'group1', + pinned: true, + columns: [ + { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'ContactName', rowStart: 2, colStart: 1 }, + { field: 'ContactTitle', rowStart: 2, colStart: 2 }, + { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } + ] + }, { + group: 'group2', + columns: [ + { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, + { field: 'Region', rowStart: 3, colStart: 1 }, + { field: 'PostalCode', rowStart: 3, colStart: 2 } + ] + }]; await wait(DEBOUNCE_TIME); fix.detectChanges(); const secondCell = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS))[1]; @@ -2301,22 +2303,22 @@ describe('IgxGrid Multi Row Layout - Keyboard navigation #grid', () => { it('should navigate from pinned to unpinned area and backwards using Ctrl+Left/Right', async () => { fix.componentInstance.colGroups = [{ - group: 'group1', - pinned: true, - columns: [ - { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'ContactName', rowStart: 2, colStart: 1 }, - { field: 'ContactTitle', rowStart: 2, colStart: 2 }, - { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } - ] - }, { - group: 'group2', - columns: [ - { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, - { field: 'Region', rowStart: 3, colStart: 1 }, - { field: 'PostalCode', rowStart: 3, colStart: 2 } - ] - }]; + group: 'group1', + pinned: true, + columns: [ + { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'ContactName', rowStart: 2, colStart: 1 }, + { field: 'ContactTitle', rowStart: 2, colStart: 2 }, + { field: 'Address', rowStart: 3, colStart: 1, colEnd: 3 } + ] + }, { + group: 'group2', + columns: [ + { field: 'City', rowStart: 1, colStart: 1, colEnd: 3, rowEnd: 3 }, + { field: 'Region', rowStart: 3, colStart: 1 }, + { field: 'PostalCode', rowStart: 3, colStart: 2 } + ] + }]; fix.detectChanges(); const secondCell = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS))[1]; diff --git a/projects/igniteui-angular/grids/grid/src/grid-row-editing.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-row-editing.spec.ts index ba77b0bbd7d..a8c83833b7a 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-row-editing.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-row-editing.spec.ts @@ -8,20 +8,11 @@ import { IgxColumnComponent } from 'igniteui-angular/grids/core'; import { UIInteractions, wait } from '../../../test-utils/ui-interactions.spec'; import { clearGridSubs, setElementSize, setupGridScrollDetection } from '../../../test-utils/helper-utils.spec'; import { GridFunctions, GridSummaryFunctions } from '../../../test-utils/grid-functions.spec'; -import { - IgxGridRowEditingComponent, - IgxGridRowEditingTransactionComponent, - IgxGridWithEditingAndFeaturesComponent, - IgxGridRowEditingWithoutEditableColumnsComponent, - IgxGridCustomOverlayComponent, - IgxGridEmptyRowEditTemplateComponent, - VirtualGridComponent, - ObjectCloneStrategy, - IgxGridCustomRowEditTemplateComponent -} from '../../../test-utils/grid-samples.spec'; +import { IgxGridRowEditingComponent, IgxGridRowEditingTransactionComponent, IgxGridWithEditingAndFeaturesComponent, IgxGridRowEditingWithoutEditableColumnsComponent, IgxGridCustomOverlayComponent, IgxGridEmptyRowEditTemplateComponent, VirtualGridComponent, ObjectCloneStrategy, IgxGridCustomRowEditTemplateComponent } from '../../../test-utils/grid-samples.spec'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { DefaultDataCloneStrategy, DefaultSortingStrategy, IgxNumberFilteringOperand, IgxStringFilteringOperand, ɵSize, SortingDirection, Transaction, TransactionType } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; const CELL_CLASS = '.igx-grid__td'; const ROW_EDITED_CLASS = 'igx-grid__tr--edited'; @@ -67,12 +58,11 @@ describe('IgxGrid - Row Editing #grid', () => { }); it('Should throw a warning when [rowEditable] is set on a grid w/o [primaryKey]', () => { - jasmine.getEnv().allowRespy(true); grid.primaryKey = null; grid.rowEditable = false; fix.detectChanges(); - spyOn(console, 'warn'); + vi.spyOn(console, 'warn'); grid.rowEditable = true; fix.detectChanges(); @@ -84,7 +74,6 @@ describe('IgxGrid - Row Editing #grid', () => { fix.detectChanges(); expect(console.warn).toHaveBeenCalledWith('The grid must have a `primaryKey` specified when using `rowEditable`!'); expect(console.warn).toHaveBeenCalledTimes(1); - jasmine.getEnv().allowRespy(false); }); it('Should be able to enter edit mode on dblclick, enter and f2', () => { @@ -142,14 +131,14 @@ describe('IgxGrid - Row Editing #grid', () => { const newCellValue = 'Aaaaa'; const updatedRowData = Object.assign({}, row.data, { ProductName: newCellValue }); - spyOn(grid.cellEditEnter, 'emit').and.callThrough(); - spyOn(grid.cellEdit, 'emit').and.callThrough(); - spyOn(grid.cellEditDone, 'emit').and.callThrough(); - spyOn(grid.cellEditExit, 'emit').and.callThrough(); - spyOn(grid.rowEditEnter, 'emit').and.callThrough(); - spyOn(grid.rowEdit, 'emit').and.callThrough(); - spyOn(grid.rowEditExit, 'emit').and.callThrough(); - spyOn(grid.rowEditDone, 'emit').and.callThrough(); + vi.spyOn(grid.cellEditEnter, 'emit'); + vi.spyOn(grid.cellEdit, 'emit'); + vi.spyOn(grid.cellEditDone, 'emit'); + vi.spyOn(grid.cellEditExit, 'emit'); + vi.spyOn(grid.rowEditEnter, 'emit'); + vi.spyOn(grid.rowEdit, 'emit'); + vi.spyOn(grid.rowEditExit, 'emit'); + vi.spyOn(grid.rowEditDone, 'emit'); let cellInput = null; @@ -167,7 +156,7 @@ describe('IgxGrid - Row Editing #grid', () => { column: cell.column, owner: grid, valid: true, - event: jasmine.anything() as any + event: expect.anything() as any }; let rowEditArgs: IGridEditEventArgs = { rowID: row.key, @@ -179,7 +168,7 @@ describe('IgxGrid - Row Editing #grid', () => { valid: true, owner: grid, isAddRow: row.addRowUI, - event: jasmine.anything() as any + event: expect.anything() as any }; expect(grid.cellEditEnter.emit).toHaveBeenCalledWith(cellEditArgs); expect(grid.rowEditEnter.emit).toHaveBeenCalledWith(rowEditArgs); @@ -200,7 +189,7 @@ describe('IgxGrid - Row Editing #grid', () => { newValue: cell.value, column: cell.column, owner: grid, - event: jasmine.anything() as any + event: expect.anything() as any }; const rowEditExitArgs: IGridEditDoneEventArgs = { @@ -212,7 +201,7 @@ describe('IgxGrid - Row Editing #grid', () => { oldValue: row.data, owner: grid, isAddRow: row.addRowUI, - event: jasmine.anything() as any, + event: expect.anything() as any, valid: true }; @@ -238,7 +227,7 @@ describe('IgxGrid - Row Editing #grid', () => { valid: true, column: cell.column, owner: grid, - event: jasmine.anything() as any + event: expect.anything() as any }; cellEditArgs.newValue = newCellValue; @@ -254,7 +243,7 @@ describe('IgxGrid - Row Editing #grid', () => { owner: grid, isAddRow: row.addRowUI, valid: true, - event: jasmine.anything() as any + event: expect.anything() as any }; const cellDoneArgs: IGridEditDoneEventArgs = { @@ -268,7 +257,7 @@ describe('IgxGrid - Row Editing #grid', () => { valid: true, column: cell.column, owner: grid, - event: jasmine.anything() as any + event: expect.anything() as any }; const rowDoneArgs: IGridEditDoneEventArgs = { @@ -280,7 +269,7 @@ describe('IgxGrid - Row Editing #grid', () => { newValue: Object.assign({}, row.data, { ProductName: newCellValue }), owner: grid, isAddRow: row.addRowUI, - event: jasmine.anything() as any, + event: expect.anything() as any, valid: true }; UIInteractions.triggerEventHandlerKeyDown('enter', gridContent); @@ -295,8 +284,8 @@ describe('IgxGrid - Row Editing #grid', () => { }); it('Emit rowAdd and rowAdded event with proper arguments', () => { - spyOn(grid.rowAdd, 'emit').and.callThrough(); - spyOn(grid.rowAdded, 'emit').and.callThrough(); + vi.spyOn(grid.rowAdd, 'emit'); + vi.spyOn(grid.rowAdded, 'emit'); // start add row grid.beginAddRowById(null); fix.detectChanges(); @@ -321,21 +310,21 @@ describe('IgxGrid - Row Editing #grid', () => { // check event args const rowAddArgs: IRowDataCancelableEventArgs = { cancel: false, - oldValue: { ProductID: generatedId}, - rowData: { ProductID: generatedId, ProductName: "NewValue"}, - data: { ProductID: generatedId, ProductName: "NewValue"}, + oldValue: { ProductID: generatedId }, + rowData: { ProductID: generatedId, ProductName: "NewValue" }, + data: { ProductID: generatedId, ProductName: "NewValue" }, rowID: generatedId, primaryKey: generatedId, rowKey: generatedId, valid: true, - event: jasmine.anything() as any, + event: expect.anything() as any, owner: grid, isAddRow: true - } + }; const rowAddedArgs: IRowDataEventArgs = { - rowData: { ProductID: generatedId, ProductName: "NewValue"}, - data: { ProductID: generatedId, ProductName: "NewValue"}, + rowData: { ProductID: generatedId, ProductName: "NewValue" }, + data: { ProductID: generatedId, ProductName: "NewValue" }, primaryKey: generatedId, rowKey: generatedId, owner: grid @@ -973,12 +962,12 @@ describe('IgxGrid - Row Editing #grid', () => { fix.detectChanges(); - const keyDonwSpy = spyOn(grid.gridKeydown, 'emit'); + const keyDonwSpy = vi.spyOn(grid.gridKeydown, 'emit'); UIInteractions.simulateDoubleClickAndSelectEvent(targetCell); fix.detectChanges(); - const detectChangesSpy = spyOn(grid.cdr, 'detectChanges').and.callThrough(); + const detectChangesSpy = vi.spyOn(grid.cdr, 'detectChanges'); const cellElem = fix.debugElement.query(By.css(CELL_CLASS)); const input = cellElem.query(By.css('input')); @@ -1012,7 +1001,7 @@ describe('IgxGrid - Row Editing #grid', () => { it(`Should call correct methods on clicking DONE and CANCEL buttons in row edit overlay`, () => { const mockEvent = new MouseEvent('click'); - spyOn(grid.gridAPI.crudService, 'endEdit'); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); // put cell in edit mode cell.editMode = true; @@ -1037,7 +1026,7 @@ describe('IgxGrid - Row Editing #grid', () => { it(`Should exit row editing AND do not commit when press Escape key on Done and Cancel buttons`, () => { const mockEvent = new KeyboardEvent('keydown', { key: 'escape' }); - spyOn(grid.gridAPI.crudService, 'endEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); // put cell in edit mode cell.editMode = true; @@ -1069,7 +1058,7 @@ describe('IgxGrid - Row Editing #grid', () => { }); it(`Should exit row editing AND COMMIT on add row`, () => { - spyOn(grid.gridAPI.crudService, 'endEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); // put cell in edit mode cell.editMode = true; @@ -1081,7 +1070,7 @@ describe('IgxGrid - Row Editing #grid', () => { }); it(`Should exit row editing AND COMMIT on delete row`, () => { - spyOn(grid.gridAPI.crudService, 'endEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); // put cell in edit mode cell.editMode = true; @@ -1095,8 +1084,8 @@ describe('IgxGrid - Row Editing #grid', () => { }); it(`Should exit row editing AND DISCARD on filter`, () => { - spyOn(grid.gridAPI.crudService, 'exitCellEdit').and.callThrough(); - spyOn(grid.gridAPI.crudService, 'endEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'exitCellEdit'); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); // put cell in edit mode // const cell = grid.getCellByColumn(0, 'ProductName'); @@ -1113,8 +1102,8 @@ describe('IgxGrid - Row Editing #grid', () => { }); it(`Should exit row editing AND DISCARD on sort`, () => { - spyOn(grid.gridAPI.crudService, 'endEdit').and.callThrough(); - spyOn(grid.crudService, 'exitCellEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); + vi.spyOn(grid.crudService, 'exitCellEdit'); // put cell in edit mode cell.editMode = true; @@ -1158,7 +1147,7 @@ describe('IgxGrid - Row Editing #grid', () => { }); it(`Should NOT exit row editing on click on non-editable cell in same row`, () => { - spyOn(grid.gridAPI.crudService, 'endEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); // put cell in edit mode cell.editMode = true; @@ -1181,7 +1170,7 @@ describe('IgxGrid - Row Editing #grid', () => { }); it(`Should exit row editing AND COMMIT on click on non-editable cell in other row`, () => { - spyOn(grid.gridAPI.crudService, 'endEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); // put cell in edit mode cell.editMode = true; @@ -1195,14 +1184,14 @@ describe('IgxGrid - Row Editing #grid', () => { fix.detectChanges(); expect(grid.gridAPI.crudService.endEdit).toHaveBeenCalled(); - expect(grid.gridAPI.crudService.endEdit).toHaveBeenCalledWith(true, (jasmine.anything() as any)); + expect(grid.gridAPI.crudService.endEdit).toHaveBeenCalledWith(true, (expect.anything() as any)); overlayContent = GridFunctions.getRowEditingOverlay(fix); expect(overlayContent).toBeFalsy(); expect(cell.editMode).toBeFalsy(); }); it(`Should exit row editing AND COMMIT on click on editable cell in other row`, () => { - spyOn(grid.gridAPI.crudService, 'endEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); // put cell in edit mode cell.editMode = true; @@ -1219,7 +1208,7 @@ describe('IgxGrid - Row Editing #grid', () => { overlayContent = GridFunctions.getRowEditingOverlay(fix); expect(overlayContent).toBeTruthy(); expect(grid.gridAPI.crudService.endEdit).toHaveBeenCalled(); - expect(grid.gridAPI.crudService.endEdit).toHaveBeenCalledWith(true, jasmine.anything() as any); + expect(grid.gridAPI.crudService.endEdit).toHaveBeenCalledWith(true, expect.anything() as any); expect(cell.editMode).toBeFalsy(); expect(otherEditableCell.editMode).toBeTruthy(); }); @@ -1229,7 +1218,7 @@ describe('IgxGrid - Row Editing #grid', () => { UIInteractions.simulateDoubleClickAndSelectEvent(targetCell); fix.detectChanges(); - spyOn(grid.gridAPI.crudService, 'exitCellEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'exitCellEdit'); UIInteractions.triggerKeyDownEvtUponElem('escape', grid.tbody.nativeElement, true); fix.detectChanges(); @@ -1240,7 +1229,7 @@ describe('IgxGrid - Row Editing #grid', () => { it(`Should exit edit mode when edited row is being deleted`, () => { const row = grid.gridAPI.get_row_by_index(0); - spyOn(grid.gridAPI.crudService, 'endEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); cell.editMode = true; fix.detectChanges(); expect(grid.rowEditingOverlay.collapsed).toBeFalsy(); @@ -1333,7 +1322,7 @@ describe('IgxGrid - Row Editing #grid', () => { it(`Paging: Should exit edit mode when changing the page size while editing`, () => { fix.componentInstance.paging = true; fix.detectChanges(); - grid.paginator.page + grid.paginator.page; grid.paginator.perPage = 7; fix.detectChanges(); @@ -1362,53 +1351,52 @@ describe('IgxGrid - Row Editing #grid', () => { expect(GridFunctions.getRowEditingBanner(fix).parentElement.attributes['aria-hidden']).toBeTruthy(); }); - it(`Paging: Should exit edit mode when changing the page size resulting in the edited cell going to the next page`, - () => { - fix.componentInstance.paging = true; - fix.detectChanges(); - grid.paginator.perPage = 7; - fix.detectChanges(); + it(`Paging: Should exit edit mode when changing the page size resulting in the edited cell going to the next page`, () => { + fix.componentInstance.paging = true; + fix.detectChanges(); + grid.paginator.perPage = 7; + fix.detectChanges(); - const select = GridFunctions.getGridPageSelectElement(fix); + const select = GridFunctions.getGridPageSelectElement(fix); - cell.editMode = true; + cell.editMode = true; - grid.gridAPI.crudService.cell.editValue = 'IG'; - // cell.update('IG'); - // Do not exit edit mode - fix.detectChanges(); + grid.gridAPI.crudService.cell.editValue = 'IG'; + // cell.update('IG'); + // Do not exit edit mode + fix.detectChanges(); - expect(GridFunctions.getRowEditingOverlay(fix)).toBeTruthy(); - expect(GridFunctions.getRowEditingBanner(fix)).toBeTruthy(); + expect(GridFunctions.getRowEditingOverlay(fix)).toBeTruthy(); + expect(GridFunctions.getRowEditingBanner(fix)).toBeTruthy(); - // Change page size - select.click(); - fix.detectChanges(); - const selectList = fix.debugElement.query(By.css('.igx-drop-down__list-scroll')); - selectList.children[0].nativeElement.click(); + // Change page size + select.click(); + fix.detectChanges(); + const selectList = fix.debugElement.query(By.css('.igx-drop-down__list-scroll')); + selectList.children[0].nativeElement.click(); - fix.detectChanges(); + fix.detectChanges(); - // Next page button click - GridFunctions.navigateToNextPage(grid.nativeElement); + // Next page button click + GridFunctions.navigateToNextPage(grid.nativeElement); - fix.detectChanges(); + fix.detectChanges(); - expect(grid.paginator.page).toEqual(1); - cell = grid.getCellByColumn(1, 'ProductName'); - cellElem = grid.gridAPI.get_cell_by_index(1, 'ProductName'); + expect(grid.paginator.page).toEqual(1); + cell = grid.getCellByColumn(1, 'ProductName'); + cellElem = grid.gridAPI.get_cell_by_index(1, 'ProductName'); - fix.detectChanges(); + fix.detectChanges(); - expect(cell.editMode).toEqual(false); + expect(cell.editMode).toEqual(false); - expect(GridFunctions.getRowEditingOverlay(fix)).toBeFalsy(); - // banner is still present in grid template, just not visible - expect(GridFunctions.getRowEditingBanner(fix)).toBeTruthy(); - }); + expect(GridFunctions.getRowEditingOverlay(fix)).toBeFalsy(); + // banner is still present in grid template, just not visible + expect(GridFunctions.getRowEditingBanner(fix)).toBeTruthy(); + }); it(`Filtering: Should exit edit mode on filter applied`, () => { - spyOn(grid.gridAPI.crudService, 'endEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); cell.editMode = true; // flush(); @@ -1463,7 +1451,7 @@ describe('IgxGrid - Row Editing #grid', () => { }); it(`GroupBy: Should exit edit mode when Grouping`, () => { - spyOn(grid.gridAPI.crudService, 'exitCellEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'exitCellEdit'); cell.editMode = true; @@ -1525,8 +1513,7 @@ describe('IgxGrid - Row Editing #grid', () => { fix.detectChanges(); let summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); cell = grid.getCellByColumn(0, 'OrderDate'); cellElem = grid.gridAPI.get_cell_by_index(0, 'OrderDate'); @@ -1545,15 +1532,13 @@ describe('IgxGrid - Row Editing #grid', () => { cellElem = grid.gridAPI.get_cell_by_index(0, 'ProductName'); expect(cell.editMode).toBeTruthy(); summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); GridFunctions.simulateGridContentKeydown(fix, 'enter'); tick(16); fix.detectChanges(); summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['10', 'Jan 1, 1901', 'Dec 25, 2025']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['10', 'Jan 1, 1901', 'Dec 25, 2025']); })); it(`Moving: Should exit edit mode when moving a column`, fakeAsync(() => { @@ -1563,7 +1548,7 @@ describe('IgxGrid - Row Editing #grid', () => { fix.detectChanges(); - spyOn(grid.gridAPI.crudService, 'endEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); // put cell in edit mode cell.editMode = true; @@ -1582,7 +1567,7 @@ describe('IgxGrid - Row Editing #grid', () => { })); it(`Pinning: Should exit edit mode when pinning/unpinning a column`, () => { - spyOn(grid.gridAPI.crudService, 'endEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); // put cell in edit mode cell.editMode = true; @@ -1613,7 +1598,7 @@ describe('IgxGrid - Row Editing #grid', () => { }); it(`Resizing: Should keep edit mode when resizing a column`, fakeAsync(() => { - spyOn(grid.gridAPI.crudService, 'endEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); // put cell in edit mode cell.editMode = true; @@ -1641,7 +1626,7 @@ describe('IgxGrid - Row Editing #grid', () => { fix.detectChanges(); expect(grid.gridAPI.crudService.cell).toBeTruthy(); // check if there is cell in edit mode - spyOn(grid.gridAPI.crudService, 'exitCellEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'exitCellEdit'); cell.column.hidden = true; @@ -1707,14 +1692,14 @@ describe('IgxGrid - Row Editing #grid', () => { })); it(`Should strictly follow the right execution sequence of editing events`, () => { - spyOn(grid.rowEditEnter, 'emit').and.callThrough(); - spyOn(grid.cellEditEnter, 'emit').and.callThrough(); - spyOn(grid.cellEdit, 'emit').and.callThrough(); - spyOn(grid.cellEditDone, 'emit').and.callThrough(); - spyOn(grid.cellEditExit, 'emit').and.callThrough(); - spyOn(grid.rowEdit, 'emit').and.callThrough(); - spyOn(grid.rowEditDone, 'emit').and.callThrough(); - spyOn(grid.rowEditExit, 'emit').and.callThrough(); + vi.spyOn(grid.rowEditEnter, 'emit'); + vi.spyOn(grid.cellEditEnter, 'emit'); + vi.spyOn(grid.cellEdit, 'emit'); + vi.spyOn(grid.cellEditDone, 'emit'); + vi.spyOn(grid.cellEditExit, 'emit'); + vi.spyOn(grid.rowEdit, 'emit'); + vi.spyOn(grid.rowEditDone, 'emit'); + vi.spyOn(grid.rowEditExit, 'emit'); grid.rowEditEnter.pipe(takeUntil($destroyer)).subscribe(() => { expect(grid.rowEditEnter.emit).toHaveBeenCalledTimes(1); @@ -1848,8 +1833,8 @@ describe('IgxGrid - Row Editing #grid', () => { }); it(`Should properly emit 'rowEdit' event - Button Click`, () => { - spyOn(grid.rowEditExit, 'emit').and.callThrough(); - spyOn(grid.rowEdit, 'emit').and.callThrough(); + vi.spyOn(grid.rowEditExit, 'emit'); + vi.spyOn(grid.rowEdit, 'emit'); cell.editMode = true; @@ -1877,12 +1862,12 @@ describe('IgxGrid - Row Editing #grid', () => { owner: grid, isAddRow: false, valid: true, - event: jasmine.anything() as any + event: expect.anything() as any }); }); it(`Should be able to cancel 'rowEdit' event `, () => { - spyOn(grid.rowEdit, 'emit').and.callThrough(); + vi.spyOn(grid.rowEdit, 'emit'); grid.rowEdit.subscribe((e: IGridEditEventArgs) => { e.cancel = true; @@ -1918,7 +1903,7 @@ describe('IgxGrid - Row Editing #grid', () => { cancel: true, owner: grid, isAddRow: false, - event: jasmine.anything() as any, + event: expect.anything() as any, valid: true }); @@ -1945,14 +1930,14 @@ describe('IgxGrid - Row Editing #grid', () => { cancel: true, owner: grid, isAddRow: false, - event: jasmine.anything() as any, + event: expect.anything() as any, valid: true }); }); it(`Should properly emit 'rowEditExit' event - Button Click`, () => { - spyOn(grid.rowEditExit, 'emit').and.callThrough(); - spyOn(grid.rowEdit, 'emit').and.callThrough(); + vi.spyOn(grid.rowEditExit, 'emit'); + vi.spyOn(grid.rowEdit, 'emit'); cell.editMode = true; @@ -1977,14 +1962,14 @@ describe('IgxGrid - Row Editing #grid', () => { oldValue: initialData, owner: grid, isAddRow: false, - event: jasmine.anything() as any, + event: expect.anything() as any, valid: true }); }); it(`Should properly emit 'rowEditEnter' event`, () => { - spyOn(grid.rowEditEnter, 'emit').and.callThrough(); + vi.spyOn(grid.rowEditEnter, 'emit'); grid.tbody.nativeElement.focus(); fix.detectChanges(); @@ -2006,13 +1991,13 @@ describe('IgxGrid - Row Editing #grid', () => { cancel: false, owner: grid, isAddRow: false, - event: jasmine.anything() as any, + event: expect.anything() as any, valid: true }); }); it(`Should be able to cancel 'rowEditEnter' event `, () => { - spyOn(grid.rowEditEnter, 'emit').and.callThrough(); + vi.spyOn(grid.rowEditEnter, 'emit'); grid.rowEditEnter.subscribe((e: IGridEditEventArgs) => { e.cancel = true; @@ -2039,13 +2024,13 @@ describe('IgxGrid - Row Editing #grid', () => { cancel: true, owner: grid, isAddRow: false, - event: jasmine.anything() as any, + event: expect.anything() as any, valid: true }); }); it(`Should properly emit 'rowEditExit' event - Filtering`, () => { - spyOn(grid.rowEditExit, 'emit').and.callThrough(); + vi.spyOn(grid.rowEditExit, 'emit'); const gridContent = GridFunctions.getGridContent(fix); const targetCell = grid.gridAPI.get_cell_by_index(0, 'ProductName') as any; @@ -2081,8 +2066,8 @@ describe('IgxGrid - Row Editing #grid', () => { it(`Should properly emit 'rowEditExit' event - Sorting`, () => { - spyOn(grid.rowEditExit, 'emit').and.callThrough(); - spyOn(grid.rowEdit, 'emit').and.callThrough(); + vi.spyOn(grid.rowEditExit, 'emit'); + vi.spyOn(grid.rowEdit, 'emit'); cell.editMode = true; @@ -2114,8 +2099,8 @@ describe('IgxGrid - Row Editing #grid', () => { it(`Should properly emit 'cellEdit' event `, () => { - spyOn(grid.rowEdit, 'emit').and.callThrough(); - spyOn(grid.cellEdit, 'emit').and.callThrough(); + vi.spyOn(grid.rowEdit, 'emit'); + vi.spyOn(grid.cellEdit, 'emit'); // TODO: cellEdit should emit updated rowData - issue #7304 const cellArgs: IGridEditEventArgs = { cellID: cell.id, @@ -2128,7 +2113,7 @@ describe('IgxGrid - Row Editing #grid', () => { cancel: false, column: cell.column, owner: grid, - event: jasmine.anything() as any, + event: expect.anything() as any, valid: true }; @@ -2167,7 +2152,7 @@ describe('IgxGrid - Row Editing #grid', () => { expect(columns[1].editable).toBeFalsy(); // column.editable not set. Primary column expect(columns[2].editable).toBeTruthy(); // column.editable set to true expect(columns[3].editable).toBeTruthy(); // column.editable not set - expect(columns[4].editable).toBeFalsy(); // column.editable set to false + expect(columns[4].editable).toBeFalsy(); // column.editable set to false grid.rowEditable = false; columns = grid.columnList.toArray(); @@ -2175,7 +2160,7 @@ describe('IgxGrid - Row Editing #grid', () => { expect(columns[1].editable).toBeFalsy(); // column.editable not set. Primary column expect(columns[2].editable).toBeTruthy(); // column.editable set to true expect(columns[3].editable).toBeFalsy(); // column.editable not set - expect(columns[4].editable).toBeFalsy(); // column.editable set to false + expect(columns[4].editable).toBeFalsy(); // column.editable set to false grid.rowEditable = true; columns = grid.columnList.toArray(); @@ -2183,7 +2168,7 @@ describe('IgxGrid - Row Editing #grid', () => { expect(columns[1].editable).toBeFalsy(); // column.editable not set. Primary column expect(columns[2].editable).toBeTruthy(); // column.editable set to true expect(columns[3].editable).toBeTruthy(); // column.editable not set - expect(columns[4].editable).toBeFalsy(); // column.editable set to false + expect(columns[4].editable).toBeFalsy(); // column.editable set to false }); it('should scroll into view not visible cell when in row edit and move from pinned to unpinned column', (async () => { @@ -2242,7 +2227,7 @@ describe('IgxGrid - Row Editing #grid', () => { const grid = fix.componentInstance.grid; const cellElem = grid.gridAPI.get_cell_by_index(0, 'ProductName'); - spyOn(grid.gridAPI.crudService, 'endEdit').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endEdit'); UIInteractions.simulateDoubleClickAndSelectEvent(cellElem); fix.detectChanges(); @@ -2259,7 +2244,7 @@ describe('IgxGrid - Row Editing #grid', () => { fix.detectChanges(); expect(cellElem.active).toBeTruthy(); - expect(grid.nativeElement.contains(document.activeElement)).toBeTrue(); + expect(grid.nativeElement.contains(document.activeElement)).toBe(true); }); it('Empty template', () => { @@ -2345,8 +2330,8 @@ describe('IgxGrid - Row Editing #grid', () => { const newCellValue = 'Aaaaa'; const updatedRowData = Object.assign({}, row.data, { ProductName: newCellValue }); - spyOn(grid.cellEditDone, 'emit').and.callThrough(); - const rowDoneSpy = spyOn(grid.rowEditDone, 'emit').and.callThrough(); + vi.spyOn(grid.cellEditDone, 'emit'); + const rowDoneSpy = vi.spyOn(grid.rowEditDone, 'emit'); UIInteractions.simulateDoubleClickAndSelectEvent(cellElem); fix.detectChanges(); @@ -2364,7 +2349,7 @@ describe('IgxGrid - Row Editing #grid', () => { newValue: newCellValue, column: cell.column, owner: grid, - event: jasmine.anything() as any, + event: expect.anything() as any, valid: true }; @@ -2377,7 +2362,7 @@ describe('IgxGrid - Row Editing #grid', () => { newValue: Object.assign({}, row.data, { ProductName: newCellValue }), owner: grid, isAddRow: row.addRowUI, - event: jasmine.anything() as any, + event: expect.anything() as any, valid: true }; @@ -2389,7 +2374,7 @@ describe('IgxGrid - Row Editing #grid', () => { expect(grid.cellEditDone.emit).toHaveBeenCalledWith(cellDoneArgs); expect(grid.rowEditDone.emit).toHaveBeenCalledWith(rowDoneArgs); - const rowDoneSpyArgs = rowDoneSpy.calls.mostRecent().args[0] as IGridEditDoneEventArgs; + const rowDoneSpyArgs = vi.mocked(rowDoneSpy).mock.lastCall[0] as IGridEditDoneEventArgs; expect(rowDoneSpyArgs.rowData).toBe(rowDoneSpyArgs.newValue); }); @@ -2440,7 +2425,7 @@ describe('IgxGrid - Row Editing #grid', () => { grid.deleteRow(1); fix.detectChanges(); - spyOn(grid.gridAPI.crudService, 'endRowTransaction').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endRowTransaction'); const firstCell = grid.gridAPI.get_cell_by_index(2, 'ProductName'); UIInteractions.simulateDoubleClickAndSelectEvent(firstCell); @@ -2462,7 +2447,7 @@ describe('IgxGrid - Row Editing #grid', () => { // Check if row is deleted expect(row.deleted).toBe(true); - spyOn(grid.gridAPI.crudService, 'endRowTransaction').and.callThrough(); + vi.spyOn(grid.gridAPI.crudService, 'endRowTransaction'); const firstCell = grid.gridAPI.get_cell_by_index(2, 'ProductName'); UIInteractions.simulateDoubleClickAndSelectEvent(firstCell); @@ -2533,7 +2518,7 @@ describe('IgxGrid - Row Editing #grid', () => { it('Transaction Update, Delete, Add, Undo, Redo, Commit check transaction and grid state', () => { const trans = grid.transactions; - spyOn(trans.onStateUpdate, 'emit').and.callThrough(); + vi.spyOn(trans.onStateUpdate, 'emit'); let row = null; let updateValue = 'Chaiiii'; cell.editMode = true; @@ -2744,8 +2729,8 @@ describe('IgxGrid - Row Editing #grid', () => { targetRowElement = targetRow.element.nativeElement; targetCellElement = targetRow.cells.toArray()[1].nativeElement; - expect(targetRowElement.classList).toContain(ROW_EDITED_CLASS, 'row does not contain edited class w/ edits'); - expect(targetCellElement.classList).toContain('igx-grid__td--edited', 'cell does not contain edited class w/ edits'); + expect(targetRowElement.classList, 'row does not contain edited class w/ edits').toContain(ROW_EDITED_CLASS); + expect(targetCellElement.classList, 'cell does not contain edited class w/ edits').toContain('igx-grid__td--edited'); }); it('Should change pages when the only item on the last page is a pending added row that gets deleted', () => { @@ -2959,7 +2944,7 @@ describe('IgxGrid - Row Editing #grid', () => { it(`Should not commit added row to grid's data in grid with transactions`, () => { - spyOn(trans, 'add').and.callThrough(); + vi.spyOn(trans, 'add'); const addRowData = { ProductID: 100, @@ -2978,7 +2963,7 @@ describe('IgxGrid - Row Editing #grid', () => { }); it(`Should not delete deleted row from grid's data in grid with transactions`, () => { - spyOn(trans, 'add').and.callThrough(); + vi.spyOn(trans, 'add'); grid.deleteRow(5); @@ -2989,7 +2974,7 @@ describe('IgxGrid - Row Editing #grid', () => { }); it(`Should not update updated cell in grid's data in grid with transactions`, () => { - spyOn(trans, 'add').and.callThrough(); + vi.spyOn(trans, 'add'); grid.updateCell('Updated Cell', 3, 'ProductName'); @@ -3004,7 +2989,7 @@ describe('IgxGrid - Row Editing #grid', () => { }); it(`Should not update updated row in grid's data in grid with transactions`, () => { - spyOn(trans, 'add').and.callThrough(); + vi.spyOn(trans, 'add'); const updateRowData = { ProductID: 100, diff --git a/projects/igniteui-angular/grids/grid/src/grid-row-pinning.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-row-pinning.spec.ts index cdbe0bf2861..55c5a5fe73a 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-row-pinning.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-row-pinning.spec.ts @@ -14,6 +14,7 @@ import { GridRowConditionalStylingComponent } from '../../../test-utils/grid-bas import { IgxColumnLayoutComponent } from 'igniteui-angular/grids/core'; import { ColumnPinningPosition, IgxStringFilteringOperand, SortingDirection } from 'igniteui-angular/core'; import { IgxPaginatorComponent } from 'igniteui-angular/paginator'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; describe('Row Pinning #grid', () => { const FIXED_ROW_CONTAINER = '.igx-grid__tr--pinned '; @@ -145,7 +146,7 @@ describe('Row Pinning #grid', () => { }); it('should emit rowPinning on pin/unpin.', () => { - spyOn(grid.rowPinning, 'emit').and.callThrough(); + vi.spyOn(grid.rowPinning, 'emit'); let row = grid.getRowByIndex(0); const rowID = row.key; @@ -173,7 +174,7 @@ describe('Row Pinning #grid', () => { }); it('should emit correct rowPinning arguments on pin/unpin.', () => { - spyOn(grid.rowPinning, 'emit').and.callThrough(); + vi.spyOn(grid.rowPinning, 'emit'); const row = grid.getRowByIndex(5); const rowID = row.key; @@ -229,7 +230,7 @@ describe('Row Pinning #grid', () => { }); it('should emit rowPinned on pin/unpin.', () => { - spyOn(grid.rowPinned, 'emit').and.callThrough(); + vi.spyOn(grid.rowPinned, 'emit'); const row = grid.getRowByIndex(0); const rowID = row.key; @@ -256,7 +257,7 @@ describe('Row Pinning #grid', () => { }); it(`Should be able to cancel rowPinning on pin/unpin event.`, () => { - spyOn(grid.rowPinning, 'emit').and.callThrough(); + vi.spyOn(grid.rowPinning, 'emit'); let sub = grid.rowPinning.subscribe((e: IPinRowEventArgs) => { e.cancel = true; }); @@ -1031,7 +1032,7 @@ describe('Row Pinning #grid', () => { }); it('should enter edit mode for the next editable cell when tabbing.', () => { - const gridContent = GridFunctions.getGridContent(fix); + const gridContent = GridFunctions.getGridContent(fix); grid.gridAPI.get_row_by_index(0).pin(); grid.gridAPI.get_row_by_index(3).pin(); @@ -1067,7 +1068,7 @@ describe('Row Pinning #grid', () => { expect(fourthEditable.editMode).toBeTruthy(); }); it('should enter edit mode for the previous editable cell when shift+tabbing.', () => { - const gridContent = GridFunctions.getGridContent(fix); + const gridContent = GridFunctions.getGridContent(fix); grid.gridAPI.get_row_by_index(0).pin(); grid.gridAPI.get_row_by_index(3).pin(); @@ -1133,7 +1134,7 @@ describe('Row Pinning #grid', () => { await wait(DEBOUNCE_TIME); fix.detectChanges(); - const lastRowCell = grid.getRowByIndex(27).cells[1]; + const lastRowCell = grid.getRowByIndex(27).cells[1]; const selectedCell = fix.componentInstance.instance.selectedCells[0]; // expect(selectedCell).toBe(lastRowCell); expect(selectedCell.row.index).toBe(lastRowCell.row.index); @@ -1158,7 +1159,7 @@ describe('Row Pinning #grid', () => { await wait(DEBOUNCE_TIME); fix.detectChanges(); - const secondRowCell = grid.getRowByIndex(1).cells[1]; + const secondRowCell = grid.getRowByIndex(1).cells[1]; const selectedCell = fix.componentInstance.instance.selectedCells[0]; expect(selectedCell.row.index).toBe(secondRowCell.row.index); expect(selectedCell.column.visibleIndex).toBe(secondRowCell.column.visibleIndex); @@ -1186,7 +1187,7 @@ describe('Row Pinning #grid', () => { await wait(DEBOUNCE_TIME); fix.detectChanges(); - const firstRowCell = grid.getRowByIndex(0).cells[1]; + const firstRowCell = grid.getRowByIndex(0).cells[1]; const selectedCell = fix.componentInstance.instance.selectedCells[0]; expect(selectedCell.row.index).toBe(firstRowCell.row.index); expect(selectedCell.column.visibleIndex).toBe(firstRowCell.column.visibleIndex); @@ -1209,7 +1210,7 @@ describe('Row Pinning #grid', () => { await wait(DEBOUNCE_TIME); fix.detectChanges(); - const secondRowCell = grid.getRowByIndex(1).cells[1]; + const secondRowCell = grid.getRowByIndex(1).cells[1]; const selectedCell = fix.componentInstance.instance.selectedCells[0]; expect(selectedCell.row.index).toBe(secondRowCell.row.index); expect(selectedCell.column.visibleIndex).toBe(secondRowCell.column.visibleIndex); @@ -1239,7 +1240,7 @@ describe('Row Pinning #grid', () => { await wait(DEBOUNCE_TIME); fix.detectChanges(); - const firstRowCell = grid.getRowByIndex(0).cells[1]; + const firstRowCell = grid.getRowByIndex(0).cells[1]; const selectedCell = fix.componentInstance.instance.selectedCells[0]; expect(selectedCell.row.index).toBe(firstRowCell.row.index); expect(selectedCell.column.visibleIndex).toBe(firstRowCell.column.visibleIndex); @@ -1261,7 +1262,7 @@ describe('Row Pinning #grid', () => { await wait(DEBOUNCE_TIME); fix.detectChanges(); - const lastUnpinnedRowCell = grid.getRowByIndex(26).cells[1]; + const lastUnpinnedRowCell = grid.getRowByIndex(26).cells[1]; const selectedCell = fix.componentInstance.instance.selectedCells[0]; expect(selectedCell.row.index).toBe(lastUnpinnedRowCell.row.index); expect(selectedCell.column.visibleIndex).toBe(lastUnpinnedRowCell.column.visibleIndex); @@ -1317,7 +1318,7 @@ describe('Row Pinning #grid', () => { await wait(DEBOUNCE_TIME); fix.detectChanges(); - const lastRowCell = grid.getRowByIndex(27).cells[1]; + const lastRowCell = grid.getRowByIndex(27).cells[1]; const selectedCell = fix.componentInstance.instance.selectedCells[0]; expect(selectedCell.row.index).toBe(lastRowCell.row.index); expect(selectedCell.column.visibleIndex).toBe(lastRowCell.column.visibleIndex); @@ -1338,7 +1339,7 @@ describe('Row Pinning #grid', () => { await wait(DEBOUNCE_TIME); fix.detectChanges(); - const lastRowCell = grid.getRowByIndex(1).cells[1]; + const lastRowCell = grid.getRowByIndex(1).cells[1]; const selectedCell = fix.componentInstance.instance.selectedCells[0]; expect(selectedCell.row.index).toBe(lastRowCell.row.index); expect(selectedCell.column.visibleIndex).toBe(lastRowCell.column.visibleIndex); @@ -1354,7 +1355,7 @@ describe('Row Pinning #grid', () => { it('should pin rows on OnInit.', () => { fix.detectChanges(); - expect(grid.hasPinnedRecords).toBeTrue(); + expect(grid.hasPinnedRecords).toBe(true); }); }); @@ -1372,14 +1373,14 @@ describe('Row Pinning #grid', () => { const fourthRow = grid.gridAPI.get_row_by_index(3); expect(firstRow).toBeDefined(); - expect(firstRow.nativeElement.classList.contains('eventRow')).toBeTrue(); - expect(firstRow.nativeElement.classList.contains('oddRow')).toBeFalse(); - expect(fourthRow.nativeElement.classList.contains('eventRow')).toBeFalse(); - expect(fourthRow.nativeElement.classList.contains('oddRow')).toBeTrue(); + expect(firstRow.nativeElement.classList.contains('eventRow')).toBe(true); + expect(firstRow.nativeElement.classList.contains('oddRow')).toBe(false); + expect(fourthRow.nativeElement.classList.contains('eventRow')).toBe(false); + expect(fourthRow.nativeElement.classList.contains('oddRow')).toBe(true); }); it('Should apply custom CSS bindings to the grid cells/rows. Check the style attribute to match each binding', () => { - const evenColStyles = { + const evenColStyles = { background: (row) => row.index % 2 === 0 ? 'gray' : 'white', animation: '0.75s popin' }; @@ -1481,7 +1482,8 @@ export class GridRowPinningWithMRLComponent extends GridRowPinningComponent { `, imports: [IgxGridComponent, IgxGridDetailTemplateDirective] }) -export class GridRowPinningWithMDVComponent extends GridRowPinningComponent { } +export class GridRowPinningWithMDVComponent extends GridRowPinningComponent { +} @Component({ @@ -1498,7 +1500,8 @@ export class GridRowPinningWithMDVComponent extends GridRowPinningComponent { } `, imports: [IgxGridComponent] }) -export class GridRowPinningWithTransactionsComponent extends GridRowPinningComponent { } +export class GridRowPinningWithTransactionsComponent extends GridRowPinningComponent { +} @Component({ template: ` diff --git a/projects/igniteui-angular/grids/grid/src/grid-row-selection.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-row-selection.spec.ts index 1b71f444157..9357615b3ed 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-row-selection.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-row-selection.spec.ts @@ -2,18 +2,12 @@ import { TestBed, fakeAsync, tick, waitForAsync, ComponentFixture } from '@angul import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxGridComponent } from './grid.component'; import { wait, UIInteractions } from '../../../test-utils/ui-interactions.spec'; -import { - RowSelectionComponent, - SelectionWithScrollsComponent, - SingleRowSelectionComponent, - RowSelectionWithoutPrimaryKeyComponent, - SelectionWithTransactionsComponent, - GridCustomSelectorsComponent -} from '../../../test-utils/grid-samples.spec'; +import { RowSelectionComponent, SelectionWithScrollsComponent, SingleRowSelectionComponent, RowSelectionWithoutPrimaryKeyComponent, SelectionWithTransactionsComponent, GridCustomSelectorsComponent } from '../../../test-utils/grid-samples.spec'; import { GridFunctions, GridSelectionFunctions } from '../../../test-utils/grid-functions.spec'; import { SampleTestData } from '../../../test-utils/sample-test-data.spec'; import { GridSelectionMode, IRowSelectionEventArgs } from 'igniteui-angular/grids/core'; import { FilteringExpressionsTree, FilteringLogic, IgxBooleanFilteringOperand, IgxNumberFilteringOperand, IgxStringFilteringOperand, SortingDirection } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const DEBOUNCETIME = 30; const SCROLL_DEBOUNCETIME = 100; @@ -126,8 +120,8 @@ describe('IgxGrid - Row Selection #grid', () => { it('Header checkbox should select/deselect all rows', () => { const allRows = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]; const allRowsArray = [gridData[0], gridData[1], gridData[2], gridData[3], gridData[4], gridData[5], gridData[6], gridData[7], gridData[8], gridData[9], - gridData[10], gridData[11], gridData[12], gridData[13], gridData[14], gridData[15], gridData[16], gridData[17], gridData[18]]; - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + gridData[10], gridData[11], gridData[12], gridData[13], gridData[14], gridData[15], gridData[16], gridData[17], gridData[18]]; + vi.spyOn(grid.rowSelectionChanging, 'emit'); GridSelectionFunctions.clickHeaderRowCheckbox(fix); fix.detectChanges(); @@ -138,7 +132,7 @@ describe('IgxGrid - Row Selection #grid', () => { let args: IRowSelectionEventArgs = { added: allRowsArray, cancel: false, - event: jasmine.anything() as any, + event: expect.anything() as any, newSelection: allRowsArray, oldSelection: [], removed: [], @@ -159,7 +153,7 @@ describe('IgxGrid - Row Selection #grid', () => { newSelection: [], added: [], removed: allRowsArray, - event: jasmine.anything() as any, + event: expect.anything() as any, cancel: false, allRowsSelected: false, owner: grid @@ -169,7 +163,7 @@ describe('IgxGrid - Row Selection #grid', () => { it('Header checkbox should deselect all rows - scenario when clicking first row, while header checkbox is clicked', () => { const firstRow = grid.gridAPI.get_row_by_index(0); - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); GridSelectionFunctions.clickHeaderRowCheckbox(fix); fix.detectChanges(); @@ -200,7 +194,7 @@ describe('IgxGrid - Row Selection #grid', () => { it('Checkbox should select/deselect row', () => { const firstRow = grid.gridAPI.get_row_by_index(0); const secondRow = grid.gridAPI.get_row_by_index(1); - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); GridSelectionFunctions.clickRowCheckbox(firstRow); fix.detectChanges(); @@ -209,7 +203,7 @@ describe('IgxGrid - Row Selection #grid', () => { let args: IRowSelectionEventArgs = { added: [gridData[0]], cancel: false, - event: jasmine.anything() as any, + event: expect.anything() as any, newSelection: [gridData[0]], oldSelection: [], removed: [], @@ -234,7 +228,7 @@ describe('IgxGrid - Row Selection #grid', () => { args = { added: [gridData[1]], cancel: false, - event: jasmine.anything() as any, + event: expect.anything() as any, newSelection: [gridData[0], gridData[1]], oldSelection: [gridData[0]], removed: [], @@ -254,7 +248,7 @@ describe('IgxGrid - Row Selection #grid', () => { args = { added: [], cancel: false, - event: jasmine.anything() as any, + event: expect.anything() as any, newSelection: [gridData[1]], oldSelection: [gridData[0], gridData[1]], removed: [gridData[0]], @@ -273,7 +267,7 @@ describe('IgxGrid - Row Selection #grid', () => { args = { added: [], cancel: false, - event: jasmine.anything() as any, + event: expect.anything() as any, newSelection: [], oldSelection: [gridData[1]], removed: [gridData[1]], @@ -287,7 +281,7 @@ describe('IgxGrid - Row Selection #grid', () => { const firstRow = grid.gridAPI.get_row_by_index(0); const secondRow = grid.gridAPI.get_row_by_index(1); const thirdRow = grid.gridAPI.get_row_by_index(2); - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); GridSelectionFunctions.clickRowCheckbox(thirdRow); fix.detectChanges(); @@ -296,7 +290,7 @@ describe('IgxGrid - Row Selection #grid', () => { let args: IRowSelectionEventArgs = { added: [gridData[2]], cancel: false, - event: jasmine.anything() as any, + event: expect.anything() as any, newSelection: [gridData[2]], oldSelection: [], removed: [], @@ -312,7 +306,7 @@ describe('IgxGrid - Row Selection #grid', () => { args = { added: [gridData[0]], cancel: false, - event: jasmine.anything() as any, + event: expect.anything() as any, newSelection: [gridData[2], gridData[0]], oldSelection: [gridData[2]], removed: [], @@ -328,7 +322,7 @@ describe('IgxGrid - Row Selection #grid', () => { args = { added: [gridData[1]], cancel: false, - event: jasmine.anything() as any, + event: expect.anything() as any, newSelection: [gridData[2], gridData[0], gridData[1]], oldSelection: [gridData[2], gridData[0]], removed: [], @@ -346,7 +340,7 @@ describe('IgxGrid - Row Selection #grid', () => { it('Should maintain selected rows through data change and new selection', async () => { const firstRow = grid.gridAPI.get_row_by_index(0); const secondRow = grid.gridAPI.get_row_by_index(1); - spyOn(grid.rowSelectionChanging, 'emit'); + vi.spyOn(grid.rowSelectionChanging, 'emit'); // second detection needed to enable scroll after first runs ngAfterViewInit... fix.detectChanges(); @@ -364,7 +358,7 @@ describe('IgxGrid - Row Selection #grid', () => { let args: IRowSelectionEventArgs = { added: [gridData[14]], cancel: false, - event: jasmine.anything() as any, + event: expect.anything() as any, newSelection: [gridData[14]], oldSelection: [], removed: [], @@ -385,8 +379,8 @@ describe('IgxGrid - Row Selection #grid', () => { args = { ...args, added: [gridData[0]], - newSelection: [{ [grid.primaryKey]: row15Data[grid.primaryKey]}, gridData[0]], - oldSelection: [{ [grid.primaryKey]: row15Data[grid.primaryKey]}], + newSelection: [{ [grid.primaryKey]: row15Data[grid.primaryKey] }, gridData[0]], + oldSelection: [{ [grid.primaryKey]: row15Data[grid.primaryKey] }], }; expect(grid.rowSelectionChanging.emit).toHaveBeenCalledWith(args); @@ -420,7 +414,7 @@ describe('IgxGrid - Row Selection #grid', () => { it('Should select the row with mouse click ', () => { expect(grid.selectRowOnClick).toBe(true); - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); const firstRow = grid.gridAPI.get_row_by_index(1); const secondRow = grid.gridAPI.get_row_by_index(2); const mockEvent = new MouseEvent('click'); @@ -476,7 +470,7 @@ describe('IgxGrid - Row Selection #grid', () => { expect(grid.selectRowOnClick).toBe(false); grid.hideRowSelectors = false; - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); const firstRow = grid.gridAPI.get_row_by_index(1); const secondRow = grid.gridAPI.get_row_by_index(2); @@ -499,7 +493,7 @@ describe('IgxGrid - Row Selection #grid', () => { }); it('Should select multiple rows with clicking and holding Ctrl', () => { expect(grid.selectRowOnClick).toBe(true); - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); const firstRow = grid.gridAPI.get_row_by_index(2); const secondRow = grid.gridAPI.get_row_by_index(0); @@ -520,7 +514,7 @@ describe('IgxGrid - Row Selection #grid', () => { }); it('Should deselect selected row with clicking and holding Ctrl', () => { expect(grid.selectRowOnClick).toBe(true); - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); const firstRow = grid.gridAPI.get_row_by_index(2); const secondRow = grid.gridAPI.get_row_by_index(0); @@ -560,7 +554,7 @@ describe('IgxGrid - Row Selection #grid', () => { it('Should NOT select rows with clicking and holding Ctrl when selectRowOnClick has false value', () => { grid.selectRowOnClick = false; grid.hideRowSelectors = false; - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); const firstRow = grid.gridAPI.get_row_by_index(2); const secondRow = grid.gridAPI.get_row_by_index(0); const thirdRow = grid.gridAPI.get_row_by_index(4); @@ -592,7 +586,7 @@ describe('IgxGrid - Row Selection #grid', () => { grid.tbody.nativeElement.focus(); fix.detectChanges(); - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); const firstRow = grid.gridAPI.get_row_by_index(0); const secondRow = grid.gridAPI.get_row_by_index(1); let cell = grid.gridAPI.get_cell_by_index(0, 'ProductName'); @@ -639,7 +633,7 @@ describe('IgxGrid - Row Selection #grid', () => { it('Should select multiple rows with Shift + Click', () => { expect(grid.selectRowOnClick).toBe(true); - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); const firstRow = grid.gridAPI.get_row_by_index(1); const secondRow = grid.gridAPI.get_row_by_index(4); const mockEvent = new MouseEvent('click', { shiftKey: true }); @@ -674,7 +668,7 @@ describe('IgxGrid - Row Selection #grid', () => { it('Should select the correct rows with Shift + Click when grouping is activated', () => { expect(grid.selectRowOnClick).toBe(true); - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); grid.groupBy({ fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false @@ -701,7 +695,7 @@ describe('IgxGrid - Row Selection #grid', () => { expect(grid.rowSelectionChanging.emit).toHaveBeenCalledWith({ added: [grid.dataView[2], grid.dataView[4]], cancel: false, - event: jasmine.anything(), + event: expect.anything(), newSelection: [grid.dataView[1], grid.dataView[2], grid.dataView[4]], oldSelection: [grid.dataView[1]], removed: [], @@ -721,7 +715,7 @@ describe('IgxGrid - Row Selection #grid', () => { it('Should NOT select multiple rows with Shift + Click when selectRowOnClick has false value', () => { grid.selectRowOnClick = false; - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); // Shift + Click const firstRow = grid.gridAPI.get_row_by_index(1); const secondRow = grid.gridAPI.get_row_by_index(4); @@ -1011,7 +1005,7 @@ describe('IgxGrid - Row Selection #grid', () => { }); it('Header checkbox should NOT select/deselect all rows when selectionMode is single', () => { - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); GridSelectionFunctions.clickHeaderRowCheckbox(fix); fix.detectChanges(); @@ -1042,7 +1036,7 @@ describe('IgxGrid - Row Selection #grid', () => { it('Should be able to select only one row when click on a checkbox', () => { const firstRow = grid.gridAPI.get_row_by_index(0); const secondRow = grid.gridAPI.get_row_by_index(1); - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); GridSelectionFunctions.clickRowCheckbox(firstRow); fix.detectChanges(); @@ -1051,7 +1045,7 @@ describe('IgxGrid - Row Selection #grid', () => { let args: IRowSelectionEventArgs = { added: [gridData[0]], cancel: false, - event: jasmine.anything() as any, + event: expect.anything() as any, newSelection: [gridData[0]], oldSelection: [], removed: [], @@ -1075,7 +1069,7 @@ describe('IgxGrid - Row Selection #grid', () => { args = { added: [gridData[1]], cancel: false, - event: jasmine.anything() as any, + event: expect.anything() as any, newSelection: [gridData[1]], oldSelection: [gridData[0]], removed: [gridData[0]], @@ -1089,7 +1083,7 @@ describe('IgxGrid - Row Selection #grid', () => { grid.tbody.nativeElement.focus(); fix.detectChanges(); - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); const firstRow = grid.gridAPI.get_row_by_index(0); const cell = grid.gridAPI.get_cell_by_index(0, 0); UIInteractions.simulateClickEvent(cell.nativeElement); @@ -1100,7 +1094,7 @@ describe('IgxGrid - Row Selection #grid', () => { expect(grid.rowSelectionChanging.emit).toHaveBeenCalledTimes(0); }); it('Should not select multiple rows with clicking and holding Ctrl', () => { - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); const firstRow = grid.gridAPI.get_row_by_index(2); const secondRow = grid.gridAPI.get_row_by_index(0); @@ -1121,7 +1115,7 @@ describe('IgxGrid - Row Selection #grid', () => { expect(grid.rowSelectionChanging.emit).toHaveBeenCalledTimes(2); }); it('Should deselect a selected row with clicking and holding Ctrl', () => { - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); const firstRow = grid.gridAPI.get_row_by_index(2); UIInteractions.simulateClickEvent(firstRow.nativeElement); @@ -1141,7 +1135,7 @@ describe('IgxGrid - Row Selection #grid', () => { }); it('Should not select a row with clicking and holding Ctrl when selectRowOnClick has false value', () => { grid.selectRowOnClick = false; - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); const firstRow = grid.gridAPI.get_row_by_index(2); const secondRow = grid.gridAPI.get_row_by_index(0); @@ -1165,7 +1159,7 @@ describe('IgxGrid - Row Selection #grid', () => { grid.tbody.nativeElement.focus(); fix.detectChanges(); - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); const firstRow = grid.gridAPI.get_row_by_index(0); const secondRow = grid.gridAPI.get_row_by_index(1); let cell = grid.gridAPI.get_cell_by_index(0, 'ProductName'); @@ -1209,7 +1203,7 @@ describe('IgxGrid - Row Selection #grid', () => { })); it('Should not select multiple rows with Shift + Click', () => { - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); const firstRow = grid.gridAPI.get_row_by_index(1); const secondRow = grid.gridAPI.get_row_by_index(4); const mockEvent = new MouseEvent('click', { shiftKey: true }); @@ -1245,7 +1239,7 @@ describe('IgxGrid - Row Selection #grid', () => { }); it('Should not select row with Shift + Click when selectRowOnClick has false value ', () => { grid.selectRowOnClick = false; - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); // Shift + Click const firstRow = grid.gridAPI.get_row_by_index(1); @@ -1298,15 +1292,13 @@ describe('IgxGrid - Row Selection #grid', () => { grid.selectRows([1, 3, 5], true); fix.detectChanges(); - GridSelectionFunctions.verifyRowsArraySelected( - [grid.gridAPI.get_row_by_index(0), grid.gridAPI.get_row_by_index(2), grid.gridAPI.get_row_by_index(4)]); + GridSelectionFunctions.verifyRowsArraySelected([grid.gridAPI.get_row_by_index(0), grid.gridAPI.get_row_by_index(2), grid.gridAPI.get_row_by_index(4)]); expect(grid.selectedRows).toEqual([1, 3, 5]); grid.selectRows([1, 2, 4], false); fix.detectChanges(); - GridSelectionFunctions.verifyRowsArraySelected( - [grid.gridAPI.get_row_by_index(0), + GridSelectionFunctions.verifyRowsArraySelected([grid.gridAPI.get_row_by_index(0), grid.gridAPI.get_row_by_index(1), grid.gridAPI.get_row_by_index(2), grid.gridAPI.get_row_by_index(3), @@ -1419,7 +1411,7 @@ describe('IgxGrid - Row Selection #grid', () => { }); it('Should be able to programmatically select all rows and keep the header checkbox intact, #1298', () => { - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); grid.selectAllRows(); grid.cdr.detectChanges(); fix.detectChanges(); @@ -1443,7 +1435,7 @@ describe('IgxGrid - Row Selection #grid', () => { }); it('Should be able to select/deselect rows programmatically', () => { - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); const firstRow = grid.gridAPI.get_row_by_index(0); const secondRow = grid.gridAPI.get_row_by_index(1); const thirdRow = grid.gridAPI.get_row_by_index(2); @@ -1553,7 +1545,7 @@ describe('IgxGrid - Row Selection #grid', () => { }); it('Verify event parameters', () => { - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); const firstRow = grid.gridAPI.get_row_by_index(1); const secondRow = grid.gridAPI.get_row_by_index(4); @@ -1566,7 +1558,7 @@ describe('IgxGrid - Row Selection #grid', () => { let args: IRowSelectionEventArgs = { added: [gridData[1]], cancel: false, - event: jasmine.anything() as any, + event: expect.anything() as any, newSelection: [gridData[1]], oldSelection: [], removed: [], @@ -1583,7 +1575,7 @@ describe('IgxGrid - Row Selection #grid', () => { args = { added: [gridData[2], gridData[3], gridData[4]], cancel: false, - event: jasmine.anything() as any, + event: expect.anything() as any, newSelection: [gridData[1], gridData[2], gridData[3], gridData[4]], oldSelection: [gridData[1]], removed: [], @@ -1665,14 +1657,14 @@ describe('IgxGrid - Row Selection #grid', () => { it('Should be able to select row through primaryKey and index', () => { expect(grid.primaryKey).toBeTruthy(); - expect(grid.rowList.length).toEqual(10, 'All 10 rows should initialized'); + expect(grid.rowList.length, 'All 10 rows should initialized').toEqual(10); expect(grid.getRowByKey(2).data['ProductName']).toMatch('Aniseed Syrup'); expect(grid.gridAPI.get_row_by_index(1).data['ProductName']).toMatch('Aniseed Syrup'); }); it('Should be able to update a cell in a row through primaryKey', () => { expect(grid.primaryKey).toBeTruthy(); - expect(grid.rowList.length).toEqual(10, 'All 10 rows should initialized'); + expect(grid.rowList.length, 'All 10 rows should initialized').toEqual(10); expect(grid.getRowByKey(2).data['UnitsInStock']).toEqual(198); grid.updateCell(300, 2, 'UnitsInStock'); fix.detectChanges(); @@ -1681,7 +1673,7 @@ describe('IgxGrid - Row Selection #grid', () => { it('Should be able to update row through primaryKey', () => { expect(grid.primaryKey).toBeTruthy(); - expect(grid.rowList.length).toEqual(10, 'All 10 rows should initialized'); + expect(grid.rowList.length, 'All 10 rows should initialized').toEqual(10); expect(grid.getRowByKey(2).data['UnitsInStock']).toEqual(198); grid.updateRow({ ProductID: 2, ProductName: 'Aniseed Syrup', UnitsInStock: 300 }, 2); fix.detectChanges(); @@ -1691,7 +1683,7 @@ describe('IgxGrid - Row Selection #grid', () => { it('Should be able to delete a row through primaryKey', () => { expect(grid.primaryKey).toBeTruthy(); - expect(grid.rowList.length).toEqual(10, 'All 10 rows should initialized'); + expect(grid.rowList.length, 'All 10 rows should initialized').toEqual(10); expect(grid.getRowByKey(2)).toBeDefined(); grid.deleteRow(2); fix.detectChanges(); @@ -1701,7 +1693,7 @@ describe('IgxGrid - Row Selection #grid', () => { it('Should handle update by not overwriting the value in the data column specified as primaryKey', () => { expect(grid.primaryKey).toBeTruthy(); - expect(grid.rowList.length).toEqual(10, 'All 10 rows should initialized'); + expect(grid.rowList.length, 'All 10 rows should initialized').toEqual(10); expect(grid.getRowByKey(2)).toBeDefined(); grid.updateRow({ ProductID: 7, ProductName: 'Aniseed Syrup', UnitsInStock: 300 }, 2); fix.detectChanges(); @@ -1956,7 +1948,7 @@ describe('IgxGrid - Row Selection #grid', () => { }); it('Filtering: Should properly check the header checkbox state when filtering, #2469', () => { - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); grid.filter('ProductID', 10, IgxNumberFilteringOperand.instance().condition('greaterThanOrEqualTo'), true); fix.detectChanges(); @@ -1998,7 +1990,7 @@ describe('IgxGrid - Row Selection #grid', () => { }); it('Filtering: Should select correct rows when filter is applied', () => { - spyOn(grid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(grid.rowSelectionChanging, 'emit'); const secondRow = grid.gridAPI.get_row_by_index(1); GridSelectionFunctions.clickRowCheckbox(secondRow); @@ -2114,14 +2106,14 @@ describe('IgxGrid - Row Selection #grid', () => { it('Should bind selectedRows properly', () => { fix.componentInstance.selectedRows = [1, 2, 3]; fix.detectChanges(); - expect(grid.gridAPI.get_row_by_index(0).selected).toBeTrue(); - expect(grid.gridAPI.get_row_by_index(4).selected).toBeFalse(); + expect(grid.gridAPI.get_row_by_index(0).selected).toBe(true); + expect(grid.gridAPI.get_row_by_index(4).selected).toBe(false); fix.componentInstance.selectedRows = [4, 5, 6]; fix.detectChanges(); - expect(grid.gridAPI.get_row_by_index(3).selected).toBeTrue(); - expect(grid.gridAPI.get_row_by_index(0).selected).toBeFalse(); + expect(grid.gridAPI.get_row_by_index(3).selected).toBe(true); + expect(grid.gridAPI.get_row_by_index(0).selected).toBe(false); }); it('Row Pinning: should update checkbox status correctly when there is pinned row and groupBy', () => { @@ -2390,7 +2382,7 @@ describe('IgxGrid - Row Selection #grid', () => { const firstCheckbox = firstRow.nativeElement.querySelector('.igx-checkbox__composite'); const context = { index: 0, rowID: 'ALFKI', key: 'ALFKI', selected: false }; const contextUnselect = { index: 0, rowID: 'ALFKI', key: 'ALFKI', selected: true }; - spyOn(fix.componentInstance, 'onRowCheckboxClick').and.callThrough(); + vi.spyOn(fix.componentInstance, 'onRowCheckboxClick'); firstCheckbox.click(); fix.detectChanges(); @@ -2409,7 +2401,7 @@ describe('IgxGrid - Row Selection #grid', () => { const context = { selectedCount: 0, totalCount: 27 }; const contextUnselect = { selectedCount: 27, totalCount: 27 }; const headerCheckbox = grid.theadRow.nativeElement.querySelector('.igx-checkbox__composite'); - spyOn(fix.componentInstance, 'onHeaderCheckboxClick').and.callThrough(); + vi.spyOn(fix.componentInstance, 'onHeaderCheckboxClick'); headerCheckbox.click(); fix.detectChanges(); @@ -2421,7 +2413,7 @@ describe('IgxGrid - Row Selection #grid', () => { expect(fix.componentInstance.onHeaderCheckboxClick).toHaveBeenCalledTimes(2); expect(fix.componentInstance.onHeaderCheckboxClick). - toHaveBeenCalledWith(fix.componentInstance.headerCheckboxClick, contextUnselect); + toHaveBeenCalledWith(fix.componentInstance.headerCheckboxClick, contextUnselect); }); it('Should have correct indices on all pages', () => { @@ -2443,7 +2435,7 @@ describe('IgxGrid - Row Selection #grid', () => { }); fix.detectChanges(); const rowDOM = grid.dataRowList.toArray()[0].nativeElement; - const groupRowDOM = grid.groupsRowList.toArray()[0].nativeElement + const groupRowDOM = grid.groupsRowList.toArray()[0].nativeElement; const rowSelector = rowDOM.querySelector(`.igx-grid__cbx-selection`); const groupRowSelector = groupRowDOM.querySelector(`.igx-grid__cbx-selection`); const headerSelector = GridSelectionFunctions.getHeaderRow(fix).querySelector(`.igx-grid__cbx-selection`); diff --git a/projects/igniteui-angular/grids/grid/src/grid-summary.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-summary.spec.ts index 923ab8e26fd..a899fc4ba3f 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-summary.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-summary.spec.ts @@ -1,23 +1,18 @@ -import { Component, DebugElement, ViewChild } from '@angular/core'; +import { Component, DebugElement, ViewChild } from '@angular/core'; import { fakeAsync, TestBed, tick, ComponentFixture, flush, waitForAsync } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxGridComponent } from './grid.component'; import { wait, UIInteractions } from '../../../test-utils/ui-interactions.spec'; import { GridFunctions, GridSummaryFunctions } from '../../../test-utils/grid-functions.spec'; -import { - ProductsComponent, - SummaryColumnComponent, - FilteringComponent, - SummariesGroupByComponent, - SummariesGroupByTransactionsComponent -} from '../../../test-utils/grid-samples.spec'; +import { ProductsComponent, SummaryColumnComponent, FilteringComponent, SummariesGroupByComponent, SummariesGroupByTransactionsComponent } from '../../../test-utils/grid-samples.spec'; import { clearGridSubs, setupGridScrollDetection, ymd } from '../../../test-utils/helper-utils.spec'; import { SampleTestData } from '../../../test-utils/sample-test-data.spec'; import { DropPosition, IgxColumnComponent, IgxDateSummaryOperand, IgxGridRow, IgxGroupByRow, IgxNumberSummaryOperand, IgxSummaryOperand, IgxSummaryRow } from 'igniteui-angular/grids/core'; import { DatePipe } from '@angular/common'; import { IgxGridGroupByRowComponent } from './groupby-row.component'; import { GridSummaryCalculationMode, IColumnPipeArgs, IgxNumberFilteringOperand, IgxStringFilteringOperand, IgxSummaryResult, SortingDirection } from 'igniteui-angular/core'; +import { describe, it, test, expect, beforeEach, afterEach, vi } from 'vitest'; describe('IgxGrid - Summaries #grid', () => { @@ -113,8 +108,7 @@ describe('IgxGrid - Summaries #grid', () => { fixture.detectChanges(); const summaryRow = GridSummaryFunctions.getRootSummaryRow(fixture); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], - ['11', '0', '99,000', '138,004', '12,545.818']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['11', '0', '99,000', '138,004', '12,545.818']); })); it('When we have data which is undefined and enable summary per defined column, error should not be thrown', () => { @@ -142,11 +136,7 @@ describe('IgxGrid - Summaries #grid', () => { fixture.detectChanges(); tick(); - GridSummaryFunctions.verifyColumnSummaries( - GridSummaryFunctions.getRootSummaryRow(fixture), 3, - ['Sum', 'Avg'], - ['39,004', '3,900.4'] - ); + GridSummaryFunctions.verifyColumnSummaries(GridSummaryFunctions.getRootSummaryRow(fixture), 3, ['Sum', 'Avg'], ['39,004', '3,900.4']); })); it('should apply disabled summaries dynamically at runtime', fakeAsync(() => { @@ -156,47 +146,27 @@ describe('IgxGrid - Summaries #grid', () => { const column = grid.getColumnByName('UnitsInStock'); - GridSummaryFunctions.verifyColumnSummaries( - GridSummaryFunctions.getRootSummaryRow(fixture), 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], - ['10', '0', '20,000', '39,004', '3,900.4'] - ); + GridSummaryFunctions.verifyColumnSummaries(GridSummaryFunctions.getRootSummaryRow(fixture), 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '20,000', '39,004', '3,900.4']); column.disabledSummaries = ['count']; fixture.detectChanges(); tick(); - GridSummaryFunctions.verifyColumnSummaries( - GridSummaryFunctions.getRootSummaryRow(fixture), 3, - ['Min', 'Max', 'Sum', 'Avg'], - ['0', '20,000', '39,004', '3,900.4'] - ); + GridSummaryFunctions.verifyColumnSummaries(GridSummaryFunctions.getRootSummaryRow(fixture), 3, ['Min', 'Max', 'Sum', 'Avg'], ['0', '20,000', '39,004', '3,900.4']); column.disabledSummaries = ['count', 'sum']; fixture.detectChanges(); tick(); - GridSummaryFunctions.verifyColumnSummaries( - GridSummaryFunctions.getRootSummaryRow(fixture), 3, - ['Min', 'Max', 'Avg'], - ['0', '20,000', '3,900.4'] - ); + GridSummaryFunctions.verifyColumnSummaries(GridSummaryFunctions.getRootSummaryRow(fixture), 3, ['Min', 'Max', 'Avg'], ['0', '20,000', '3,900.4']); column.disabledSummaries = ['count', 'sum', 'average']; fixture.detectChanges(); tick(); - GridSummaryFunctions.verifyColumnSummaries( - GridSummaryFunctions.getRootSummaryRow(fixture), 3, - ['Min', 'Max'], - ['0', '20,000'] - ); + GridSummaryFunctions.verifyColumnSummaries(GridSummaryFunctions.getRootSummaryRow(fixture), 3, ['Min', 'Max'], ['0', '20,000']); column.disabledSummaries = ['min', 'max']; fixture.detectChanges(); tick(); - GridSummaryFunctions.verifyColumnSummaries( - GridSummaryFunctions.getRootSummaryRow(fixture), 3, - ['Count', 'Sum', 'Avg'], - ['10', '39,004', '3,900.4'] - ); + GridSummaryFunctions.verifyColumnSummaries(GridSummaryFunctions.getRootSummaryRow(fixture), 3, ['Count', 'Sum', 'Avg'], ['10', '39,004', '3,900.4']); })); }); @@ -262,21 +232,18 @@ describe('IgxGrid - Summaries #grid', () => { grid.getColumnByName('UnitsInStock').summaries = fixture.componentInstance.inStockSummary; fixture.detectChanges(); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg', 'Items InStock'], - ['10', '0', '20,000', '39,004', '3,900.4', '6']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg', 'Items InStock'], ['10', '0', '20,000', '39,004', '3,900.4', '6']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Earliest', 'Items InStock'], ['May 17, 1990', '1337']); grid.getCellByColumn(4, 'InStock').update(true); fixture.detectChanges(); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg', 'Items InStock'], - ['10', '0', '20,000', '39,004', '3,900.4', '7']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg', 'Items InStock'], ['10', '0', '20,000', '39,004', '3,900.4', '7']); grid.filter('UnitsInStock', 0, IgxNumberFilteringOperand.instance().condition('equals')); fixture.detectChanges(); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg', 'Items InStock'], - ['3', '0', '0', '0', '0', '1']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg', 'Items InStock'], ['3', '0', '0', '0', '0', '1']); }); it('Last column summary cell should be aligned according to its data cells', () => { @@ -297,10 +264,8 @@ describe('IgxGrid - Summaries #grid', () => { const lastColumnSummaryCell = GridSummaryFunctions.getSummaryCellByVisibleIndex(summaryRow, 4); const lastColumnSummaryCellRect = lastColumnSummaryCell.nativeElement.getBoundingClientRect(); - expect(lastColumnSummaryCellRect.left).toBe(lastColumnNormalCellRect.left, - 'summary cell and data cell are not left aligned'); - expect(lastColumnSummaryCellRect.right).toBe(lastColumnNormalCellRect.right, - 'summary cell and data cell are not right aligned'); + expect(lastColumnSummaryCellRect.left, 'summary cell and data cell are not left aligned').toBe(lastColumnNormalCellRect.left); + expect(lastColumnSummaryCellRect.right, 'summary cell and data cell are not right aligned').toBe(lastColumnNormalCellRect.right); }); it('should apply disabledSummaries with custom summary', fakeAsync(() => { @@ -313,21 +278,13 @@ describe('IgxGrid - Summaries #grid', () => { fixture.detectChanges(); tick(); - GridSummaryFunctions.verifyColumnSummaries( - GridSummaryFunctions.getRootSummaryRow(fixture), 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg', 'Items InStock'], - ['10', '0', '20,000', '39,004', '3,900.4', '6'] - ); + GridSummaryFunctions.verifyColumnSummaries(GridSummaryFunctions.getRootSummaryRow(fixture), 3, ['Count', 'Min', 'Max', 'Sum', 'Avg', 'Items InStock'], ['10', '0', '20,000', '39,004', '3,900.4', '6']); column.disabledSummaries = ['test']; fixture.detectChanges(); tick(); - GridSummaryFunctions.verifyColumnSummaries( - GridSummaryFunctions.getRootSummaryRow(fixture), 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], - ['10', '0', '20,000', '39,004', '3,900.4'] - ); + GridSummaryFunctions.verifyColumnSummaries(GridSummaryFunctions.getRootSummaryRow(fixture), 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '20,000', '39,004', '3,900.4']); })); }); @@ -350,8 +307,7 @@ describe('IgxGrid - Summaries #grid', () => { const summaryRow = fixture.debugElement.query(By.css(SUMMARY_ROW)); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['8']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['8', '1', '1,000', '2,204', '275.5']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['8', '1', '1,000', '2,204', '275.5']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count'], ['8']); const options: Intl.DateTimeFormatOptions = { year: 'numeric', month: 'short', day: 'numeric' }; const earliest = SampleTestData.timeGenerator.timedelta(SampleTestData.today, 'month', -1).toLocaleString('us', options); @@ -494,8 +450,7 @@ describe('IgxGrid - Summaries #grid', () => { const summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); const pipe = new DatePipe('fr-FR'); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); grid.getColumnByName('OrderDate').summaryFormatter = ((summaryResult: IgxSummaryResult, summaryOperand: IgxSummaryOperand) => { @@ -508,8 +463,7 @@ describe('IgxGrid - Summaries #grid', () => { }); fix.detectChanges(); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Earliest', 'Latest'], ['10', '17 mai 1990', '25 déc. 2025']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['10', '17 mai 1990', '25 déc. 2025']); }); it('should calc tfoot height according number of summary functions', () => { @@ -537,8 +491,7 @@ describe('IgxGrid - Summaries #grid', () => { expect(grid.getColumnByName('UnitsInStock').hasSummary).toBe(false); - const summaries = fix.debugElement.queryAll(By.css(SUMMARY_CELL)).filter((el) => - el.nativeElement.classList.contains(EMPTY_SUMMARY_CLASS) === false); + const summaries = fix.debugElement.queryAll(By.css(SUMMARY_CELL)).filter((el) => el.nativeElement.classList.contains(EMPTY_SUMMARY_CLASS) === false); const tfootSize = GridSummaryFunctions.getRootSummaryRow(fix).nativeElement.getBoundingClientRect().height; const expectedHeight = GridSummaryFunctions.calcMaxSummaryHeight(grid.columnList, summaries, grid.defaultSummaryHeight); expect(tfootSize).toBe(expectedHeight); @@ -698,8 +651,7 @@ describe('IgxGrid - Summaries #grid', () => { GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['3']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['3']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['3', '0', '0', '0', '0']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Earliest', 'Latest'], ['3', 'Jul 27, 2001', 'Oct 11, 2007']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['3', 'Jul 27, 2001', 'Oct 11, 2007']); grid.filter('ProductID', 0, IgxNumberFilteringOperand.instance().condition('equals'), true); fix.detectChanges(); @@ -724,10 +676,8 @@ describe('IgxGrid - Summaries #grid', () => { GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['10']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['10']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '20,000', '39,004', '3,900.4']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '20,000', '39,004', '3,900.4']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); })); it('Moving: should move summaries when move column', fakeAsync(() => { @@ -741,13 +691,11 @@ describe('IgxGrid - Summaries #grid', () => { fix.detectChanges(); const summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '20,000', '39,004', '3,900.4']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '20,000', '39,004', '3,900.4']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['10']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count'], ['10']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); })); it('Hiding: should hide summary row when a column which has summary is hidded', fakeAsync(() => { @@ -762,8 +710,7 @@ describe('IgxGrid - Summaries #grid', () => { GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, [], []); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '20,000', '39,004', '3,900.4']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '20,000', '39,004', '3,900.4']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, [], []); grid.getColumnByName('UnitsInStock').hidden = true; @@ -784,8 +731,7 @@ describe('IgxGrid - Summaries #grid', () => { GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, [], []); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '20,000', '39,004', '3,900.4']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '20,000', '39,004', '3,900.4']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, [], []); })); @@ -806,8 +752,7 @@ describe('IgxGrid - Summaries #grid', () => { GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['10']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['10']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); grid.getColumnByName('UnitsInStock').hidden = false; grid.summaryRowHeight = 0; @@ -821,10 +766,8 @@ describe('IgxGrid - Summaries #grid', () => { GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['10']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['10']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '20,000', '39,004', '3,900.4']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '20,000', '39,004', '3,900.4']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); })); it('CRUD: should recalculate summary functions rowAdded', () => { @@ -837,10 +780,8 @@ describe('IgxGrid - Summaries #grid', () => { GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['11']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['11']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['11', '0', '99,000', '138,004', '12,545.818']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Earliest', 'Latest'], ['11', 'May 17, 1990', 'Dec 25, 2025']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['11', '0', '99,000', '138,004', '12,545.818']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['11', 'May 17, 1990', 'Dec 25, 2025']); }); it('CRUD: should recalculate summary functions rowDeleted', () => { @@ -851,10 +792,8 @@ describe('IgxGrid - Summaries #grid', () => { GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['9']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['9']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['9', '0', '20,000', '32,006', '3,556.222']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Earliest', 'Latest'], ['9', 'May 17, 1990', 'Mar 1, 2018']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['9', '0', '20,000', '32,006', '3,556.222']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['9', 'May 17, 1990', 'Mar 1, 2018']); }); it('CRUD: should recalculate summary functions on updateRow', () => { @@ -876,10 +815,8 @@ describe('IgxGrid - Summaries #grid', () => { GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['10']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['10']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '510,000', '546,244', '54,624.4']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Earliest', 'Latest'], ['10', 'Mar 21, 1984', 'Dec 25, 2025']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '510,000', '546,244', '54,624.4']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['10', 'Mar 21, 1984', 'Dec 25, 2025']); }); it('CRUD: should recalculate summary functions on cell update', () => { @@ -888,14 +825,12 @@ describe('IgxGrid - Summaries #grid', () => { fix.detectChanges(); let summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '99,000', '135,244', '13,524.4']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '99,000', '135,244', '13,524.4']); unitsInStockCell.update(-12); fix.detectChanges(); summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '-12', '20,000', '36,232', '3,623.2']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '-12', '20,000', '36,232', '3,623.2']); }); it('Pinning: should display all active summaries after column pinning', () => { @@ -904,13 +839,11 @@ describe('IgxGrid - Summaries #grid', () => { fix.detectChanges(); const summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '20,000', '39,004', '3,900.4']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['10', '0', '20,000', '39,004', '3,900.4']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['10']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count'], ['10']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Earliest', 'Latest'], ['10', 'May 17, 1990', 'Dec 25, 2025']); }); it('CRUD: Apply filter and update cell', () => { @@ -919,8 +852,7 @@ describe('IgxGrid - Summaries #grid', () => { let summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['4']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['4', '52', '20,000', '29,810', '7,452.5']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['4', '52', '20,000', '29,810', '7,452.5']); const cell = grid.getCellByColumn(2, 'ProductName'); cell.update('Teatime Cocoa Biscuits'); @@ -928,8 +860,7 @@ describe('IgxGrid - Summaries #grid', () => { summaryRow = fix.debugElement.query(By.css(SUMMARY_ROW)); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['3']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['3', '52', '20,000', '22,812', '7,604']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['3', '52', '20,000', '22,812', '7,604']); }); }); }); @@ -963,8 +894,7 @@ describe('IgxGrid - Summaries #grid', () => { } summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['8', '25', '50', '293', '36.625']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['8', '25', '50', '293', '36.625']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 5, ['Count'], ['8']); for (let i = 5; i > 0; i--) { @@ -976,8 +906,7 @@ describe('IgxGrid - Summaries #grid', () => { summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['8', '17', '847', '2,188', '273.5']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['8', '17', '847', '2,188', '273.5']); }); it('should be able to navigate with Arrow keys and Ctrl', async () => { @@ -990,8 +919,7 @@ describe('IgxGrid - Summaries #grid', () => { fix.detectChanges(); GridSummaryFunctions.verifySummaryCellActive(fix, summaryRow, 5); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['8', '25', '50', '293', '36.625']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['8', '25', '50', '293', '36.625']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 5, ['Count'], ['8']); UIInteractions.triggerEventHandlerKeyDown('ArrowLeft', gridFooter, false, false, true); @@ -1001,8 +929,7 @@ describe('IgxGrid - Summaries #grid', () => { GridSummaryFunctions.verifySummaryCellActive(fix, summaryRow, 0); summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['8', '17', '847', '2,188', '273.5']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['8', '17', '847', '2,188', '273.5']); }); it('should not change active summary cell when press Arrow Down and Up', () => { @@ -1035,8 +962,7 @@ describe('IgxGrid - Summaries #grid', () => { } let summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 3); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '27', '50', '77', '38.5']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '27', '50', '77', '38.5']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 5, ['Count'], ['2']); for (let i = 5; i > 0; i--) { @@ -1048,8 +974,7 @@ describe('IgxGrid - Summaries #grid', () => { summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 3); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '17', '17', '34', '17']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '17', '17', '34', '17']); }); it('Grouping: should not change active summary cell when press Ctrl+ArrowUp/Down', () => { @@ -1085,8 +1010,7 @@ describe('IgxGrid - Summaries #grid', () => { GridSummaryFunctions.verifySummaryCellActive(fix, 3, 5); let summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 3); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '27', '50', '77', '38.5']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '27', '50', '77', '38.5']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 5, ['Count'], ['2']); UIInteractions.triggerEventHandlerKeyDown('ArrowLeft', gridContent, false, false, true); @@ -1175,8 +1099,10 @@ describe('IgxGrid - Summaries #grid', () => { expect(cell.selected).toBe(false); }); - it('should navigate with tab to filter row if the grid is empty', () => { - pending('this test need to be written again when the header are ready'); + it.skip('should navigate with tab to filter row if the grid is empty', () => { + // TODO: vitest-migration: The pending() function was converted to a skipped test (`it.skip`). See: https://vitest.dev/api/vi.html#it-skip + // pending('this test need to be written again when the header are ready'); + ; grid.allowFiltering = true; grid.filter('ID', 0, IgxNumberFilteringOperand.instance().condition('lessThanOrEqualTo')); fix.detectChanges(); @@ -1326,8 +1252,7 @@ describe('IgxGrid - Summaries #grid', () => { fix.detectChanges(); let summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['8', 'Jul 19, 2009', 'Apr 3, 2019']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['8', 'Jul 19, 2009', 'Apr 3, 2019']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Min', 'Max'], ['19', '44']); // Undo transactions @@ -1335,8 +1260,7 @@ describe('IgxGrid - Summaries #grid', () => { fix.detectChanges(); summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['8', 'Dec 18, 2007', 'Dec 9, 2017']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['8', 'Dec 18, 2007', 'Dec 9, 2017']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Min', 'Max'], ['25', '50']); // redo transactions @@ -1344,8 +1268,7 @@ describe('IgxGrid - Summaries #grid', () => { fix.detectChanges(); summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['8', 'Jul 19, 2009', 'Apr 3, 2019']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['8', 'Jul 19, 2009', 'Apr 3, 2019']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Min', 'Max'], ['19', '44']); // Commit @@ -1353,8 +1276,7 @@ describe('IgxGrid - Summaries #grid', () => { fix.detectChanges(); summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['8', 'Jul 19, 2009', 'Apr 3, 2019']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['8', 'Jul 19, 2009', 'Apr 3, 2019']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Min', 'Max'], ['19', '44']); newRow = { @@ -1376,8 +1298,7 @@ describe('IgxGrid - Summaries #grid', () => { fix.detectChanges(); summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['8', 'Jul 19, 2009', 'Apr 3, 2019']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['8', 'Jul 19, 2009', 'Apr 3, 2019']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Min', 'Max'], ['19', '44']); }); @@ -1511,8 +1432,7 @@ describe('IgxGrid - Summaries #grid', () => { const summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['9']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['9', 'Dec 18, 2007', 'Dec 9, 2017']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['9', 'Dec 18, 2007', 'Dec 9, 2017']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Min', 'Max'], ['19', '50']); grid.verticalScrollContainer.scrollTo(grid.dataView.length - 1); @@ -1881,8 +1801,7 @@ describe('IgxGrid - Summaries #grid', () => { const summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 8); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['2']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['2', 'Jul 3, 2011', 'Sep 18, 2014']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['2', 'Jul 3, 2011', 'Sep 18, 2014']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '31', '43', '74', '37']); grid.clearGrouping('OnPTO'); @@ -1975,8 +1894,7 @@ describe('IgxGrid - Summaries #grid', () => { let summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 1); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '17', '17', '34', '17']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['2']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['2', 'Dec 18, 2007', 'Mar 19, 2016']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['2', 'Dec 18, 2007', 'Mar 19, 2016']); groupRows[0].toggle(); fix.detectChanges(); @@ -1986,8 +1904,7 @@ describe('IgxGrid - Summaries #grid', () => { summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 3); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '17', '17', '34', '17']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['2']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['2', 'Dec 18, 2007', 'Mar 19, 2016']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['2', 'Dec 18, 2007', 'Mar 19, 2016']); }); it('should be able to change showSummaryOnCollapse run time', () => { @@ -2010,8 +1927,7 @@ describe('IgxGrid - Summaries #grid', () => { const summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 1); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '17', '17', '34', '17']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['2']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['2', 'Dec 18, 2007', 'Mar 19, 2016']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['2', 'Dec 18, 2007', 'Mar 19, 2016']); }); @@ -2024,14 +1940,12 @@ describe('IgxGrid - Summaries #grid', () => { let summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 4); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '17', '17', '34', '17']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['2']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['2', 'Dec 18, 2007', 'Mar 19, 2016']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['2', 'Dec 18, 2007', 'Mar 19, 2016']); summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 5); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '17', '17', '34', '17']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['2']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['2', 'Dec 18, 2007', 'Mar 19, 2016']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['2', 'Dec 18, 2007', 'Mar 19, 2016']); const groupRows = grid.groupsRowList.toArray(); groupRows[1].toggle(); @@ -2040,14 +1954,12 @@ describe('IgxGrid - Summaries #grid', () => { summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 2); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '17', '17', '34', '17']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['2']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['2', 'Dec 18, 2007', 'Mar 19, 2016']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['2', 'Dec 18, 2007', 'Mar 19, 2016']); summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 3); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '17', '17', '34', '17']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['2']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['2', 'Dec 18, 2007', 'Mar 19, 2016']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['2', 'Dec 18, 2007', 'Mar 19, 2016']); grid.summaryPosition = 'top'; fix.detectChanges(); @@ -2055,14 +1967,12 @@ describe('IgxGrid - Summaries #grid', () => { summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 1); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '17', '17', '34', '17']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['2']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['2', 'Dec 18, 2007', 'Mar 19, 2016']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['2', 'Dec 18, 2007', 'Mar 19, 2016']); summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 3); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '17', '17', '34', '17']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['2']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['2', 'Dec 18, 2007', 'Mar 19, 2016']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['2', 'Dec 18, 2007', 'Mar 19, 2016']); }); @@ -2232,14 +2142,12 @@ describe('IgxGrid - Summaries #grid', () => { expect(GridSummaryFunctions.getAllVisibleSummariesLength(fix)).toEqual(2); let summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 2); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['1']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['1', 'Dec 18, 2007', 'Dec 18, 2007']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['1', 'Dec 18, 2007', 'Dec 18, 2007']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['1', '50', '50', '50', '50']); summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['1']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['1', 'Dec 18, 2007', 'Dec 18, 2007']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['1', 'Dec 18, 2007', 'Dec 18, 2007']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['1', '50', '50', '50', '50']); grid.clearFilter(); @@ -2345,21 +2253,17 @@ describe('IgxGrid - Summaries #grid', () => { let summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['9', '17', '847', '2,205', '245']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['9', '17', '847', '2,205', '245']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['9']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['9', 'Dec 18, 2007', 'Apr 3, 2019']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['9', '19', '50', '312', '34.667']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['9', 'Dec 18, 2007', 'Apr 3, 2019']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['9', '19', '50', '312', '34.667']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 5, ['Count'], ['9']); summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 4); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['3', '17', '17', '51', '17']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['3']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['3', 'Dec 18, 2007', 'Apr 3, 2019']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['3', 'Dec 18, 2007', 'Apr 3, 2019']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 5, ['Count'], ['3']); }); @@ -2384,7 +2288,7 @@ describe('IgxGrid - Summaries #grid', () => { fix.detectChanges(); let addRow = grid.gridAPI.get_row_by_index(2); - expect(addRow.addRowUI).toBeTrue(); + expect(addRow.addRowUI).toBe(true); let cell = grid.getCellByColumn(2, 'ParentID'); cell.update(newRow.ParentID); @@ -2403,14 +2307,13 @@ describe('IgxGrid - Summaries #grid', () => { fix.detectChanges(); addRow = grid.gridAPI.get_row_by_index(2); - expect(addRow.addRowUI).toBeFalse(); + expect(addRow.addRowUI).toBe(false); const summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 4); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['3', '17', '17', '51', '17']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['3']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['3', 'Dec 18, 2007', 'Apr 3, 2019']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['3', 'Dec 18, 2007', 'Apr 3, 2019']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 5, ['Count'], ['3']); }); @@ -2428,13 +2331,10 @@ describe('IgxGrid - Summaries #grid', () => { let summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['9', '1', '847', '2,189', '243.222']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['9', '1', '847', '2,189', '243.222']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['9']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['9', 'Dec 18, 2007', 'Apr 3, 2019']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['9', '19', '50', '312', '34.667']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['9', 'Dec 18, 2007', 'Apr 3, 2019']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['9', '19', '50', '312', '34.667']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 5, ['Count'], ['9']); summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 2); @@ -2509,17 +2409,14 @@ describe('IgxGrid - Summaries #grid', () => { let summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['8']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['8', 'Jul 19, 2009', 'Apr 3, 2019']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['8', '19', '44', '262', '32.75']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['8', 'Jul 19, 2009', 'Apr 3, 2019']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['8', '19', '44', '262', '32.75']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 5, ['Count'], ['8']); summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 3); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['2']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['2', 'Mar 19, 2016', 'Apr 3, 2019']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['2', 'Mar 19, 2016', 'Apr 3, 2019']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '19', '27', '46', '23']); }); @@ -2540,15 +2437,13 @@ describe('IgxGrid - Summaries #grid', () => { let summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['8']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['8', 'Jul 19, 2009', 'Apr 3, 2019']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['8', 'Jul 19, 2009', 'Apr 3, 2019']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 5, ['Count'], ['8']); summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 2); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['1']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Earliest', 'Latest'], ['1', 'Mar 19, 2016', 'Mar 19, 2016']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['1', 'Mar 19, 2016', 'Mar 19, 2016']); summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 6); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); @@ -2568,25 +2463,19 @@ describe('IgxGrid - Summaries #grid', () => { fix.detectChanges(); let summaryRow = GridSummaryFunctions.getAllVisibleSummariesSorted(fix)[0]; - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '12', '101', '113', '56.5']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '17', '17', '34', '17']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '12', '101', '113', '56.5']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '17', '17', '34', '17']); grid.updateCell(19, 101, 'ParentID'); fix.detectChanges(); summaryRow = GridSummaryFunctions.getAllVisibleSummariesSorted(fix)[0]; - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['1', '12', '12', '12', '12']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['1', '17', '17', '17', '17']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['1', '12', '12', '12', '12']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['1', '17', '17', '17', '17']); const secondSummaryRow = GridSummaryFunctions.getAllVisibleSummariesSorted(fix)[1]; - GridSummaryFunctions.verifyColumnSummaries(secondSummaryRow, 0, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '15', '101', '116', '58']); - GridSummaryFunctions.verifyColumnSummaries(secondSummaryRow, 1, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '19', '19', '38', '19']); + GridSummaryFunctions.verifyColumnSummaries(secondSummaryRow, 0, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '15', '101', '116', '58']); + GridSummaryFunctions.verifyColumnSummaries(secondSummaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '19', '19', '38', '19']); }); }); @@ -2600,12 +2489,10 @@ describe('IgxGrid - Summaries #grid', () => { const verifyBaseSummaries = (fixture) => { const summaryRow = GridSummaryFunctions.getRootSummaryRow(fixture); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['8', '17', '847', '2,188', '273.5']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['8', '17', '847', '2,188', '273.5']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['8']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['8', 'Dec 18, 2007', 'Dec 9, 2017']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['8', '25', '50', '293', '36.625']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['8', '25', '50', '293', '36.625']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 5, ['Count'], ['8']); }; @@ -2625,8 +2512,7 @@ describe('IgxGrid - Summaries #grid', () => { GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['3', '147', '147', '441', '147']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count'], ['3']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Earliest', 'Latest'], ['3', 'Jul 19, 2009', 'Sep 18, 2014']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['3', '29', '43', '103', '34.333']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['3', '29', '43', '103', '34.333']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 5, ['Count'], ['3']); }; diff --git a/projects/igniteui-angular/grids/grid/src/grid-toolbar.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-toolbar.spec.ts index 5c974efbd89..534c32c57fd 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-toolbar.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-toolbar.spec.ts @@ -7,6 +7,7 @@ import { By } from "@angular/platform-browser"; import { AbsoluteScrollStrategy, GlobalPositionStrategy } from 'igniteui-angular/core'; import { IgxCsvExporterService, IgxExcelExporterService, IgxGridToolbarActionsComponent, IgxGridToolbarAdvancedFilteringComponent, IgxGridToolbarComponent, IgxGridToolbarExporterComponent, IgxGridToolbarHidingComponent, IgxGridToolbarPinningComponent, IgxGridToolbarTitleComponent } from 'igniteui-angular/grids/core'; import { ExportUtilities } from 'igniteui-angular/grids/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const TOOLBAR_TAG = 'igx-grid-toolbar'; const TOOLBAR_TITLE_TAG = 'igx-grid-toolbar-title'; @@ -55,7 +56,7 @@ describe('IgxGrid - Grid Toolbar #grid - ', () => { fixture.detectChanges(); })); - it ('toolbar is rendered when declared between grid tags', () => { + it('toolbar is rendered when declared between grid tags', () => { expect($(TOOLBAR_TAG)).toBeInstanceOf(HTMLElement); }); @@ -177,8 +178,8 @@ describe('IgxGrid - Grid Toolbar #grid - ', () => { $('#excelEntry').click(); fixture.detectChanges(); - expect(instance.exporterAction.isExporting).toBeFalse(); - expect(instance.exporterAction.toolbar.showProgress).toBeFalse(); + expect(instance.exporterAction.isExporting).toBe(false); + expect(instance.exporterAction.toolbar.showProgress).toBe(false); }); it('toolbar exporter should include PDF option by default', () => { @@ -224,7 +225,7 @@ describe('IgxGrid - Grid Toolbar #grid - ', () => { exporterButton.click(); fixture.detectChanges(); - spyOn(instance.exporterAction, 'export'); + vi.spyOn(instance.exporterAction, 'export'); $('#pdfEntry').click(); fixture.detectChanges(); @@ -241,7 +242,7 @@ describe('IgxGrid - Grid Toolbar #grid - ', () => { exporterButton.click(); fixture.detectChanges(); - spyOn(ExportUtilities, 'saveBlobToFile'); + vi.spyOn(ExportUtilities, 'saveBlobToFile'); $('#pdfEntry').click(); fixture.detectChanges(); @@ -258,8 +259,8 @@ describe('IgxGrid - Grid Toolbar #grid - ', () => { $('#pdfEntry').click(); fixture.detectChanges(); - expect(instance.exporterAction.isExporting).toBeFalse(); - expect(instance.exporterAction.toolbar.showProgress).toBeFalse(); + expect(instance.exporterAction.isExporting).toBe(false); + expect(instance.exporterAction.toolbar.showProgress).toBe(false); }); it('Setting overlaySettings for each toolbar columns action', () => { @@ -295,7 +296,7 @@ describe('IgxGrid - Grid Toolbar #grid - ', () => { const pinningButton = GridFunctions.getColumnPinningButton(fixture); pinningButton.click(); tick(); - fixture.detectChanges() + fixture.detectChanges(); const element = fixture.debugElement.query(By.css('.igx-column-actions__columns')); expect(element.attributes.style).toBe('max-height: 10px;'); @@ -303,7 +304,7 @@ describe('IgxGrid - Grid Toolbar #grid - ', () => { })); it('should emit columnToggle event when a column is shown/hidden via the column hiding action', fakeAsync(() => { - const spy = spyOn(instance.hidingAction.columnToggle, 'emit'); + const spy = vi.spyOn(instance.hidingAction.columnToggle, 'emit'); const hidingUI = $(TOOLBAR_HIDING_TAG); const grid = fixture.componentInstance.grid; fixture.detectChanges(); @@ -318,11 +319,10 @@ describe('IgxGrid - Grid Toolbar #grid - ', () => { fixture.detectChanges(); expect(instance.hidingAction.columnToggle.emit).toHaveBeenCalledTimes(1); - expect(instance.hidingAction.columnToggle.emit).toHaveBeenCalledWith( - { column: grid.getColumnByName('ProductID'), checked: false }); + expect(instance.hidingAction.columnToggle.emit).toHaveBeenCalledWith({ column: grid.getColumnByName('ProductID'), checked: false }); // test after closing and reopening the hiding UI - spy.calls.reset(); + spy.mockClear(); hidingActionButton.click(); tick(); fixture.detectChanges(); @@ -335,8 +335,7 @@ describe('IgxGrid - Grid Toolbar #grid - ', () => { fixture.detectChanges(); expect(instance.hidingAction.columnToggle.emit).toHaveBeenCalledTimes(1); - expect(instance.hidingAction.columnToggle.emit).toHaveBeenCalledWith( - { column: grid.getColumnByName('ProductID'), checked: true }); + expect(instance.hidingAction.columnToggle.emit).toHaveBeenCalledWith({ column: grid.getColumnByName('ProductID'), checked: true }); })); }); }); @@ -410,19 +409,19 @@ export class ToolbarActionsComponent { @ViewChild(IgxGridComponent, { static: true }) public grid: IgxGridComponent; - @ViewChild('pinningAction', {static: true}) + @ViewChild('pinningAction', { static: true }) public pinningAction; - @ViewChild('hidingAction', {static: true}) + @ViewChild('hidingAction', { static: true }) public hidingAction; - @ViewChild('advancedFiltAction', {static: true}) + @ViewChild('advancedFiltAction', { static: true }) public advancedFiltAction; - @ViewChild('exporterAction', {static: true}) + @ViewChild('exporterAction', { static: true }) public exporterAction; - public data = []; + public data = []; public advancedFilteringTitle = 'Custom button text'; public exportCSV = true; public exportExcel = true; diff --git a/projects/igniteui-angular/grids/grid/src/grid-validation.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-validation.spec.ts index 2e6ab931322..bf4d96c8f53 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-validation.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-validation.spec.ts @@ -3,21 +3,17 @@ import { Validators } from '@angular/forms'; import { By } from '@angular/platform-browser'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators' +import { takeUntil } from 'rxjs/operators'; import { IgxInputDirective } from 'igniteui-angular/input-group'; import { IgxTooltipTargetDirective } from 'igniteui-angular/directives'; import { GridFunctions, GridSelectionFunctions } from '../../../test-utils/grid-functions.spec'; -import { - IgxGridCustomEditorsComponent, - IgxGridValidationTestBaseComponent, - IgxGridValidationTestCustomErrorComponent, - IgxTreeGridValidationTestComponent -} from '../../../test-utils/grid-validation-samples.spec'; +import { IgxGridCustomEditorsComponent, IgxGridValidationTestBaseComponent, IgxGridValidationTestCustomErrorComponent, IgxTreeGridValidationTestComponent } from '../../../test-utils/grid-validation-samples.spec'; import { UIInteractions } from '../../../test-utils/ui-interactions.spec'; import { IGridFormGroupCreatedEventArgs } from 'igniteui-angular/grids/core'; import { IgxGridComponent } from './grid.component'; import { AutoPositionStrategy, HorizontalAlignment, IgxOverlayService, VerticalAlignment } from 'igniteui-angular/core'; import { IgxTreeGridComponent } from 'igniteui-angular/grids/tree-grid'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; describe('IgxGrid - Validation #grid', () => { @@ -118,7 +114,7 @@ describe('IgxGrid - Validation #grid', () => { cell = grid.gridAPI.get_cell_by_visible_index(1, 1); //the name should be correct email GridFunctions.verifyCellValid(cell, false); - expect(cell.formControl.errors.email).toBeTrue(); + expect(cell.formControl.errors.email).toBe(true); cell.editMode = true; cell.update('m@in.com'); @@ -222,13 +218,13 @@ describe('IgxGrid - Validation #grid', () => { cell.errorTooltip.first.close(); tick(); fixture.detectChanges(); - expect(cell.errorTooltip.first.collapsed).toBeTrue(); + expect(cell.errorTooltip.first.collapsed).toBe(true); const element = fixture.debugElement.query(By.directive(IgxTooltipTargetDirective)).nativeElement; element.dispatchEvent(new MouseEvent('pointerenter')); flush(); fixture.detectChanges(); - expect(cell.errorTooltip.first.collapsed).toBeFalse(); + expect(cell.errorTooltip.first.collapsed).toBe(false); })); it('should allow preventing edit mode for cell/row to end by canceling the related event if isValid event argument is false', () => { @@ -264,7 +260,7 @@ describe('IgxGrid - Validation #grid', () => { it('should trigger the validationStatusChange event on grid when validation status changes', () => { const grid = fixture.componentInstance.grid as IgxGridComponent; - spyOn(grid.validationStatusChange, "emit").and.callThrough(); + vi.spyOn(grid.validationStatusChange, "emit"); let cell = grid.gridAPI.get_cell_by_visible_index(1, 1); UIInteractions.simulateDoubleClickAndSelectEvent(cell.element); diff --git a/projects/igniteui-angular/grids/grid/src/grid.component.spec.ts b/projects/igniteui-angular/grids/grid/src/grid.component.spec.ts index 3a09da1118b..39efc98776a 100644 --- a/projects/igniteui-angular/grids/grid/src/grid.component.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid.component.spec.ts @@ -18,6 +18,7 @@ import { AsyncPipe } from '@angular/common'; import { setElementSize, ymd } from '../../../test-utils/helper-utils.spec'; import { FilteringExpressionsTree, FilteringLogic, getComponentSize, GridColumnDataType, IgxNumberFilteringOperand, IgxStringFilteringOperand, ISortingExpression, ɵSize, SortingDirection } from 'igniteui-angular/core'; import { IgxPaginatorComponent, IgxPaginatorContentDirective } from 'igniteui-angular/paginator'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; describe('IgxGrid Component Tests #grid', () => { const MIN_COL_WIDTH = '136px'; @@ -38,7 +39,7 @@ describe('IgxGrid Component Tests #grid', () => { IgxGridEmptyMessage100PercentComponent ] }) - .compileComponents(); + .compileComponents(); })); it('should initialize a grid with columns from markup', () => { @@ -48,9 +49,9 @@ describe('IgxGrid Component Tests #grid', () => { const grid = fix.componentInstance.instance; const domGrid = fix.debugElement.query(By.css('igx-grid')).nativeElement; - expect(grid).toBeDefined('Grid initializing through markup failed'); - expect(grid.columnList.length).toEqual(2, 'Invalid number of columns initialized'); - expect(grid.rowList.length).toEqual(3, 'Invalid number of rows initialized'); + expect(grid, 'Grid initializing through markup failed').toBeDefined(); + expect(grid.columnList.length, 'Invalid number of columns initialized').toEqual(2); + expect(grid.rowList.length, 'Invalid number of rows initialized').toEqual(3); expect(grid.id).toContain('igx-grid-'); expect(domGrid.id).toContain('igx-grid-'); @@ -76,15 +77,13 @@ describe('IgxGrid Component Tests #grid', () => { const grid = fix.componentInstance.grid; - expect(grid).toBeDefined('Grid initializing through autoGenerate failed'); - expect(grid.columns.length).toEqual(4, 'Invalid number of columns initialized'); - expect(grid.rowList.length).toEqual(1, 'Invalid number of rows initialized'); - expect(grid.columns[0].dataType).toEqual(GridColumnDataType.Number, 'Invalid dataType set on column'); - expect(grid.columns.find((col) => col.index === 1).dataType) - .toEqual(GridColumnDataType.String, 'Invalid dataType set on column'); - expect(grid.columns.find((col) => col.index === 2).dataType) - .toEqual(GridColumnDataType.Boolean, 'Invalid dataType set on column'); - expect(grid.columns[grid.columns.length - 1].dataType).toEqual(GridColumnDataType.Date, 'Invalid dataType set on column'); + expect(grid, 'Grid initializing through autoGenerate failed').toBeDefined(); + expect(grid.columns.length, 'Invalid number of columns initialized').toEqual(4); + expect(grid.rowList.length, 'Invalid number of rows initialized').toEqual(1); + expect(grid.columns[0].dataType, 'Invalid dataType set on column').toEqual(GridColumnDataType.Number); + expect(grid.columns.find((col) => col.index === 1).dataType, 'Invalid dataType set on column').toEqual(GridColumnDataType.String); + expect(grid.columns.find((col) => col.index === 2).dataType, 'Invalid dataType set on column').toEqual(GridColumnDataType.Boolean); + expect(grid.columns[grid.columns.length - 1].dataType, 'Invalid dataType set on column').toEqual(GridColumnDataType.Date); expect(fix.componentInstance.columnEventCount).toEqual(4); }); @@ -115,7 +114,7 @@ describe('IgxGrid Component Tests #grid', () => { fix.detectChanges(); const grid = fix.componentInstance.grid; - expect(grid.columns.map(col => col.field)).toEqual(['Number', 'Boolean'], 'Invalid columns after exclusion initialized'); + expect(grid.columns.map(col => col.field), 'Invalid columns after exclusion initialized').toEqual(['Number', 'Boolean']); }); it('should initialize a grid and allow changing columns runtime with @for', () => { @@ -250,9 +249,7 @@ describe('IgxGrid Component Tests #grid', () => { const gridBody = fix.debugElement.query(By.css(TBODY_CLASS)); const gridHeader = fix.debugElement.query(By.css(THEAD_CLASS)); - expect(window.getComputedStyle(gridBody.children[0].nativeElement).width).toEqual( - window.getComputedStyle(gridHeader.children[0].nativeElement).width - ); + expect(window.getComputedStyle(gridBody.children[0].nativeElement).width).toEqual(window.getComputedStyle(gridHeader.children[0].nativeElement).width); expect(grid.rowList.length).toBeGreaterThan(0); }); @@ -270,16 +267,20 @@ describe('IgxGrid Component Tests #grid', () => { const summaryItemHeight = fixture.debugElement.query(By.css('.igx-grid__tfoot')) .query(By.css('.igx-grid-summary__item')).nativeElement; const summaryRowHeight = fixture.debugElement.query(By.css('.igx-grid__tfoot')).nativeElement; + // TODO: vitest-migration: Verify this matches strict array content (multiset equality). Vitest's arrayContaining is a subset check. - expect(grid.nativeElement.classList).toEqual(jasmine.arrayWithExactContents(['igx-grid', 'custom'])); + expect(grid.nativeElement.classList).toHaveLength(2); + + + expect(grid.nativeElement.classList).toEqual(expect.arrayContaining(['igx-grid', 'custom'])); expect(getComponentSize(grid.nativeElement)).toEqual('3'); expect(grid.defaultRowHeight).toBe(50); expect(headerHight.offsetHeight).toBe(grid.defaultRowHeight); expect(rowHeight.offsetHeight).toBe(51); expect(summaryItemHeight.offsetHeight).toBe(grid.defaultSummaryHeight - 1); expect(summaryRowHeight.offsetHeight).toBe(grid.defaultSummaryHeight); - setElementSize(grid.nativeElement, ɵSize.Medium) + setElementSize(grid.nativeElement, ɵSize.Medium); grid.summaryRowHeight = null; fixture.detectChanges(); await wait(32); // needed because of the throttleTime on the resize observer @@ -291,7 +292,7 @@ describe('IgxGrid Component Tests #grid', () => { expect(rowHeight.offsetHeight).toBe(41); expect(summaryItemHeight.offsetHeight).toBe(grid.defaultSummaryHeight - 1); expect(summaryRowHeight.offsetHeight).toBe(grid.defaultSummaryHeight); - setElementSize(grid.nativeElement, ɵSize.Small) + setElementSize(grid.nativeElement, ɵSize.Small); grid.summaryRowHeight = undefined; fixture.detectChanges(); await wait(32); // needed because of the throttleTime on the resize observer @@ -305,7 +306,7 @@ describe('IgxGrid Component Tests #grid', () => { expect(summaryRowHeight.offsetHeight).toBe(grid.defaultSummaryHeight); }); - it ('checks if attributes are correctly assigned when grid has or does not have data', fakeAsync( () => { + it('checks if attributes are correctly assigned when grid has or does not have data', fakeAsync(() => { const fixture = TestBed.createComponent(IgxGridTestComponent); const grid = fixture.componentInstance.grid; @@ -317,7 +318,7 @@ describe('IgxGrid Component Tests #grid', () => { expect(container.getAttribute('role')).toBe(null); //Filter grid so no results are available and grid is empty - grid.filter('index','111',IgxStringFilteringOperand.instance().condition('contains'),true); + grid.filter('index', '111', IgxStringFilteringOperand.instance().condition('contains'), true); grid.markForCheck(); fixture.detectChanges(); expect(container.getAttribute('role')).toMatch('row'); @@ -675,18 +676,15 @@ describe('IgxGrid Component Tests #grid', () => { }); it('should throw a warning when primaryKey is set to a non-existing data field', () => { - jasmine.getEnv().allowRespy(true); - const warnSpy = spyOn(console, 'warn'); + const warnSpy = vi.spyOn(console, 'warn'); const fixture = TestBed.createComponent(IgxGridTestComponent); const grid = fixture.componentInstance.grid; grid.primaryKey = 'testField'; fixture.detectChanges(); expect(console.warn).toHaveBeenCalledTimes(1); - expect(console.warn).toHaveBeenCalledWith( - `Field "${grid.primaryKey}" is not defined in the data. Set \`primaryKey\` to a valid field.` - ); - warnSpy.calls.reset(); + expect(console.warn).toHaveBeenCalledWith(`Field "${grid.primaryKey}" is not defined in the data. Set \`primaryKey\` to a valid field.`); + warnSpy.mockClear(); // update data to include the 'testField' fixture.componentInstance.data = [{ index: 1, value: 1, testField: 1 }]; @@ -700,10 +698,7 @@ describe('IgxGrid Component Tests #grid', () => { fixture.detectChanges(); expect(console.warn).toHaveBeenCalledTimes(1); - expect(console.warn).toHaveBeenCalledWith( - `Field "${grid.primaryKey}" is not defined in the data. Set \`primaryKey\` to a valid field.` - ); - jasmine.getEnv().allowRespy(false); + expect(console.warn).toHaveBeenCalledWith(`Field "${grid.primaryKey}" is not defined in the data. Set \`primaryKey\` to a valid field.`); }); }); @@ -715,7 +710,7 @@ describe('IgxGrid Component Tests #grid', () => { IgxGridTestComponent ] }) - .compileComponents(); + .compileComponents(); })); it('should change chunk size for every record after enlarging the grid and the horizontal dirs are scrambled', async () => { @@ -725,10 +720,7 @@ describe('IgxGrid Component Tests #grid', () => { } fix.componentInstance.columns[0].width = '400px'; fix.componentInstance.columns[1].width = '400px'; - fix.componentInstance.columns.push( - { field: 'desc', header: 'desc', dataType: 'number', width: '400px', hasSummary: false }, - { field: 'detail', header: 'detail', dataType: 'number', width: '400px', hasSummary: false } - ); + fix.componentInstance.columns.push({ field: 'desc', header: 'desc', dataType: 'number', width: '400px', hasSummary: false }, { field: 'detail', header: 'detail', dataType: 'number', width: '400px', hasSummary: false }); fix.detectChanges(); fix.componentInstance.grid.verticalScrollContainer.getScroll().scrollTop = 100; await wait(100); @@ -752,10 +744,7 @@ describe('IgxGrid Component Tests #grid', () => { } fix.componentInstance.columns[0].width = '400px'; fix.componentInstance.columns[1].width = '400px'; - fix.componentInstance.columns.push( - { field: 'desc', header: 'desc', dataType: 'number', width: '400px', hasSummary: false }, - { field: 'detail', header: 'detail', dataType: 'number', width: '400px', hasSummary: false } - ); + fix.componentInstance.columns.push({ field: 'desc', header: 'desc', dataType: 'number', width: '400px', hasSummary: false }, { field: 'detail', header: 'detail', dataType: 'number', width: '400px', hasSummary: false }); fix.detectChanges(); fix.componentInstance.grid.groupBy({ fieldName: 'value', dir: SortingDirection.Asc }); fix.detectChanges(); @@ -775,10 +764,7 @@ describe('IgxGrid Component Tests #grid', () => { } fix.componentInstance.columns[0].width = '400px'; fix.componentInstance.columns[1].width = '400px'; - fix.componentInstance.columns.push( - { field: 'desc', header: 'desc', dataType: 'number', width: '400px', hasSummary: false }, - { field: 'detail', header: 'detail', dataType: 'number', width: '400px', hasSummary: false } - ); + fix.componentInstance.columns.push({ field: 'desc', header: 'desc', dataType: 'number', width: '400px', hasSummary: false }, { field: 'detail', header: 'detail', dataType: 'number', width: '400px', hasSummary: false }); fix.detectChanges(); const grid = fix.componentInstance.grid; grid.headerContainer.dc.instance._scrollInertia.smoothingDuration = 0; @@ -809,10 +795,7 @@ describe('IgxGrid Component Tests #grid', () => { } fix.componentInstance.columns[0].width = '400px'; fix.componentInstance.columns[1].width = '400px'; - fix.componentInstance.columns.push( - { field: 'desc', header: 'desc', dataType: 'number', width: '400px', hasSummary: false }, - { field: 'detail', header: 'detail', dataType: 'number', width: '400px', hasSummary: false } - ); + fix.componentInstance.columns.push({ field: 'desc', header: 'desc', dataType: 'number', width: '400px', hasSummary: false }, { field: 'detail', header: 'detail', dataType: 'number', width: '400px', hasSummary: false }); fix.detectChanges(); const grid = fix.componentInstance.grid; grid.rowList.first.virtDirRow.dc.instance._scrollInertia.smoothingDuration = 0; @@ -852,7 +835,7 @@ describe('IgxGrid Component Tests #grid', () => { IgxGridFixedContainerHeightComponent ] }) - .compileComponents(); + .compileComponents(); })); it('should init columns with width >= 136px when 5 rows and 5 columns are rendered', () => { @@ -935,8 +918,7 @@ describe('IgxGrid Component Tests #grid', () => { const actualGridWidth = grid.nativeElement.clientWidth; const expectedDefWidth = Math.max(Math.floor((actualGridWidth - parseInt(grid.columnList.get(0).width, 10) - - parseInt(grid.columnList.get(4).width, 10)) / 3), - parseInt(MIN_COL_WIDTH, 10)); + parseInt(grid.columnList.get(4).width, 10)) / 3), parseInt(MIN_COL_WIDTH, 10)); expect(parseInt(grid.columnWidth, 10)).toEqual(expectedDefWidth); expect(parseInt(grid.columnList.get(1).width, 10)).toEqual(expectedDefWidth); @@ -972,8 +954,7 @@ describe('IgxGrid Component Tests #grid', () => { const actualGridWidth = grid.nativeElement.clientWidth; const expectedDefWidth = Math.max(Math.floor((actualGridWidth - parseInt(grid.columnList.get(0).width, 10) - - parseInt(grid.columnList.get(4).width, 10)) / 3), - parseInt(MIN_COL_WIDTH, 10)); + parseInt(grid.columnList.get(4).width, 10)) / 3), parseInt(MIN_COL_WIDTH, 10)); expect(parseInt(grid.columnWidth, 10)).toEqual(expectedDefWidth); expect(parseInt(grid.columnList.get(1).width, 10)).toEqual(expectedDefWidth); @@ -1010,8 +991,7 @@ describe('IgxGrid Component Tests #grid', () => { const expectedDefWidth = Math.max(Math.floor((actualGridWidth - parseInt(grid.columnList.get(0).width, 10) - - parseInt(grid.columnList.get(4).width, 10)) / 3), - parseInt(MIN_COL_WIDTH, 10)); + parseInt(grid.columnList.get(4).width, 10)) / 3), parseInt(MIN_COL_WIDTH, 10)); expect(parseInt(grid.columnWidth, 10)).toEqual(expectedDefWidth); expect(parseInt(grid.columnList.get(1).width, 10)).toEqual(expectedDefWidth); @@ -1253,7 +1233,7 @@ describe('IgxGrid Component Tests #grid', () => { fix.detectChanges(); expect(fix.componentInstance.grid.rowList.length).toEqual(10); - setElementSize(fix.componentInstance.grid.nativeElement, ɵSize.Small) + setElementSize(fix.componentInstance.grid.nativeElement, ɵSize.Small); fix.detectChanges(); await wait(32); // needed because of the throttleTime on the resize observer fix.detectChanges(); @@ -1503,28 +1483,28 @@ describe('IgxGrid Component Tests #grid', () => { })); it('should render correct columns if after scrolling right container size changes so that all columns become visible.', async () => { - const fix = TestBed.createComponent(IgxGridDefaultRenderingComponent); - fix.detectChanges(); - const grid = fix.componentInstance.grid; - grid.width = '500px'; - fix.componentInstance.initColumnsRows(5, 5); - fix.detectChanges(); - await wait(16); - fix.detectChanges(); - expect(fix.componentInstance.isHorizontalScrollbarVisible()).toBe(true); - const scrollbar = grid.headerContainer.getScroll(); - scrollbar.scrollLeft = 10000; - grid.width = '1500px'; + const fix = TestBed.createComponent(IgxGridDefaultRenderingComponent); + fix.detectChanges(); + const grid = fix.componentInstance.grid; + grid.width = '500px'; + fix.componentInstance.initColumnsRows(5, 5); + fix.detectChanges(); + await wait(16); + fix.detectChanges(); + expect(fix.componentInstance.isHorizontalScrollbarVisible()).toBe(true); + const scrollbar = grid.headerContainer.getScroll(); + scrollbar.scrollLeft = 10000; + grid.width = '1500px'; - fix.detectChanges(); - await wait(100); - expect(fix.componentInstance.isHorizontalScrollbarVisible()).toBe(false); - const headers = fix.debugElement.queryAll(By.css(COLUMN_HEADER_CLASS)); - expect(headers.length).toEqual(5); - for (let i = 0; i < headers.length; i++) { - expect(headers[i].context.column.field).toEqual(grid.columnList.get(i).field); - } - }); + fix.detectChanges(); + await wait(100); + expect(fix.componentInstance.isHorizontalScrollbarVisible()).toBe(false); + const headers = fix.debugElement.queryAll(By.css(COLUMN_HEADER_CLASS)); + expect(headers.length).toEqual(5); + for (let i = 0; i < headers.length; i++) { + expect(headers[i].context.column.field).toEqual(grid.columnList.get(i).field); + } + }); it('Should render date and number values based on default formatting', fakeAsync(() => { const fixture = TestBed.createComponent(IgxGridFormattingComponent); @@ -1721,7 +1701,7 @@ describe('IgxGrid Component Tests #grid', () => { expect((rows[0].cells.toArray()[4] as any).element.nativeElement.textContent).toBe(expectedValue); expectedValue = `${ymd('2005-01-15').getUTCDate()}. Januar 2008`; expect((rows[1].cells.toArray()[4] as any).element.nativeElement.textContent).toBe(expectedValue); - expectedValue =`${ymd('2005-11-20').getUTCDate()}. November 2010`; + expectedValue = `${ymd('2005-11-20').getUTCDate()}. November 2010`; expect((rows[2].cells.toArray()[4] as any).element.nativeElement.textContent).toBe(expectedValue); // verify summaries formatting @@ -1882,7 +1862,7 @@ describe('IgxGrid Component Tests #grid', () => { const cell = fix.debugElement.queryAll(By.css('igx-grid-cell'))[i]; const headerStyle = document.defaultView.getComputedStyle(header.nativeElement); const paddingsAndBorders = parseFloat(headerStyle.paddingLeft) + parseFloat(headerStyle.paddingRight) + - parseFloat(headerStyle.borderRightWidth); + parseFloat(headerStyle.borderRightWidth); expect(header.nativeElement.offsetWidth).toEqual(Math.max(cell.nativeElement.offsetWidth, paddingsAndBorders)); expect(Number.isInteger(header.nativeElement.offsetWidth)).toBe(true); } @@ -1914,7 +1894,7 @@ describe('IgxGrid Component Tests #grid', () => { fix.componentInstance.initColumnsRows(5, 4); fix.detectChanges(); - expect(grid.calcWidth).toBe(136*4); + expect(grid.calcWidth).toBe(136 * 4); expect(grid.columns[0].calcWidth).toBe(136); expect(grid.columns[1].calcWidth).toBe(136); }); @@ -1952,10 +1932,10 @@ describe('IgxGrid Component Tests #grid', () => { fix.detectChanges(); fix.componentInstance.gridContainerHidden = false; - await wait(17) - fix.detectChanges() + await wait(17); + fix.detectChanges(); - const calcWidth = parseInt(grid.columnList.first.calcWidth, 10) + const calcWidth = parseInt(grid.columnList.first.calcWidth, 10); expect(calcWidth).not.toBe(80); }); @@ -1963,7 +1943,7 @@ describe('IgxGrid Component Tests #grid', () => { it('should correctly autosize column headers inside column groups.', async () => { const fix = TestBed.createComponent(IgxGridColumnHeaderInGroupAutoSizeComponent); const grid = fix.componentInstance.grid; - grid.data = [{field1: "Test"}]; + grid.data = [{ field1: "Test" }]; //waiting for requestAnimationFrame to finish fix.detectChanges(); @@ -2050,7 +2030,7 @@ describe('IgxGrid Component Tests #grid', () => { describe('min/max in px', () => { - it('in column with no width should not go outside bounds.', async() => { + it('in column with no width should not go outside bounds.', async () => { const fix = TestBed.createComponent(IgxGridDefaultRenderingComponent); // 4 cols fix.componentInstance.initColumnsRows(5, 4); @@ -2099,7 +2079,7 @@ describe('IgxGrid Component Tests #grid', () => { expect(col4.calcPixelWidth).toBe((grid.calcWidth - col1.calcPixelWidth) / 3); }); - it('in column with pixel width should not go outside bounds.', async() => { + it('in column with pixel width should not go outside bounds.', async () => { const fix = TestBed.createComponent(IgxGridDefaultRenderingComponent); // 4 cols fix.componentInstance.initColumnsRows(5, 4); @@ -2133,7 +2113,7 @@ describe('IgxGrid Component Tests #grid', () => { expect(col1.calcPixelWidth).toBe(500); }); - it('in column with auto width should not go outside bounds.', async() => { + it('in column with auto width should not go outside bounds.', async () => { const fix = TestBed.createComponent(IgxGridDefaultRenderingComponent); // 4 cols fix.componentInstance.initColumnsRows(5, 4); @@ -2247,7 +2227,7 @@ describe('IgxGrid Component Tests #grid', () => { expect(col4.calcPixelWidth).toBe((grid.calcWidth - col1.calcPixelWidth) / 3); }); - it('in column with pixel width should not go outside bounds.', async() => { + it('in column with pixel width should not go outside bounds.', async () => { const fix = TestBed.createComponent(IgxGridDefaultRenderingComponent); // 4 cols fix.componentInstance.initColumnsRows(5, 4); @@ -2289,7 +2269,7 @@ describe('IgxGrid Component Tests #grid', () => { expect(col4.calcPixelWidth).toBe((grid.calcWidth - col1.calcPixelWidth) / 3); }); - it('in column with auto width should not go outside bounds.', async() => { + it('in column with auto width should not go outside bounds.', async () => { const fix = TestBed.createComponent(IgxGridDefaultRenderingComponent); // 4 cols fix.componentInstance.initColumnsRows(5, 4); @@ -2326,7 +2306,7 @@ describe('IgxGrid Component Tests #grid', () => { // first column takes new min expect(col1.calcPixelWidth).toBe(grid.calcWidth * 0.5); }); - }) + }); }); @@ -2472,7 +2452,7 @@ describe('IgxGrid Component Tests #grid', () => { grid.width = '300px'; fix.detectChanges(); - spyOn(grid.gridScroll, 'emit').and.callThrough(); + vi.spyOn(grid.gridScroll, 'emit'); let verticalScrollEvent; let horizontalScrollEvent; grid.verticalScrollContainer.getScroll().addEventListener('scroll', (evt) => verticalScrollEvent = evt); @@ -2514,7 +2494,7 @@ describe('IgxGrid Component Tests #grid', () => { ignoreCase: false }); fix.detectChanges(); - spyOn(fix.componentInstance.grid.rowClick, 'emit').and.callThrough(); + vi.spyOn(fix.componentInstance.grid.rowClick, 'emit'); const event = new Event('click'); const grow = grid.rowList.get(0); const row = grid.rowList.get(1); @@ -2539,22 +2519,22 @@ describe('IgxGrid Component Tests #grid', () => { const grid = fix.componentInstance.grid; grid.columnList.forEach(c => c.width = '100px'); fix.detectChanges(); - const spy = spyOn(grid.contextMenu, 'emit').and.callThrough(); + const spy = vi.spyOn(grid.contextMenu, 'emit'); const event = new Event('contextmenu', { bubbles: true }); const row = grid.rowList.get(0); const cell = row.cells.get(0); cell.nativeElement.dispatchEvent(event); fix.detectChanges(); expect(grid.contextMenu.emit).toHaveBeenCalledTimes(1); - expect(grid.contextMenu.emit).toHaveBeenCalledWith(jasmine.objectContaining({ - cell: jasmine.anything() + expect(grid.contextMenu.emit).toHaveBeenCalledWith(expect.objectContaining({ + cell: expect.anything() })); - spy.calls.reset(); + spy.mockClear(); row.nativeElement.dispatchEvent(event); fix.detectChanges(); expect(grid.contextMenu.emit).toHaveBeenCalledTimes(1); - expect(grid.contextMenu.emit).toHaveBeenCalledWith(jasmine.objectContaining({ - row: jasmine.anything() + expect(grid.contextMenu.emit).toHaveBeenCalledWith(expect.objectContaining({ + row: expect.anything() })); }); @@ -2656,25 +2636,25 @@ describe('IgxGrid Component Tests #grid', () => { expect(secondRow.viewIndex).toBe(1); // select group row - expect(firstRow.selected).toBeFalse(); - expect(secondRow.selected).toBeFalse(); + expect(firstRow.selected).toBe(false); + expect(secondRow.selected).toBe(false); firstRow.children.forEach(row => { - expect(row.selected).toBeFalse(); + expect(row.selected).toBe(false); }); firstRow.selected = !firstRow.selected; - expect(firstRow.selected).toBeTrue(); - expect(secondRow.selected).toBeTrue(); + expect(firstRow.selected).toBe(true); + expect(secondRow.selected).toBe(true); firstRow.children.forEach(row => { - expect(row.selected).toBeTrue(); + expect(row.selected).toBe(true); }); firstRow.selected = !firstRow.selected; - expect(firstRow.selected).toBeFalse(); - expect(secondRow.selected).toBeFalse(); + expect(firstRow.selected).toBe(false); + expect(secondRow.selected).toBe(false); firstRow.children.forEach(row => { - expect(row.selected).toBeFalse(); + expect(row.selected).toBe(false); }); (firstRow as IgxGroupByRow).toggle(); @@ -2709,7 +2689,7 @@ describe('IgxGrid Component Tests #grid', () => { expect(secondRow.key).toBeUndefined(); expect(secondRow.data).toBeUndefined(); expect(secondRow.pinned).toBeUndefined(); - expect(secondRow.selected).toBeFalse(); + expect(secondRow.selected).toBe(false); expect(thirdRow.key).toBeTruthy(); expect(thirdRow.data).toBeTruthy(); expect(thirdRow.pinned).toBe(false); @@ -2933,7 +2913,7 @@ describe('IgxGrid Component Tests #grid', () => { await wait(100); fix.detectChanges(); - grid.navigateTo(0, grid.columnList.length - 1); + grid.navigateTo(0, grid.columnList.length - 1); await wait(100); fix.detectChanges(); grid.navigateTo(grid.data.length - 1); @@ -3040,10 +3020,8 @@ describe('IgxGrid Component Tests #grid', () => { it('should render the grid in a certain amount of time', async () => { const fix = TestBed.createComponent(IgxGridPerformanceComponent); fix.detectChanges(); - expect(fix.componentInstance.delta) - .withContext('Rendering took: ' + fix.componentInstance.delta + - 'ms but should have taken at most: ' + MAX_RAW_RENDER + 'ms') - .toBeLessThan(MAX_RAW_RENDER); + expect(fix.componentInstance.delta, 'Rendering took: ' + fix.componentInstance.delta + + 'ms but should have taken at most: ' + MAX_RAW_RENDER + 'ms').toBeLessThan(MAX_RAW_RENDER); }); it('should render grouped grid in a certain amount of time', async () => { @@ -3053,13 +3031,11 @@ describe('IgxGrid Component Tests #grid', () => { dir: SortingDirection.Asc }); fix.detectChanges(); - expect(fix.componentInstance.delta) - .withContext('Rendering took: ' + fix.componentInstance.delta + - 'ms but should have taken at most: ' + MAX_GROUPED_RENDER + 'ms') - .toBeLessThan(MAX_GROUPED_RENDER); + expect(fix.componentInstance.delta, 'Rendering took: ' + fix.componentInstance.delta + + 'ms but should have taken at most: ' + MAX_GROUPED_RENDER + 'ms').toBeLessThan(MAX_GROUPED_RENDER); }); - xit('should scroll (optimized delta) the grid vertically in a certain amount of time', async (done) => { + it.skip('should scroll (optimized delta) the grid vertically in a certain amount of time', async (done) => { const fix = TestBed.createComponent(IgxGridPerformanceComponent); fix.detectChanges(); await wait(16); @@ -3080,9 +3056,7 @@ describe('IgxGrid Component Tests #grid', () => { } if (ready) { const delta = new Date().getTime() - startTime; - expect(delta) - .withContext('Scrolling took: ' + delta + 'ms but should have taken at most: ' + MAX_VER_SCROLL_O + 'ms') - .toBeLessThan(MAX_VER_SCROLL_O); + expect(delta, 'Scrolling took: ' + delta + 'ms but should have taken at most: ' + MAX_VER_SCROLL_O + 'ms').toBeLessThan(MAX_VER_SCROLL_O); observer.disconnect(); done(); } @@ -3095,7 +3069,7 @@ describe('IgxGrid Component Tests #grid', () => { fix.detectChanges(); }); - xit('should scroll (unoptimized delta) the grid vertically in a certain amount of time', async (done) => { + it.skip('should scroll (unoptimized delta) the grid vertically in a certain amount of time', async (done) => { const fix = TestBed.createComponent(IgxGridPerformanceComponent); fix.detectChanges(); await wait(16); @@ -3106,13 +3080,10 @@ describe('IgxGrid Component Tests #grid', () => { attributeFilter: ['ng-reflect-value'] }; const callback = (mutationsList) => { - const cellMutated = mutationsList.filter(mutation => - mutation.oldValue === '60' && mutation.target.attributes['ng-reflect-value'].nodeValue === '84').length === 1; + const cellMutated = mutationsList.filter(mutation => mutation.oldValue === '60' && mutation.target.attributes['ng-reflect-value'].nodeValue === '84').length === 1; if (cellMutated) { const delta = new Date().getTime() - startTime; - expect(delta) - .withContext('Scrolling took: ' + delta + 'ms but should have taken at most: ' + MAX_VER_SCROLL_U + 'ms') - .toBeLessThan(MAX_VER_SCROLL_U); + expect(delta, 'Scrolling took: ' + delta + 'ms but should have taken at most: ' + MAX_VER_SCROLL_U + 'ms').toBeLessThan(MAX_VER_SCROLL_U); observer.disconnect(); done(); } @@ -3124,7 +3095,7 @@ describe('IgxGrid Component Tests #grid', () => { fix.detectChanges(); }); - xit('should scroll (optimized delta) the grid horizontally in a certain amount of time', async (done) => { + it.skip('should scroll (optimized delta) the grid horizontally in a certain amount of time', async (done) => { const fix = TestBed.createComponent(IgxGridPerformanceComponent); fix.detectChanges(); await wait(16); @@ -3135,13 +3106,10 @@ describe('IgxGrid Component Tests #grid', () => { attributeFilter: ['ng-reflect-value'] }; const callback = mutationsList => { - const cellMutated = mutationsList.filter(mutation => - mutation.oldValue === '1' && mutation.target.attributes['ng-reflect-value'].nodeValue === '22').length === 1; + const cellMutated = mutationsList.filter(mutation => mutation.oldValue === '1' && mutation.target.attributes['ng-reflect-value'].nodeValue === '22').length === 1; if (cellMutated) { const delta = new Date().getTime() - startTime; - expect(delta) - .withContext('Scrolling took: ' + delta + 'ms but should have taken at most: ' + MAX_HOR_SCROLL_O + 'ms') - .toBeLessThan(MAX_HOR_SCROLL_O); + expect(delta, 'Scrolling took: ' + delta + 'ms but should have taken at most: ' + MAX_HOR_SCROLL_O + 'ms').toBeLessThan(MAX_HOR_SCROLL_O); observer.disconnect(); done(); } @@ -3153,7 +3121,7 @@ describe('IgxGrid Component Tests #grid', () => { fix.detectChanges(); }); - xit('should scroll (unoptimized delta) the grid horizontally in a certain amount of time', async (done) => { + it.skip('should scroll (unoptimized delta) the grid horizontally in a certain amount of time', async (done) => { const fix = TestBed.createComponent(IgxGridPerformanceComponent); fix.detectChanges(); await wait(16); @@ -3164,13 +3132,10 @@ describe('IgxGrid Component Tests #grid', () => { attributeFilter: ['ng-reflect-value'] }; const callback = mutationsList => { - const cellMutated = mutationsList.filter(mutation => - mutation.oldValue === '60' && mutation.target.attributes['ng-reflect-value'].nodeValue === '8').length === 1; + const cellMutated = mutationsList.filter(mutation => mutation.oldValue === '60' && mutation.target.attributes['ng-reflect-value'].nodeValue === '8').length === 1; if (cellMutated) { const delta = new Date().getTime() - startTime; - expect(delta) - .withContext('Scrolling took: ' + delta + 'ms but should have taken at most: ' + MAX_HOR_SCROLL_U + 'ms') - .toBeLessThan(MAX_HOR_SCROLL_U); + expect(delta, 'Scrolling took: ' + delta + 'ms but should have taken at most: ' + MAX_HOR_SCROLL_U + 'ms').toBeLessThan(MAX_HOR_SCROLL_U); observer.disconnect(); done(); } @@ -3182,7 +3147,7 @@ describe('IgxGrid Component Tests #grid', () => { fix.detectChanges(); }); - xit('should focus a cell in a certain amount of time', async (done) => { + it.skip('should focus a cell in a certain amount of time', async (done) => { const fix = TestBed.createComponent(IgxGridPerformanceComponent); fix.detectChanges(); await wait(16); @@ -3193,13 +3158,10 @@ describe('IgxGrid Component Tests #grid', () => { attributeFilter: ['aria-selected'] }; const callback = mutationsList => { - const cellMutated = mutationsList.filter(mutation => - mutation.oldValue === 'false' && mutation.target.attributes['aria-selected'].nodeValue === 'true').length === 1; + const cellMutated = mutationsList.filter(mutation => mutation.oldValue === 'false' && mutation.target.attributes['aria-selected'].nodeValue === 'true').length === 1; if (cellMutated) { const delta = new Date().getTime() - startTime; - expect(delta) - .withContext('Focusing took: ' + delta + 'ms but should have taken at most: ' + MAX_FOCUS + 'ms') - .toBeLessThan(MAX_FOCUS); + expect(delta, 'Focusing took: ' + delta + 'ms but should have taken at most: ' + MAX_FOCUS + 'ms').toBeLessThan(MAX_FOCUS); observer.disconnect(); done(); } @@ -3259,7 +3221,8 @@ describe('IgxGrid Component Tests #grid', () => { export class IgxGridTestComponent { public cdr = inject(ChangeDetectorRef); - @ViewChild('grid', { static: true }) public grid: IgxGridComponent; + @ViewChild('grid', { static: true }) + public grid: IgxGridComponent; public data: any[] = [{ index: 1, value: 1 }]; public columns = [ { field: 'index', header: 'index', dataType: 'number', width: null, hasSummary: false }, @@ -3346,7 +3309,8 @@ export class IgxGridDefaultRenderingComponent { public initColumnsRows(rowsNumber: number, columnsNumber: number): void { this.columns = []; this.data = []; - let i; let j: number; + let i; + let j: number; for (i = 0; i < columnsNumber; i++) { this.columns.push({ key: 'col' + i, @@ -3418,7 +3382,6 @@ export class IgxGridColumnHeaderAutoSizeComponent { public grid: IgxGridComponent; public gridContainerHidden = true; - } @Component({ @@ -3493,7 +3456,8 @@ export class IgxGridColumnHiddenPercentageWidthComponent extends IgxGridDefaultR imports: [IgxGridComponent, IgxGridFooterComponent] }) export class IgxGridWithCustomFooterComponent extends IgxGridTestComponent { - @ViewChild(IgxGridComponent, { static: true }) public override grid: IgxGridComponent; + @ViewChild(IgxGridComponent, { static: true }) + public override grid: IgxGridComponent; public override data = SampleTestData.foodProductData(); } @Component({ @@ -3732,7 +3696,8 @@ export class IgxGridRemoteOnDemandComponent { imports: [IgxGridComponent, IgxColumnComponent] }) export class IgxGridFormattingComponent extends BasicGridComponent { - @ViewChild(IgxGridComponent, { static: true }) public override grid: IgxGridComponent; + @ViewChild(IgxGridComponent, { static: true }) + public override grid: IgxGridComponent; public override data = SampleTestData.foodProductData(); public width = '600px'; public height = '400px'; @@ -3912,7 +3877,8 @@ export class IgxGridWithCustomPaginationTemplateComponent { }) export class IgxGridPerformanceComponent implements AfterViewInit, OnInit { - @ViewChild('grid', { read: IgxGridComponent, static: true }) public grid: IgxGridComponent; + @ViewChild('grid', { read: IgxGridComponent, static: true }) + public grid: IgxGridComponent; public columns = []; public data = []; @@ -3930,7 +3896,8 @@ export class IgxGridPerformanceComponent implements AfterViewInit, OnInit { } public ngOnInit() { - const cols = []; const d = []; + const cols = []; + const d = []; for (let i = 0; i < 30; i++) { cols.push({ field: 'field' + i, width: '100px', hasSummary: false }); } @@ -3963,5 +3930,6 @@ export class IgxGridPerformanceComponent implements AfterViewInit, OnInit { imports: [IgxGridComponent, IgxColumnComponent, IgxPaginatorComponent] }) export class IgxGridNoDataComponent { - @ViewChild(IgxGridComponent, { static: true }) public grid: IgxGridComponent; + @ViewChild(IgxGridComponent, { static: true }) + public grid: IgxGridComponent; } diff --git a/projects/igniteui-angular/grids/grid/src/grid.crud.spec.ts b/projects/igniteui-angular/grids/grid/src/grid.crud.spec.ts index a1e0ee794bf..afdcb797add 100644 --- a/projects/igniteui-angular/grids/grid/src/grid.crud.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid.crud.spec.ts @@ -5,6 +5,7 @@ import { IgxGridComponent } from './grid.component'; import { wait } from '../../../test-utils/ui-interactions.spec'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IGridEditEventArgs } from 'igniteui-angular/grids/core'; +import { describe, it, expect, beforeEach } from 'vitest'; const CELL_CSS_CLASS = '.igx-grid__td'; @@ -34,7 +35,7 @@ describe('IgxGrid - CRUD operations #grid', () => { expect(grid.rowList.length).toEqual(expectedLength); for (let i = 0; i < 10; i++) { - grid.addRow({ index: i, value: i}); + grid.addRow({ index: i, value: i }); } fix.detectChanges(); @@ -47,7 +48,7 @@ describe('IgxGrid - CRUD operations #grid', () => { // Add to the data array without changing the reference // with manual detection for (let i = 0; i < 10; i++) { - fix.componentInstance.data.push({ index: i, value: i}); + fix.componentInstance.data.push({ index: i, value: i }); } grid.cdr.markForCheck(); @@ -60,7 +61,7 @@ describe('IgxGrid - CRUD operations #grid', () => { // without manual detection for (let i = 0; i < 10; i++) { - fix.componentInstance.data.push({ index: i, value: i}); + fix.componentInstance.data.push({ index: i, value: i }); } fix.componentInstance.data = fix.componentInstance.data.slice(); fix.detectChanges(); @@ -79,7 +80,7 @@ describe('IgxGrid - CRUD operations #grid', () => { expect(grid.rowList.length).toEqual(expectedLength); for (let i = 0; i < 10; i++) { - grid.addRow({ index: i, value: i}); + grid.addRow({ index: i, value: i }); } fix.detectChanges(); @@ -114,7 +115,7 @@ describe('IgxGrid - CRUD operations #grid', () => { expect(grid.rowList.length).toEqual(0); for (let i = 0; i < 10; i++) { - fix.componentInstance.data.push({ index: i, value: i}); + fix.componentInstance.data.push({ index: i, value: i }); } fix.componentInstance.data = fix.componentInstance.data.slice(); fix.detectChanges(); @@ -186,7 +187,7 @@ describe('IgxGrid - CRUD operations #grid', () => { it('should update row through row object when PK is defined', () => { let firstRow = grid.getRowByKey(1); - firstRow.update({ index: 31, value: 51}); + firstRow.update({ index: 31, value: 51 }); fix.detectChanges(); firstRow = grid.getRowByKey(31); @@ -202,7 +203,7 @@ describe('IgxGrid - CRUD operations #grid', () => { fix.detectChanges(); expect(grid.primaryKey).toBeNull(); let firstRow = grid.getRowByIndex(0); - firstRow.update({ index: 100, value: 99}); + firstRow.update({ index: 100, value: 99 }); fix.detectChanges(); firstRow = grid.getRowByIndex(0); @@ -277,15 +278,15 @@ describe('IgxGrid - CRUD operations #grid', () => { await wait(50); fix.detectChanges(); const rowID = 9; - const sampleData = [{ index: 2, value: 2}, - { index: 3, value: 3}, { index: 4, value: 4}, { index: 5, value: 5}, - { index: 6, value: 6}, { index: 7, value: 7}, { index: 8, value: 8}, - { index: 9, value: 9}, { index: 10, value: 10}, { index: 11, value: 11}]; + const sampleData = [{ index: 2, value: 2 }, + { index: 3, value: 3 }, { index: 4, value: 4 }, { index: 5, value: 5 }, + { index: 6, value: 6 }, { index: 7, value: 7 }, { index: 8, value: 8 }, + { index: 9, value: 9 }, { index: 10, value: 10 }, { index: 11, value: 11 }]; sampleData.forEach((record) => grid.addRow(record)); fix.detectChanges(); expect(grid.data.length).toBe(11); - grid.updateRow({ index: 97, value: 87}, rowID); + grid.updateRow({ index: 97, value: 87 }, rowID); fix.detectChanges(); expect(grid.data.map((record) => record[grid.primaryKey]).indexOf(rowID)).toBe(-1); expect(grid.data[grid.data.map((record) => record[grid.primaryKey]).indexOf(97)]).toBeDefined(); @@ -296,10 +297,10 @@ describe('IgxGrid - CRUD operations #grid', () => { await wait(50); fix.detectChanges(); const rowID = 9; - const sampleData = [{ index: 2, value: 2}, - { index: 3, value: 3}, { index: 4, value: 4}, { index: 5, value: 5}, - { index: 6, value: 6}, { index: 7, value: 7}, { index: 8, value: 8}, - { index: 9, value: 9}, { index: 10, value: 10}, { index: 11, value: 11}]; + const sampleData = [{ index: 2, value: 2 }, + { index: 3, value: 3 }, { index: 4, value: 4 }, { index: 5, value: 5 }, + { index: 6, value: 6 }, { index: 7, value: 7 }, { index: 8, value: 8 }, + { index: 9, value: 9 }, { index: 10, value: 10 }, { index: 11, value: 11 }]; sampleData.forEach((record) => grid.addRow(record)); fix.detectChanges(); expect(grid.data.length).toBe(11); @@ -316,10 +317,10 @@ describe('IgxGrid - CRUD operations #grid', () => { fix.detectChanges(); const rowID = 9; const columnName = 'value'; - const sampleData = [{ index: 2, value: 2}, - { index: 3, value: 3}, { index: 4, value: 4}, { index: 5, value: 5}, - { index: 6, value: 6}, { index: 7, value: 7}, { index: 8, value: 8}, - { index: 9, value: 9}, { index: 10, value: 10}, { index: 11, value: 11}]; + const sampleData = [{ index: 2, value: 2 }, + { index: 3, value: 3 }, { index: 4, value: 4 }, { index: 5, value: 5 }, + { index: 6, value: 6 }, { index: 7, value: 7 }, { index: 8, value: 8 }, + { index: 9, value: 9 }, { index: 10, value: 10 }, { index: 11, value: 11 }]; sampleData.forEach((record) => grid.addRow(record)); fix.detectChanges(); @@ -329,7 +330,7 @@ describe('IgxGrid - CRUD operations #grid', () => { expect(cell.row.key).toBe(rowID); expect(cell.column.field).toBe(columnName); - grid.updateCell( 97, rowID, columnName); + grid.updateCell(97, rowID, columnName); fix.detectChanges(); const row = grid.data[grid.data.map((record) => record[grid.primaryKey]).indexOf(rowID)]; expect(row).toBeDefined(); @@ -356,7 +357,7 @@ export class DefaultCRUDGridComponent { public instance: IgxGridComponent; public data = [ - { index: 1, value: 1} + { index: 1, value: 1 } ]; public editDone(event: IGridEditEventArgs) { diff --git a/projects/igniteui-angular/grids/grid/src/grid.groupby.spec.ts b/projects/igniteui-angular/grids/grid/src/grid.groupby.spec.ts index 0087c32f4db..c38dc05709e 100644 --- a/projects/igniteui-angular/grids/grid/src/grid.groupby.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid.groupby.spec.ts @@ -1,5 +1,5 @@ -import { Component, ViewChild, TemplateRef, QueryList } from '@angular/core'; -import { formatNumber } from '@angular/common' +import { Component, ViewChild, TemplateRef, QueryList } from '@angular/core'; +import { formatNumber } from '@angular/common'; import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; @@ -20,6 +20,7 @@ import { DefaultSortingStrategy, IGroupingExpression, IgxGrouping, IgxStringFilt import { IgxChipComponent } from 'igniteui-angular/chips'; import { IgxPaginatorComponent } from 'igniteui-angular/paginator'; import { IgxCheckboxComponent } from 'igniteui-angular/checkbox'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxGrid - GroupBy #grid', () => { @@ -178,9 +179,7 @@ describe('IgxGrid - GroupBy #grid', () => { expect(actualValue2).toEqual(expectedValue2); expect(actualValue3).toEqual(expectedValue3); - checkGroups( - groupRows, - [null, fix.componentInstance.prevDay, fix.componentInstance.today, fix.componentInstance.nextDay]); + checkGroups(groupRows, [null, fix.componentInstance.prevDay, fix.componentInstance.today, fix.componentInstance.nextDay]); })); it('should only account for year, month and day when grouping by \'date\' dataType column', fakeAsync(() => { @@ -344,10 +343,8 @@ describe('IgxGrid - GroupBy #grid', () => { expect(groupRows.length).toEqual(13); expect(dataRows.length).toEqual(8); // verify groups - checkGroups(groupRows, - ['NetAdvantage', true, false, 'Ignite UI for JavaScript', true, - false, 'Ignite UI for Angular', false, null, '', true, null, true], - grid.groupingExpressions); + checkGroups(groupRows, ['NetAdvantage', true, false, 'Ignite UI for JavaScript', true, + false, 'Ignite UI for Angular', false, null, '', true, null, true], grid.groupingExpressions); // group by 3rd column @@ -363,10 +360,8 @@ describe('IgxGrid - GroupBy #grid', () => { expect(groupRows.length).toEqual(21); expect(dataRows.length).toEqual(8); // verify groups - checkGroups(groupRows, - ['NetAdvantage', true, 1000, false, 1000, 'Ignite UI for JavaScript', true, null, false, 254, 'Ignite UI for Angular', - false, 20, null, 1000, '', true, 100, null, true, 0], - grid.groupingExpressions); + checkGroups(groupRows, ['NetAdvantage', true, 1000, false, 1000, 'Ignite UI for JavaScript', true, null, false, 254, 'Ignite UI for Angular', + false, 20, null, 1000, '', true, 100, null, true, 0], grid.groupingExpressions); })); it('should allow grouping with a custom comparer', fakeAsync(() => { @@ -499,10 +494,8 @@ describe('IgxGrid - GroupBy #grid', () => { expect(groupRows.length).toEqual(13); expect(dataRows.length).toEqual(8); // verify groups - checkGroups(groupRows, - ['NetAdvantage', true, false, 'Ignite UI for JavaScript', true, - false, 'Ignite UI for Angular', false, null, '', true, null, true], - grid.groupingExpressions); + checkGroups(groupRows, ['NetAdvantage', true, false, 'Ignite UI for JavaScript', true, + false, 'Ignite UI for Angular', false, null, '', true, null, true], grid.groupingExpressions); // change order grid.groupingExpressions = [ @@ -522,10 +515,8 @@ describe('IgxGrid - GroupBy #grid', () => { expect(groupRows.length).toEqual(11); expect(dataRows.length).toEqual(8); // verify groups - checkGroups(groupRows, - [null, 'Ignite UI for Angular', false, 'Ignite UI for Angular', 'Ignite UI for JavaScript', - 'NetAdvantage', true, null, '', 'Ignite UI for JavaScript', 'NetAdvantage'], - grid.groupingExpressions); + checkGroups(groupRows, [null, 'Ignite UI for Angular', false, 'Ignite UI for Angular', 'Ignite UI for JavaScript', + 'NetAdvantage', true, null, '', 'Ignite UI for JavaScript', 'NetAdvantage'], grid.groupingExpressions); })); it('should group records correctly when ignoreCase is set to true.', fakeAsync(() => { @@ -547,9 +538,7 @@ describe('IgxGrid - GroupBy #grid', () => { expect(groupRows.length).toEqual(2); expect(dataRows.length).toEqual(5); // verify groups - checkGroups(groupRows, - ['Order Administrator', 'Owner'], - grid.groupingExpressions); + checkGroups(groupRows, ['Order Administrator', 'Owner'], grid.groupingExpressions); })); it('should allow setting expand/collapse state', fakeAsync(() => { @@ -716,7 +705,7 @@ describe('IgxGrid - GroupBy #grid', () => { let groupsRecordsLength; - spyOn(grid.groupingDone, 'emit').and.callThrough(); + vi.spyOn(grid.groupingDone, 'emit'); grid.groupingDone.subscribe(() => { groupsRecordsLength = grid.groupsRecords.length; }); @@ -806,7 +795,7 @@ describe('IgxGrid - GroupBy #grid', () => { fieldName: 'ReleaseDate', dir: SortingDirection.Asc, ignoreCase: false }); fix.detectChanges(); - spyOn(grid.groupingExpressionsChange, 'emit'); + vi.spyOn(grid.groupingExpressionsChange, 'emit'); fix.detectChanges(); const firstCellElem = grid.gridAPI.get_cell_by_index(2, 'Downloads'); UIInteractions.simulateClickAndSelectEvent(firstCellElem); @@ -825,7 +814,7 @@ describe('IgxGrid - GroupBy #grid', () => { fieldName: 'ReleaseDate', dir: SortingDirection.Asc, ignoreCase: false }); fix.detectChanges(); - spyOn(grid.groupingExpressionsChange, 'emit'); + vi.spyOn(grid.groupingExpressionsChange, 'emit'); fix.detectChanges(); const chips = grid.groupArea.chips; grid.groupArea.handleClick(chips.first.id); @@ -862,7 +851,7 @@ describe('IgxGrid - GroupBy #grid', () => { // no such column initially, so chip is disabled. const chips = grid.groupArea.chips; - expect(chips.first.disabled).toBeTrue(); + expect(chips.first.disabled).toBe(true); const newCols = [...fix.componentInstance.columns]; newCols.push({ field: "NewColumn", @@ -872,7 +861,7 @@ describe('IgxGrid - GroupBy #grid', () => { fix.detectChanges(); // column now exists and has groupable=true, so chip should be enabled. - expect(chips.first.disabled).toBeFalse(); + expect(chips.first.disabled).toBe(false); }); it('should update chip state on column groupable prop change', () => { @@ -888,12 +877,12 @@ describe('IgxGrid - GroupBy #grid', () => { // initially should not be disabled. const chips = grid.groupArea.chips; - expect(chips.first.disabled).toBeFalse(); + expect(chips.first.disabled).toBe(false); // should get disabled on groupable=false column.groupable = false; fix.detectChanges(); - expect(chips.first.disabled).toBeTrue(); + expect(chips.first.disabled).toBe(true); }); // GroupBy + Sorting integration @@ -927,40 +916,39 @@ describe('IgxGrid - GroupBy #grid', () => { })); - it('should apply the specified sort order on the group rows when already grouped column is sorted in asc/desc order.', - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.enableSorting = true; - fix.detectChanges(); - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - fix.detectChanges(); + it('should apply the specified sort order on the group rows when already grouped column is sorted in asc/desc order.', fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.enableSorting = true; + fix.detectChanges(); + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + fix.detectChanges(); - let groupRows = grid.groupsRowList.toArray(); - let dataRows = grid.dataRowList.toArray(); + let groupRows = grid.groupsRowList.toArray(); + let dataRows = grid.dataRowList.toArray(); - // verify groups and data rows count - expect(groupRows.length).toEqual(5); - expect(dataRows.length).toEqual(8); + // verify groups and data rows count + expect(groupRows.length).toEqual(5); + expect(dataRows.length).toEqual(8); - // verify group order - checkGroups(groupRows, ['NetAdvantage', 'Ignite UI for JavaScript', 'Ignite UI for Angular', '', null]); - grid.sort({ - fieldName: 'ProductName', - dir: SortingDirection.Asc, - ignoreCase: false - }); - fix.detectChanges(); + // verify group order + checkGroups(groupRows, ['NetAdvantage', 'Ignite UI for JavaScript', 'Ignite UI for Angular', '', null]); + grid.sort({ + fieldName: 'ProductName', + dir: SortingDirection.Asc, + ignoreCase: false + }); + fix.detectChanges(); - groupRows = grid.groupsRowList.toArray(); - dataRows = grid.dataRowList.toArray(); + groupRows = grid.groupsRowList.toArray(); + dataRows = grid.dataRowList.toArray(); - // verify group order - checkGroups(groupRows, [null, '', 'Ignite UI for Angular', 'Ignite UI for JavaScript', 'NetAdvantage']); + // verify group order + checkGroups(groupRows, [null, '', 'Ignite UI for Angular', 'Ignite UI for JavaScript', 'NetAdvantage']); - })); + })); it('should remove grouping when already grouped column is sorted with order "None" via the API.', fakeAsync(() => { const fix = TestBed.createComponent(DefaultGridComponent); @@ -1005,7 +993,7 @@ describe('IgxGrid - GroupBy #grid', () => { const headers = fix.debugElement.queryAll(By.css(COLUMN_HEADER_CLASS)); //header sort icon should not be displayed const sortIcon = headers[0].query(By.css('.sort-icon')); - expect(sortIcon).toBeNull() + expect(sortIcon).toBeNull(); })); it('should group by the specified field when grouping by an already sorted field.', fakeAsync(() => { @@ -1360,784 +1348,764 @@ describe('IgxGrid - GroupBy #grid', () => { } })); - it('group row checkboxes should be checked when selectAll API is called or when header checkbox is clicked.', - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.width = '1200px'; - tick(); - grid.columnWidth = '200px'; - tick(); - grid.rowSelection = GridSelectionMode.multiple; - tick(); - fix.detectChanges(); + it('group row checkboxes should be checked when selectAll API is called or when header checkbox is clicked.', fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.width = '1200px'; + tick(); + grid.columnWidth = '200px'; + tick(); + grid.rowSelection = GridSelectionMode.multiple; + tick(); + fix.detectChanges(); - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - tick(); - fix.detectChanges(); + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + tick(); + fix.detectChanges(); - grid.selectAllRows(); - fix.detectChanges(); + grid.selectAllRows(); + fix.detectChanges(); - expect(grid.selectedRows.length).toEqual(8); - const grRows = grid.groupsRowList.toArray(); - for (const grRow of grRows) { - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, true, false)); - } - let rows = fix.debugElement.queryAll(By.css('.igx-grid__tr--selected')); - for (const r of rows) { - expect(r.componentInstance instanceof IgxGridRowComponent).toBe(true); - } + expect(grid.selectedRows.length).toEqual(8); + const grRows = grid.groupsRowList.toArray(); + for (const grRow of grRows) { + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, true, false)); + } + let rows = fix.debugElement.queryAll(By.css('.igx-grid__tr--selected')); + for (const r of rows) { + expect(r.componentInstance instanceof IgxGridRowComponent).toBe(true); + } - grid.deselectAllRows(); - fix.detectChanges(); - expect(grid.selectedRows.length).toEqual(0); - for (const grRow of grRows) { - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, false)); - } + grid.deselectAllRows(); + fix.detectChanges(); + expect(grid.selectedRows.length).toEqual(0); + for (const grRow of grRows) { + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, false)); + } - GridSelectionFunctions.clickHeaderRowCheckbox(fix); - fix.detectChanges(); + GridSelectionFunctions.clickHeaderRowCheckbox(fix); + fix.detectChanges(); - expect(grid.selectedRows.length).toEqual(8); + expect(grid.selectedRows.length).toEqual(8); - rows = fix.debugElement.queryAll(By.css('.igx-grid__tr--selected')); - for (const grRow of grRows) { - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, true, false)); - } - for (const r of rows) { - expect(r.componentInstance instanceof IgxGridRowComponent).toBe(true); - } - })); + rows = fix.debugElement.queryAll(By.css('.igx-grid__tr--selected')); + for (const grRow of grRows) { + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, true, false)); + } + for (const r of rows) { + expect(r.componentInstance instanceof IgxGridRowComponent).toBe(true); + } + })); it(`should select all records for group by pressing space when selectionMode is multiple - and not all records within a group are selected and the groupRow is focused`, - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.width = '1200px'; - tick(); - grid.columnWidth = '200px'; - tick(); - grid.rowSelection = GridSelectionMode.multiple; - tick(); - fix.detectChanges(); + and not all records within a group are selected and the groupRow is focused`, fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.width = '1200px'; + tick(); + grid.columnWidth = '200px'; + tick(); + grid.rowSelection = GridSelectionMode.multiple; + tick(); + fix.detectChanges(); - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - tick(); - fix.detectChanges(); + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + tick(); + fix.detectChanges(); - const grRow = grid.groupsRowList.toArray()[0]; + const grRow = grid.groupsRowList.toArray()[0]; - grRow.activate(); - tick(); - fix.detectChanges(); + grRow.activate(); + tick(); + fix.detectChanges(); - const selectionSpy = spyOn(grid.rowSelectionChanging, 'emit'); - GridFunctions.simulateGridContentKeydown(fix, 'Space'); - fix.detectChanges(); + const selectionSpy = vi.spyOn(grid.rowSelectionChanging, 'emit'); + GridFunctions.simulateGridContentKeydown(fix, 'Space'); + fix.detectChanges(); - expect(selectionSpy).toHaveBeenCalledTimes(1); - const args = selectionSpy.calls.mostRecent().args[0]; - expect(args.added.length).toBe(2); - expect(grid.selectedRows.length).toEqual(2); + expect(selectionSpy).toHaveBeenCalledTimes(1); + const args = vi.mocked(selectionSpy).mock.lastCall[0]; + expect(args.added.length).toBe(2); + expect(grid.selectedRows.length).toEqual(2); - for (const key of grRow.groupRow.records) { - expect(GridSelectionFunctions.verifyRowSelected(grid.gridAPI.get_row_by_key(key))); - } + for (const key of grRow.groupRow.records) { + expect(GridSelectionFunctions.verifyRowSelected(grid.gridAPI.get_row_by_key(key))); + } - grid.deselectAllRows(); - fix.detectChanges(); + grid.deselectAllRows(); + fix.detectChanges(); - grid.selectRows([grRow.groupRow.records[0]]); - fix.detectChanges(); + grid.selectRows([grRow.groupRow.records[0]]); + fix.detectChanges(); - GridFunctions.simulateGridContentKeydown(fix, 'Space'); - fix.detectChanges(); + GridFunctions.simulateGridContentKeydown(fix, 'Space'); + fix.detectChanges(); - for (const key of grRow.groupRow.records) { - expect(GridSelectionFunctions.verifyRowSelected(grid.gridAPI.get_row_by_key(key))); - } - })); + for (const key of grRow.groupRow.records) { + expect(GridSelectionFunctions.verifyRowSelected(grid.gridAPI.get_row_by_key(key))); + } + })); - it('should not affect current row selection by pressing space when selectionMode is single and the groupRow is focused', - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.width = '1200px'; - tick(); - grid.columnWidth = '200px'; - tick(); - grid.rowSelection = GridSelectionMode.single; - tick(); - fix.detectChanges(); + it('should not affect current row selection by pressing space when selectionMode is single and the groupRow is focused', fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.width = '1200px'; + tick(); + grid.columnWidth = '200px'; + tick(); + grid.rowSelection = GridSelectionMode.single; + tick(); + fix.detectChanges(); - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - tick(); - fix.detectChanges(); + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + tick(); + fix.detectChanges(); - const selectionCount = grid.selectedRows.length; + const selectionCount = grid.selectedRows.length; - const grRow = grid.groupsRowList.toArray()[0]; + const grRow = grid.groupsRowList.toArray()[0]; - grRow.activate(); - tick(); - fix.detectChanges(); + grRow.activate(); + tick(); + fix.detectChanges(); - GridFunctions.simulateGridContentKeydown(fix, 'Space'); - fix.detectChanges(); + GridFunctions.simulateGridContentKeydown(fix, 'Space'); + fix.detectChanges(); - const newSelectionCount = grid.selectedRows.length; + const newSelectionCount = grid.selectedRows.length; - expect(selectionCount).toEqual(newSelectionCount); + expect(selectionCount).toEqual(newSelectionCount); - })); + })); it(`should deselect all records for group by pressing space when selectionMode is multiple - and all records within a group are selected and the groupRow is focused`, - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.width = '1200px'; - tick(); - grid.columnWidth = '200px'; - tick(); - grid.rowSelection = GridSelectionMode.multiple; - tick(); - fix.detectChanges(); - - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - tick(); - fix.detectChanges(); + and all records within a group are selected and the groupRow is focused`, fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.width = '1200px'; + tick(); + grid.columnWidth = '200px'; + tick(); + grid.rowSelection = GridSelectionMode.multiple; + tick(); + fix.detectChanges(); - const grRow = grid.groupsRowList.toArray()[0]; - grid.selectRows(grRow.groupRow.records); - tick(); - fix.detectChanges(); + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + tick(); + fix.detectChanges(); - grRow.activate(); - tick(); - fix.detectChanges(); + const grRow = grid.groupsRowList.toArray()[0]; + grid.selectRows(grRow.groupRow.records); + tick(); + fix.detectChanges(); - const selectionSpy = spyOn(grid.rowSelectionChanging, 'emit'); - GridFunctions.simulateGridContentKeydown(fix, 'Space'); - fix.detectChanges(); + grRow.activate(); + tick(); + fix.detectChanges(); - expect(selectionSpy).toHaveBeenCalledTimes(1); - const args = selectionSpy.calls.mostRecent().args[0]; - expect(args.removed.length).toBe(2); - expect(grid.selectedRows.length).toEqual(0); + const selectionSpy = vi.spyOn(grid.rowSelectionChanging, 'emit'); + GridFunctions.simulateGridContentKeydown(fix, 'Space'); + fix.detectChanges(); - for (const key of grRow.groupRow.records) { - expect(GridSelectionFunctions.verifyRowSelected(grid.gridAPI.get_row_by_key(key), false)); - } - })); + expect(selectionSpy).toHaveBeenCalledTimes(1); + const args = vi.mocked(selectionSpy).mock.lastCall[0]; + expect(args.removed.length).toBe(2); + expect(grid.selectedRows.length).toEqual(0); - it('row selectors for all rows in certain group should be checked/unchecked if the checkbox for this group row is checked/unchecked', - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.width = '1200px'; - tick(); - grid.columnWidth = '200px'; - tick(); - grid.rowSelection = GridSelectionMode.multiple; - tick(); - fix.detectChanges(); + for (const key of grRow.groupRow.records) { + expect(GridSelectionFunctions.verifyRowSelected(grid.gridAPI.get_row_by_key(key), false)); + } + })); - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - tick(); - fix.detectChanges(); + it('row selectors for all rows in certain group should be checked/unchecked if the checkbox for this group row is checked/unchecked', fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.width = '1200px'; + tick(); + grid.columnWidth = '200px'; + tick(); + grid.rowSelection = GridSelectionMode.multiple; + tick(); + fix.detectChanges(); - const grRow = grid.groupsRowList.toArray()[0]; + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + tick(); + fix.detectChanges(); - for (const key of grRow.groupRow.records) { - expect(GridSelectionFunctions.verifyRowSelected(grid.gridAPI.get_row_by_key(key), false, false)); - } + const grRow = grid.groupsRowList.toArray()[0]; - GridSelectionFunctions.clickRowCheckbox(grRow); - fix.detectChanges(); + for (const key of grRow.groupRow.records) { + expect(GridSelectionFunctions.verifyRowSelected(grid.gridAPI.get_row_by_key(key), false, false)); + } - for (const key of grRow.groupRow.records) { - expect(GridSelectionFunctions.verifyRowSelected(grid.gridAPI.get_row_by_key(key), true, true)); - } - })); + GridSelectionFunctions.clickRowCheckbox(grRow); + fix.detectChanges(); - it('the group row selector state should be checked if all records in the group are selected', - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.width = '1200px'; - tick(); - grid.columnWidth = '200px'; - tick(); - grid.rowSelection = GridSelectionMode.multiple; - tick(); - fix.detectChanges(); + for (const key of grRow.groupRow.records) { + expect(GridSelectionFunctions.verifyRowSelected(grid.gridAPI.get_row_by_key(key), true, true)); + } + })); - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - tick(); - fix.detectChanges(); + it('the group row selector state should be checked if all records in the group are selected', fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.width = '1200px'; + tick(); + grid.columnWidth = '200px'; + tick(); + grid.rowSelection = GridSelectionMode.multiple; + tick(); + fix.detectChanges(); - const grRow = grid.groupsRowList.toArray()[0]; + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + tick(); + fix.detectChanges(); - grid.selectRows(grRow.groupRow.records); - fix.detectChanges(); + const grRow = grid.groupsRowList.toArray()[0]; - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, true, false)); - })); + grid.selectRows(grRow.groupRow.records); + fix.detectChanges(); - it('the group row selector state should be undetermined if some of the records in the group but not all are selected', - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.width = '1200px'; - tick(); - grid.columnWidth = '200px'; - tick(); - grid.rowSelection = GridSelectionMode.multiple; - tick(); - fix.detectChanges(); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, true, false)); + })); - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - tick(); - fix.detectChanges(); + it('the group row selector state should be undetermined if some of the records in the group but not all are selected', fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.width = '1200px'; + tick(); + grid.columnWidth = '200px'; + tick(); + grid.rowSelection = GridSelectionMode.multiple; + tick(); + fix.detectChanges(); - const grRow = grid.groupsRowList.toArray()[0]; + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + tick(); + fix.detectChanges(); - grid.selectRows([grRow.groupRow.records[0]]); - fix.detectChanges(); + const grRow = grid.groupsRowList.toArray()[0]; - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, true)); - })); + grid.selectRows([grRow.groupRow.records[0]]); + fix.detectChanges(); - it('the group row selectors should be disabled if the grid selection mode is single', - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.width = '1200px'; - tick(); - grid.columnWidth = '200px'; - tick(); - grid.rowSelection = GridSelectionMode.single; - tick(); - fix.detectChanges(); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, true)); + })); - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - tick(); - fix.detectChanges(); + it('the group row selectors should be disabled if the grid selection mode is single', fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.width = '1200px'; + tick(); + grid.columnWidth = '200px'; + tick(); + grid.rowSelection = GridSelectionMode.single; + tick(); + fix.detectChanges(); - const grRow = grid.groupsRowList.toArray()[0]; + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + tick(); + fix.detectChanges(); - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, false, true)); - })); + const grRow = grid.groupsRowList.toArray()[0]; - it('group row checkbox should remain the right state after filter is applied, all rows are selected and filter is removed', - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.width = '1200px'; - tick(); - grid.columnWidth = '200px'; - tick(); - grid.rowSelection = GridSelectionMode.multiple; - tick(); - fix.detectChanges(); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, false, true)); + })); - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - tick(); - fix.detectChanges(); + it('group row checkbox should remain the right state after filter is applied, all rows are selected and filter is removed', fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.width = '1200px'; + tick(); + grid.columnWidth = '200px'; + tick(); + grid.rowSelection = GridSelectionMode.multiple; + tick(); + fix.detectChanges(); - grid.filter('ID', '2', IgxStringFilteringOperand.instance().condition('doesNotEqual'), true); - tick(); - fix.detectChanges(); + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + tick(); + fix.detectChanges(); - const grRow = grid.groupsRowList.toArray()[0]; + grid.filter('ID', '2', IgxStringFilteringOperand.instance().condition('doesNotEqual'), true); + tick(); + fix.detectChanges(); - GridSelectionFunctions.clickRowCheckbox(grRow); - fix.detectChanges(); + const grRow = grid.groupsRowList.toArray()[0]; - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, true, false)); + GridSelectionFunctions.clickRowCheckbox(grRow); + fix.detectChanges(); - grid.clearFilter(); - tick(); - fix.detectChanges(); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, true, false)); - expect(GridSelectionFunctions.verifyRowSelected(grid.gridAPI.get_row_by_key(grRow.groupRow.records[0]), false)); - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, true)); - })); + grid.clearFilter(); + tick(); + fix.detectChanges(); - it('group row checkbox should remain the right state after selecting all rows in group and adding a new row to that group', - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.width = '1200px'; - tick(); - grid.columnWidth = '200px'; - tick(); - grid.rowSelection = GridSelectionMode.multiple; - tick(); - fix.detectChanges(); + expect(GridSelectionFunctions.verifyRowSelected(grid.gridAPI.get_row_by_key(grRow.groupRow.records[0]), false)); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, true)); + })); - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - tick(); - fix.detectChanges(); + it('group row checkbox should remain the right state after selecting all rows in group and adding a new row to that group', fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.width = '1200px'; + tick(); + grid.columnWidth = '200px'; + tick(); + grid.rowSelection = GridSelectionMode.multiple; + tick(); + fix.detectChanges(); - const grRow = grid.groupsRowList.toArray()[0]; + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + tick(); + fix.detectChanges(); - GridSelectionFunctions.clickRowCheckbox(grRow); - fix.detectChanges(); + const grRow = grid.groupsRowList.toArray()[0]; - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, true, false)); + GridSelectionFunctions.clickRowCheckbox(grRow); + fix.detectChanges(); - const newRow = { ID: '9', ProductName: 'NetAdvantage', Downloads: '350' }; - grid.addRow(newRow); - fix.detectChanges(); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, true, false)); - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, true)); - })); + const newRow = { ID: '9', ProductName: 'NetAdvantage', Downloads: '350' }; + grid.addRow(newRow); + fix.detectChanges(); - it('should select/deselect all rows in group from API', - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.width = '1200px'; - tick(); - grid.columnWidth = '200px'; - tick(); - grid.rowSelection = GridSelectionMode.multiple; - tick(); - fix.detectChanges(); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, true)); + })); - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - tick(); - fix.detectChanges(); + it('should select/deselect all rows in group from API', fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.width = '1200px'; + tick(); + grid.columnWidth = '200px'; + tick(); + grid.rowSelection = GridSelectionMode.multiple; + tick(); + fix.detectChanges(); - const grRow = grid.groupsRowList.toArray()[0]; - const grRecord = grid.groupsRecords[0]; + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + tick(); + fix.detectChanges(); - grid.selectRowsInGroup(grRecord); - tick(); - fix.detectChanges(); + const grRow = grid.groupsRowList.toArray()[0]; + const grRecord = grid.groupsRecords[0]; - for (const key of grRow.groupRow.records) { - expect(GridSelectionFunctions.verifyRowSelected(grid.gridAPI.get_row_by_key(key))); - } + grid.selectRowsInGroup(grRecord); + tick(); + fix.detectChanges(); - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, true, false)); + for (const key of grRow.groupRow.records) { + expect(GridSelectionFunctions.verifyRowSelected(grid.gridAPI.get_row_by_key(key))); + } - grid.deselectRowsInGroup(grRecord); - tick(); - fix.detectChanges(); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, true, false)); - for (const key of grRow.groupRow.records) { - expect(GridSelectionFunctions.verifyRowSelected(grid.gridAPI.get_row_by_key(key), false)); - } + grid.deselectRowsInGroup(grRecord); + tick(); + fix.detectChanges(); - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, false)); - })); + for (const key of grRow.groupRow.records) { + expect(GridSelectionFunctions.verifyRowSelected(grid.gridAPI.get_row_by_key(key), false)); + } - it('should select/deselect all rows in group from API with PrimaryKey', - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - grid.primaryKey = 'ID'; - fix.detectChanges(); - fix.componentInstance.width = '1200px'; - tick(); - grid.columnWidth = '200px'; - tick(); - grid.rowSelection = GridSelectionMode.multiple; - tick(); - fix.detectChanges(); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, false)); + })); - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - tick(); - fix.detectChanges(); + it('should select/deselect all rows in group from API with PrimaryKey', fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + grid.primaryKey = 'ID'; + fix.detectChanges(); + fix.componentInstance.width = '1200px'; + tick(); + grid.columnWidth = '200px'; + tick(); + grid.rowSelection = GridSelectionMode.multiple; + tick(); + fix.detectChanges(); - const grRow = grid.groupsRowList.toArray()[0]; - const grRecord = grid.groupsRecords[0]; + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + tick(); + fix.detectChanges(); - grid.selectRowsInGroup(grRecord); - tick(); - fix.detectChanges(); + const grRow = grid.groupsRowList.toArray()[0]; + const grRecord = grid.groupsRecords[0]; - for (const key of grRow.groupRow.records) { - expect(GridSelectionFunctions.verifyRowSelected(grid.gridAPI.get_row_by_key(key.ID))); - } + grid.selectRowsInGroup(grRecord); + tick(); + fix.detectChanges(); - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, true, false)); + for (const key of grRow.groupRow.records) { + expect(GridSelectionFunctions.verifyRowSelected(grid.gridAPI.get_row_by_key(key.ID))); + } - grid.deselectRowsInGroup(grRecord); - tick(); - fix.detectChanges(); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, true, false)); - for (const key of grRow.groupRow.records) { - expect(GridSelectionFunctions.verifyRowSelected(grid.gridAPI.get_row_by_key(key.ID), false)); - } + grid.deselectRowsInGroup(grRecord); + tick(); + fix.detectChanges(); - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, false)); - })); + for (const key of grRow.groupRow.records) { + expect(GridSelectionFunctions.verifyRowSelected(grid.gridAPI.get_row_by_key(key.ID), false)); + } - it('ARIA support for groupby row selectors', - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.width = '1200px'; - tick(); - grid.columnWidth = '200px'; - tick(); - grid.rowSelection = GridSelectionMode.multiple; - tick(); - fix.detectChanges(); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, false)); + })); - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - tick(); - fix.detectChanges(); + it('ARIA support for groupby row selectors', fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.width = '1200px'; + tick(); + grid.columnWidth = '200px'; + tick(); + grid.rowSelection = GridSelectionMode.multiple; + tick(); + fix.detectChanges(); - const grRow = grid.groupsRowList.toArray()[0]; - const groupByRowCheckboxElement = GridSelectionFunctions.getRowCheckboxInput(grRow.element.nativeElement); + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + tick(); + fix.detectChanges(); - expect(groupByRowCheckboxElement.getAttribute('aria-checked')).toMatch('false'); - expect(groupByRowCheckboxElement.getAttribute('aria-label')) - .toMatch('Select all rows in the group with field name ProductName and value NetAdvantage'); + const grRow = grid.groupsRowList.toArray()[0]; + const groupByRowCheckboxElement = GridSelectionFunctions.getRowCheckboxInput(grRow.element.nativeElement); - grid.selectRows([grRow.groupRow.records[0]]); - fix.detectChanges(); + expect(groupByRowCheckboxElement.getAttribute('aria-checked')).toMatch('false'); + expect(groupByRowCheckboxElement.getAttribute('aria-label')) + .toMatch('Select all rows in the group with field name ProductName and value NetAdvantage'); - expect(groupByRowCheckboxElement.getAttribute('aria-checked')).toMatch('mixed'); - expect(groupByRowCheckboxElement.getAttribute('aria-label')) - .toMatch('Select all rows in the group with field name ProductName and value NetAdvantage'); + grid.selectRows([grRow.groupRow.records[0]]); + fix.detectChanges(); - grid.selectRows([grRow.groupRow.records[1]]); - fix.detectChanges(); + expect(groupByRowCheckboxElement.getAttribute('aria-checked')).toMatch('mixed'); + expect(groupByRowCheckboxElement.getAttribute('aria-label')) + .toMatch('Select all rows in the group with field name ProductName and value NetAdvantage'); - expect(groupByRowCheckboxElement.getAttribute('aria-checked')).toMatch('true'); - expect(groupByRowCheckboxElement.getAttribute('aria-label')) - .toMatch('Deselect all rows in the group with field name ProductName and value NetAdvantage'); + grid.selectRows([grRow.groupRow.records[1]]); + fix.detectChanges(); - })); + expect(groupByRowCheckboxElement.getAttribute('aria-checked')).toMatch('true'); + expect(groupByRowCheckboxElement.getAttribute('aria-label')) + .toMatch('Deselect all rows in the group with field name ProductName and value NetAdvantage'); + + })); it(`edit selected row so it goes to another group where all rows are selected as well. - The group row checkbox of the new group that the record becomes part of should be checked.`, - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.enableEditing = true; - fix.componentInstance.width = '1200px'; - grid.primaryKey = 'ID'; - grid.columnWidth = '200px'; - grid.rowSelection = GridSelectionMode.multiple; - fix.detectChanges(); + The group row checkbox of the new group that the record becomes part of should be checked.`, fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.enableEditing = true; + fix.componentInstance.width = '1200px'; + grid.primaryKey = 'ID'; + grid.columnWidth = '200px'; + grid.rowSelection = GridSelectionMode.multiple; + fix.detectChanges(); - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - fix.detectChanges(); + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + fix.detectChanges(); - const grRow = grid.groupsRowList.toArray()[0]; + const grRow = grid.groupsRowList.toArray()[0]; - grid.selectRowsInGroup(grRow.groupRow); - grid.selectRows([5]); - fix.detectChanges(); + grid.selectRowsInGroup(grRow.groupRow); + grid.selectRows([5]); + fix.detectChanges(); - const cell = grid.getCellByKey(5, 'ProductName'); - cell.column.editable = true; - fix.detectChanges(); + const cell = grid.getCellByKey(5, 'ProductName'); + cell.column.editable = true; + fix.detectChanges(); - UIInteractions.simulateDoubleClickAndSelectEvent(grid.gridAPI.get_cell_by_key(5, 'ProductName')); - fix.detectChanges(); + UIInteractions.simulateDoubleClickAndSelectEvent(grid.gridAPI.get_cell_by_key(5, 'ProductName')); + fix.detectChanges(); - expect(cell.editMode).toBe(true); - expect(grid.selectedRows.length).toEqual(3); + expect(cell.editMode).toBe(true); + expect(grid.selectedRows.length).toEqual(3); - const editCellDom = fix.debugElement.query(By.css('.igx-grid__td--editing')); - const input = editCellDom.query(By.css('input')); + const editCellDom = fix.debugElement.query(By.css('.igx-grid__td--editing')); + const input = editCellDom.query(By.css('input')); - clickAndSendInputElementValue(input, 'NetAdvantage', fix); - GridFunctions.simulateGridContentKeydown(fix, 'Enter'); - fix.detectChanges(); + clickAndSendInputElementValue(input, 'NetAdvantage', fix); + GridFunctions.simulateGridContentKeydown(fix, 'Enter'); + fix.detectChanges(); - expect(grRow.groupRow.records.length).toEqual(3); - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, true, false)); - })); + expect(grRow.groupRow.records.length).toEqual(3); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, true, false)); + })); it(`edit selected row so it goes to another group where all rows are not selected. - The group row checkbox of the new group that the record becomes part of should be in indeterminate state.`, - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.enableEditing = true; - fix.componentInstance.width = '1200px'; - grid.primaryKey = 'ID'; - grid.columnWidth = '200px'; - grid.rowSelection = GridSelectionMode.multiple; - fix.detectChanges(); + The group row checkbox of the new group that the record becomes part of should be in indeterminate state.`, fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.enableEditing = true; + fix.componentInstance.width = '1200px'; + grid.primaryKey = 'ID'; + grid.columnWidth = '200px'; + grid.rowSelection = GridSelectionMode.multiple; + fix.detectChanges(); - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - fix.detectChanges(); + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + fix.detectChanges(); - const grRow = grid.groupsRowList.toArray()[0]; + const grRow = grid.groupsRowList.toArray()[0]; - grid.selectRows([5]); - fix.detectChanges(); + grid.selectRows([5]); + fix.detectChanges(); - const cell = grid.getCellByKey(5, 'ProductName'); - cell.column.editable = true; - fix.detectChanges(); + const cell = grid.getCellByKey(5, 'ProductName'); + cell.column.editable = true; + fix.detectChanges(); - UIInteractions.simulateDoubleClickAndSelectEvent(grid.gridAPI.get_cell_by_key(5, 'ProductName')); - fix.detectChanges(); + UIInteractions.simulateDoubleClickAndSelectEvent(grid.gridAPI.get_cell_by_key(5, 'ProductName')); + fix.detectChanges(); - expect(cell.editMode).toBe(true); - expect(grid.selectedRows.length).toEqual(1); + expect(cell.editMode).toBe(true); + expect(grid.selectedRows.length).toEqual(1); - const editCellDom = fix.debugElement.query(By.css('.igx-grid__td--editing')); - const input = editCellDom.query(By.css('input')); + const editCellDom = fix.debugElement.query(By.css('.igx-grid__td--editing')); + const input = editCellDom.query(By.css('input')); - clickAndSendInputElementValue(input, 'NetAdvantage', fix); - GridFunctions.simulateGridContentKeydown(fix, 'Enter'); - fix.detectChanges(); + clickAndSendInputElementValue(input, 'NetAdvantage', fix); + GridFunctions.simulateGridContentKeydown(fix, 'Enter'); + fix.detectChanges(); - expect(grRow.groupRow.records.length).toEqual(3); - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, true)); - })); + expect(grRow.groupRow.records.length).toEqual(3); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, true)); + })); it(`edit non-selected row so it goes to another group where all rows are selected. - The group row checkbox of the new group that the record becomes part of should become in indeterminate state.`, - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.enableEditing = true; - fix.componentInstance.width = '1200px'; - grid.primaryKey = 'ID'; - grid.columnWidth = '200px'; - grid.rowSelection = GridSelectionMode.multiple; - fix.detectChanges(); + The group row checkbox of the new group that the record becomes part of should become in indeterminate state.`, fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.enableEditing = true; + fix.componentInstance.width = '1200px'; + grid.primaryKey = 'ID'; + grid.columnWidth = '200px'; + grid.rowSelection = GridSelectionMode.multiple; + fix.detectChanges(); - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - fix.detectChanges(); + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + fix.detectChanges(); - const grRow = grid.groupsRowList.toArray()[0]; + const grRow = grid.groupsRowList.toArray()[0]; - grid.selectRowsInGroup(grRow.groupRow); - fix.detectChanges(); + grid.selectRowsInGroup(grRow.groupRow); + fix.detectChanges(); - const cell = grid.getCellByKey(5, 'ProductName'); - cell.column.editable = true; - fix.detectChanges(); + const cell = grid.getCellByKey(5, 'ProductName'); + cell.column.editable = true; + fix.detectChanges(); - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, true, false)); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, true, false)); - UIInteractions.simulateDoubleClickAndSelectEvent(grid.gridAPI.get_cell_by_key(5, 'ProductName')); - fix.detectChanges(); + UIInteractions.simulateDoubleClickAndSelectEvent(grid.gridAPI.get_cell_by_key(5, 'ProductName')); + fix.detectChanges(); - expect(cell.editMode).toBe(true); + expect(cell.editMode).toBe(true); - const editCellDom = fix.debugElement.query(By.css('.igx-grid__td--editing')); - const input = editCellDom.query(By.css('input')); + const editCellDom = fix.debugElement.query(By.css('.igx-grid__td--editing')); + const input = editCellDom.query(By.css('input')); - clickAndSendInputElementValue(input, 'NetAdvantage', fix); - GridFunctions.simulateGridContentKeydown(fix, 'Enter'); - fix.detectChanges(); + clickAndSendInputElementValue(input, 'NetAdvantage', fix); + GridFunctions.simulateGridContentKeydown(fix, 'Enter'); + fix.detectChanges(); - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, true)); - })); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, true)); + })); it(`edit the only non-selected row in a group so that it moves to another group - and check whether the current group row checkbox becomes checked.`, - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.enableEditing = true; - fix.componentInstance.width = '1200px'; - grid.primaryKey = 'ID'; - grid.columnWidth = '200px'; - grid.rowSelection = GridSelectionMode.multiple; - fix.detectChanges(); + and check whether the current group row checkbox becomes checked.`, fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.enableEditing = true; + fix.componentInstance.width = '1200px'; + grid.primaryKey = 'ID'; + grid.columnWidth = '200px'; + grid.rowSelection = GridSelectionMode.multiple; + fix.detectChanges(); - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - fix.detectChanges(); + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + fix.detectChanges(); - const grRow = grid.groupsRowList.toArray()[0]; + const grRow = grid.groupsRowList.toArray()[0]; - grid.selectRows([2]); - fix.detectChanges(); + grid.selectRows([2]); + fix.detectChanges(); - const cell = grid.getCellByKey(8, 'ProductName'); - cell.column.editable = true; - fix.detectChanges(); + const cell = grid.getCellByKey(8, 'ProductName'); + cell.column.editable = true; + fix.detectChanges(); - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, true)); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, true)); - UIInteractions.simulateDoubleClickAndSelectEvent(grid.gridAPI.get_cell_by_key(8, 'ProductName')); - fix.detectChanges(); + UIInteractions.simulateDoubleClickAndSelectEvent(grid.gridAPI.get_cell_by_key(8, 'ProductName')); + fix.detectChanges(); - expect(cell.editMode).toBe(true); + expect(cell.editMode).toBe(true); - const editCellDom = fix.debugElement.query(By.css('.igx-grid__td--editing')); - const input = editCellDom.query(By.css('input')); + const editCellDom = fix.debugElement.query(By.css('.igx-grid__td--editing')); + const input = editCellDom.query(By.css('input')); - clickAndSendInputElementValue(input, 'Ignite UI for Angular', fix); - GridFunctions.simulateGridContentKeydown(fix, 'Enter'); - fix.detectChanges(); + clickAndSendInputElementValue(input, 'Ignite UI for Angular', fix); + GridFunctions.simulateGridContentKeydown(fix, 'Enter'); + fix.detectChanges(); - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, true, false)); - })); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, true, false)); + })); it(`edit the only selected row in a group so that it moves to another group - and check whether the current group row checkbox becomes unchecked.`, - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.enableEditing = true; - fix.componentInstance.width = '1200px'; - grid.primaryKey = 'ID'; - grid.columnWidth = '200px'; - grid.rowSelection = GridSelectionMode.multiple; - fix.detectChanges(); - - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - fix.detectChanges(); + and check whether the current group row checkbox becomes unchecked.`, fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.enableEditing = true; + fix.componentInstance.width = '1200px'; + grid.primaryKey = 'ID'; + grid.columnWidth = '200px'; + grid.rowSelection = GridSelectionMode.multiple; + fix.detectChanges(); - const grRow = grid.groupsRowList.toArray()[0]; + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + fix.detectChanges(); - grid.selectRows([2]); - fix.detectChanges(); + const grRow = grid.groupsRowList.toArray()[0]; - const cell = grid.getCellByKey(2, 'ProductName'); - cell.column.editable = true; - fix.detectChanges(); + grid.selectRows([2]); + fix.detectChanges(); - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, true)); + const cell = grid.getCellByKey(2, 'ProductName'); + cell.column.editable = true; + fix.detectChanges(); - UIInteractions.simulateDoubleClickAndSelectEvent(grid.gridAPI.get_cell_by_key(2, 'ProductName')); - fix.detectChanges(); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, true)); - expect(cell.editMode).toBe(true); + UIInteractions.simulateDoubleClickAndSelectEvent(grid.gridAPI.get_cell_by_key(2, 'ProductName')); + fix.detectChanges(); - const editCellDom = fix.debugElement.query(By.css('.igx-grid__td--editing')); - const input = editCellDom.query(By.css('input')); + expect(cell.editMode).toBe(true); - clickAndSendInputElementValue(input, 'Ignite UI for Angular', fix); - GridFunctions.simulateGridContentKeydown(fix, 'Enter'); - fix.detectChanges(); + const editCellDom = fix.debugElement.query(By.css('.igx-grid__td--editing')); + const input = editCellDom.query(By.css('input')); - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, false)); - })); + clickAndSendInputElementValue(input, 'Ignite UI for Angular', fix); + GridFunctions.simulateGridContentKeydown(fix, 'Enter'); + fix.detectChanges(); - it('groupRowCheckbox should be in the right state by deleting rows from that group', - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.width = '1200px'; - tick(); - grid.columnWidth = '200px'; - tick(); - grid.rowSelection = GridSelectionMode.multiple; - tick(); - fix.detectChanges(); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow, false, false)); + })); - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - tick(); - fix.detectChanges(); + it('groupRowCheckbox should be in the right state by deleting rows from that group', fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.width = '1200px'; + tick(); + grid.columnWidth = '200px'; + tick(); + grid.rowSelection = GridSelectionMode.multiple; + tick(); + fix.detectChanges(); - const grRow1 = grid.groupsRowList.toArray()[0]; + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + tick(); + fix.detectChanges(); - grid.selectRows([grRow1.groupRow.records[0]]); - fix.detectChanges(); - grid.deleteRowById(grRow1.groupRow.records[0]); - fix.detectChanges(); - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow1, false, false)); + const grRow1 = grid.groupsRowList.toArray()[0]; - const grRow2 = grid.groupsRowList.toArray()[1]; + grid.selectRows([grRow1.groupRow.records[0]]); + fix.detectChanges(); + grid.deleteRowById(grRow1.groupRow.records[0]); + fix.detectChanges(); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow1, false, false)); - grid.selectRows(grRow2.groupRow.records); - fix.detectChanges(); - grid.deleteRowById(grRow2.groupRow.records[0]); - fix.detectChanges(); - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow2, true, false)); + const grRow2 = grid.groupsRowList.toArray()[1]; - const grRow3 = grid.groupsRowList.toArray()[2]; + grid.selectRows(grRow2.groupRow.records); + fix.detectChanges(); + grid.deleteRowById(grRow2.groupRow.records[0]); + fix.detectChanges(); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow2, true, false)); - grid.selectRows([grRow3.groupRow.records[1]]); - fix.detectChanges(); - grid.deleteRowById(grRow3.groupRow.records[0]); - fix.detectChanges(); - expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow3, true, false)); - })); + const grRow3 = grid.groupsRowList.toArray()[2]; - it('should hide/show checkboxes when change hideRowSelectors', - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.width = '1200px'; - tick(); - grid.columnWidth = '200px'; - tick(); - grid.rowSelection = GridSelectionMode.multiple; - tick(); - fix.detectChanges(); + grid.selectRows([grRow3.groupRow.records[1]]); + fix.detectChanges(); + grid.deleteRowById(grRow3.groupRow.records[0]); + fix.detectChanges(); + expect(GridSelectionFunctions.verifyGroupByRowCheckboxState(grRow3, true, false)); + })); - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false - }); - tick(); - fix.detectChanges(); + it('should hide/show checkboxes when change hideRowSelectors', fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.width = '1200px'; + tick(); + grid.columnWidth = '200px'; + tick(); + grid.rowSelection = GridSelectionMode.multiple; + tick(); + fix.detectChanges(); - grid.hideRowSelectors = true; - fix.detectChanges(); + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Desc, ignoreCase: false + }); + tick(); + fix.detectChanges(); - const grRows = grid.groupsRowList.toArray(); + grid.hideRowSelectors = true; + fix.detectChanges(); - for (const grRow of grRows) { - expect(GridSelectionFunctions.verifyRowHasCheckbox(grRow.element.nativeElement, false, false)); - } + const grRows = grid.groupsRowList.toArray(); - grid.hideRowSelectors = false; - fix.detectChanges(); + for (const grRow of grRows) { + expect(GridSelectionFunctions.verifyRowHasCheckbox(grRow.element.nativeElement, false, false)); + } - for (const grRow of grRows) { - expect(GridSelectionFunctions.verifyRowHasCheckbox(grRow.element.nativeElement)); - } + grid.hideRowSelectors = false; + fix.detectChanges(); - })); + for (const grRow of grRows) { + expect(GridSelectionFunctions.verifyRowHasCheckbox(grRow.element.nativeElement)); + } + + })); it('Should have the correct properties in the custom row selector template', fakeAsync(() => { const fix = TestBed.createComponent(GridGroupByRowCustomSelectorsComponent); @@ -2160,7 +2128,7 @@ describe('IgxGrid - GroupBy #grid', () => { const contextSelect = { selectedCount: 0, totalCount: 2, groupRow: grid.groupsRowList.toArray()[0].groupRow }; const contextUnselect = { selectedCount: 2, totalCount: 2, groupRow: grid.groupsRowList.toArray()[0].groupRow }; - spyOn(fix.componentInstance, 'onGroupByRowClick').and.callThrough(); + vi.spyOn(fix.componentInstance, 'onGroupByRowClick'); grRow.nativeElement.querySelector('.igx-checkbox__composite').click(); fix.detectChanges(); @@ -2646,10 +2614,8 @@ describe('IgxGrid - GroupBy #grid', () => { tick(); fix.detectChanges(); let groupRows = grid.groupsRowList.toArray(); - checkGroups(groupRows, - ['NetAdvantage', true, false, 'Ignite UI for JavaScript', true, - false, 'Ignite UI for Angular', false, null, '', true, null, true], - grid.groupingExpressions); + checkGroups(groupRows, ['NetAdvantage', true, false, 'Ignite UI for JavaScript', true, + false, 'Ignite UI for Angular', false, null, '', true, null, true], grid.groupingExpressions); const chips = grid.groupArea.chips; checkChips(chips, grid.groupingExpressions); @@ -2668,10 +2634,8 @@ describe('IgxGrid - GroupBy #grid', () => { groupRows = grid.groupsRowList.toArray(); // verify groups - checkGroups(groupRows, - [null, 'Ignite UI for Angular', false, 'Ignite UI for Angular', 'Ignite UI for JavaScript', - 'NetAdvantage', true, null, '', 'Ignite UI for JavaScript', 'NetAdvantage'], - grid.groupingExpressions); + checkGroups(groupRows, [null, 'Ignite UI for Angular', false, 'Ignite UI for Angular', 'Ignite UI for JavaScript', + 'NetAdvantage', true, null, '', 'Ignite UI for JavaScript', 'NetAdvantage'], grid.groupingExpressions); checkChips(chips, grid.groupingExpressions); })); @@ -2778,53 +2742,51 @@ describe('IgxGrid - GroupBy #grid', () => { }); - it('should persist state for the correct group record when there are group records with the same fieldName and value.', - fakeAsync(() => { - const fix = TestBed.createComponent(GroupableGridComponent); - const grid = fix.componentInstance.instance; - fix.componentInstance.data = [ - { - Downloads: 0, - ID: 1, - ProductName: 'JavaScript', - ReleaseDate: new Date(), - Released: false - }, - { - Downloads: 0, - ID: 2, - ProductName: 'JavaScript', - ReleaseDate: new Date(), - Released: true - } - ]; - tick(); - fix.detectChanges(); + it('should persist state for the correct group record when there are group records with the same fieldName and value.', fakeAsync(() => { + const fix = TestBed.createComponent(GroupableGridComponent); + const grid = fix.componentInstance.instance; + fix.componentInstance.data = [ + { + Downloads: 0, + ID: 1, + ProductName: 'JavaScript', + ReleaseDate: new Date(), + Released: false + }, + { + Downloads: 0, + ID: 2, + ProductName: 'JavaScript', + ReleaseDate: new Date(), + Released: true + } + ]; + tick(); + fix.detectChanges(); - grid.groupBy({ - fieldName: 'Released', - dir: SortingDirection.Asc, - }); - grid.groupBy({ - fieldName: 'ProductName', dir: SortingDirection.Asc, ignoreCase: false - }); + grid.groupBy({ + fieldName: 'Released', + dir: SortingDirection.Asc, + }); + grid.groupBy({ + fieldName: 'ProductName', dir: SortingDirection.Asc, ignoreCase: false + }); - fix.detectChanges(); + fix.detectChanges(); - const groupRows = grid.groupsRowList.toArray(); + const groupRows = grid.groupsRowList.toArray(); - // group rows that have the same fieldName and value but belong to different parent groups - const similarGroupRows = groupRows.filter((gRows) => - gRows.groupRow.value === 'JavaScript' && gRows.groupRow.expression.fieldName); - expect(similarGroupRows.length).toEqual(2); + // group rows that have the same fieldName and value but belong to different parent groups + const similarGroupRows = groupRows.filter((gRows) => gRows.groupRow.value === 'JavaScript' && gRows.groupRow.expression.fieldName); + expect(similarGroupRows.length).toEqual(2); - // verify that if one is collapse the other remains expanded - similarGroupRows[0].toggle(); - tick(); + // verify that if one is collapse the other remains expanded + similarGroupRows[0].toggle(); + tick(); - expect(similarGroupRows[0].expanded).toEqual(false); - expect(similarGroupRows[1].expanded).toEqual(true); - })); + expect(similarGroupRows[0].expanded).toEqual(false); + expect(similarGroupRows[1].expanded).toEqual(true); + })); it('should render disabled non-interactable chip for column that does not allow grouping.', fakeAsync(() => { const fix = TestBed.createComponent(DefaultGridComponent); @@ -2915,8 +2877,8 @@ describe('IgxGrid - GroupBy #grid', () => { fix.detectChanges(); grid.groupBy([{ - fieldName: 'ProductName', dir: SortingDirection.Asc, ignoreCase: false - }]); + fieldName: 'ProductName', dir: SortingDirection.Asc, ignoreCase: false + }]); fix.detectChanges(); expect(groupRows[0].expanded).toEqual(true); @@ -3022,8 +2984,7 @@ describe('IgxGrid - GroupBy #grid', () => { // Trigger initial pointer events on the element with igxDrag. When the drag begins the ghostElement should receive events. UIInteractions.simulatePointerEvent('pointerdown', chipComponents[0].componentInstance.dragDirective.element.nativeElement, 75, 30); await wait(); - UIInteractions.simulatePointerEvent('pointermove', - chipComponents[0].componentInstance.dragDirective.element.nativeElement, 110, 30); + UIInteractions.simulatePointerEvent('pointermove', chipComponents[0].componentInstance.dragDirective.element.nativeElement, 110, 30); await wait(); fix.detectChanges(); @@ -3039,10 +3000,8 @@ describe('IgxGrid - GroupBy #grid', () => { // verify groups const groupRows = grid.groupsRowList.toArray(); - checkGroups(groupRows, - ['NetAdvantage', true, false, 'Ignite UI for JavaScript', true, - false, 'Ignite UI for Angular', false, null, '', true, null, true], - grid.groupingExpressions); + checkGroups(groupRows, ['NetAdvantage', true, false, 'Ignite UI for JavaScript', true, + false, 'Ignite UI for Angular', false, null, '', true, null, true], grid.groupingExpressions); }); @@ -3089,11 +3048,9 @@ describe('IgxGrid - GroupBy #grid', () => { fix.detectChanges(); // Trigger initial pointer events on the element with igxDrag. When the drag begins the ghostElement should receive events. - UIInteractions.simulatePointerEvent('pointerdown', - chipComponents[0].componentInstance.dragDirective.element.nativeElement, 100, 30); + UIInteractions.simulatePointerEvent('pointerdown', chipComponents[0].componentInstance.dragDirective.element.nativeElement, 100, 30); await wait(); - UIInteractions.simulatePointerEvent('pointermove', - chipComponents[0].componentInstance.dragDirective.element.nativeElement, 110, 30); + UIInteractions.simulatePointerEvent('pointermove', chipComponents[0].componentInstance.dragDirective.element.nativeElement, 110, 30); await wait(); fix.detectChanges(); @@ -3116,11 +3073,9 @@ describe('IgxGrid - GroupBy #grid', () => { chipComponents = fix.debugElement.queryAll(By.directive(IgxChipComponent)); // Trigger initial pointer events on the element with igxDrag. When the drag begins the ghostElement should receive events. - UIInteractions.simulatePointerEvent('pointerdown', - chipComponents[0].componentInstance.dragDirective.element.nativeElement, 100, 30); + UIInteractions.simulatePointerEvent('pointerdown', chipComponents[0].componentInstance.dragDirective.element.nativeElement, 100, 30); await wait(); - UIInteractions.simulatePointerEvent('pointermove', - chipComponents[0].componentInstance.dragDirective.element.nativeElement, 110, 30); + UIInteractions.simulatePointerEvent('pointermove', chipComponents[0].componentInstance.dragDirective.element.nativeElement, 110, 30); await wait(); fix.detectChanges(); @@ -3366,56 +3321,54 @@ describe('IgxGrid - GroupBy #grid', () => { } })); - it('should allow setting groupingExpressions and sortingExpressions initially.', - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - fix.componentInstance.enableSorting = true; - const grid = fix.componentInstance.instance; - grid.sortingExpressions = - [{ fieldName: 'Downloads', dir: SortingDirection.Asc, ignoreCase: false }]; - grid.groupingExpressions = - [{ fieldName: 'Released', dir: SortingDirection.Asc, ignoreCase: false }]; - fix.detectChanges(); + it('should allow setting groupingExpressions and sortingExpressions initially.', fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + fix.componentInstance.enableSorting = true; + const grid = fix.componentInstance.instance; + grid.sortingExpressions = + [{ fieldName: 'Downloads', dir: SortingDirection.Asc, ignoreCase: false }]; + grid.groupingExpressions = + [{ fieldName: 'Released', dir: SortingDirection.Asc, ignoreCase: false }]; + fix.detectChanges(); - //grouping expressions should not affect grouping expressions - expect(grid.sortingExpressions.length).toEqual(1); - expect(grid.groupingExpressions.length).toEqual(1); + //grouping expressions should not affect grouping expressions + expect(grid.sortingExpressions.length).toEqual(1); + expect(grid.groupingExpressions.length).toEqual(1); - const groupRows = grid.groupsRowList.toArray(); + const groupRows = grid.groupsRowList.toArray(); - expect(groupRows.length).toEqual(3); + expect(groupRows.length).toEqual(3); - const chips = grid.groupArea.chips; - checkChips(chips, grid.groupingExpressions); + const chips = grid.groupArea.chips; + checkChips(chips, grid.groupingExpressions); - const sortingIcon = fix.debugElement.query(By.css('.sort-icon')); - expect(sortingIcon.nativeElement.textContent.trim()).toEqual(SORTING_ICON_ASC_CONTENT); - })); + const sortingIcon = fix.debugElement.query(By.css('.sort-icon')); + expect(sortingIcon.nativeElement.textContent.trim()).toEqual(SORTING_ICON_ASC_CONTENT); + })); - it('should show horizontal scrollbar if column widths are equal to the grid width and a column is grouped.', - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); + it('should show horizontal scrollbar if column widths are equal to the grid width and a column is grouped.', fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; + const grid = fix.componentInstance.instance; - grid.columnWidth = '200px'; - tick(); - fix.componentInstance.width = '1000px'; - tick(); + grid.columnWidth = '200px'; + tick(); + fix.componentInstance.width = '1000px'; + tick(); - fix.detectChanges(); + fix.detectChanges(); - const hScrBar = grid.scr.nativeElement; - expect(hScrBar.hidden).toBe(true); + const hScrBar = grid.scr.nativeElement; + expect(hScrBar.hidden).toBe(true); - grid.groupBy({ - fieldName: 'Downloads', - dir: SortingDirection.Asc, - ignoreCase: false - }); - fix.detectChanges(); - expect(hScrBar.hidden).toBe(false); - })); + grid.groupBy({ + fieldName: 'Downloads', + dir: SortingDirection.Asc, + ignoreCase: false + }); + fix.detectChanges(); + expect(hScrBar.hidden).toBe(false); + })); it('should allow changing the text of the drop area', async () => { const fix = TestBed.createComponent(DefaultGridComponent); @@ -3441,119 +3394,114 @@ describe('IgxGrid - GroupBy #grid', () => { expect(groupDropArea.nativeElement.textContent.trim()).toEqual('Custom template'); }); - it('should hide all the grouped columns when hideGroupedColumns option is initially set to "true"', - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - grid.hideGroupedColumns = true; - tick(); - fix.detectChanges(); - grid.groupBy([ - { fieldName: 'Downloads', dir: SortingDirection.Asc, ignoreCase: false }, - { fieldName: 'ProductName', dir: SortingDirection.Asc, ignoreCase: false } - ]); - tick(); - fix.detectChanges(); - // the two grouped columns should be hidden - expect(grid.getColumnByName('Downloads').hidden).toBe(true); - expect(grid.getColumnByName('ProductName').hidden).toBe(true); - // these should be visible - expect(grid.getColumnByName('ID').hidden).toBe(false); - expect(grid.getColumnByName('ReleaseDate').hidden).toBe(false); - expect(grid.getColumnByName('Released').hidden).toBe(false); - })); + it('should hide all the grouped columns when hideGroupedColumns option is initially set to "true"', fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + grid.hideGroupedColumns = true; + tick(); + fix.detectChanges(); + grid.groupBy([ + { fieldName: 'Downloads', dir: SortingDirection.Asc, ignoreCase: false }, + { fieldName: 'ProductName', dir: SortingDirection.Asc, ignoreCase: false } + ]); + tick(); + fix.detectChanges(); + // the two grouped columns should be hidden + expect(grid.getColumnByName('Downloads').hidden).toBe(true); + expect(grid.getColumnByName('ProductName').hidden).toBe(true); + // these should be visible + expect(grid.getColumnByName('ID').hidden).toBe(false); + expect(grid.getColumnByName('ReleaseDate').hidden).toBe(false); + expect(grid.getColumnByName('Released').hidden).toBe(false); + })); - it('should show all the grid columns when hideGroupedColumns option is set to "false" at runtime, after being "true" initially', - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - grid.hideGroupedColumns = true; - fix.detectChanges(); - grid.groupBy([ - { fieldName: 'Downloads', dir: SortingDirection.Asc, ignoreCase: false }, - { fieldName: 'ProductName', dir: SortingDirection.Asc, ignoreCase: false } - ]); - tick(); - fix.detectChanges(); - // the two grouped columns should be hidden initially - expect(grid.getColumnByName('Downloads').hidden).toBe(true); - expect(grid.getColumnByName('ProductName').hidden).toBe(true); - grid.hideGroupedColumns = false; - tick(); - fix.detectChanges(); - // all columns, whether grouped or ungrouped, should be visible - expect(grid.getColumnByName('Downloads').hidden).toBe(false); - expect(grid.getColumnByName('ProductName').hidden).toBe(false); - expect(grid.getColumnByName('ID').hidden).toBe(false); - expect(grid.getColumnByName('ReleaseDate').hidden).toBe(false); - expect(grid.getColumnByName('Released').hidden).toBe(false); - })); + it('should show all the grid columns when hideGroupedColumns option is set to "false" at runtime, after being "true" initially', fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + grid.hideGroupedColumns = true; + fix.detectChanges(); + grid.groupBy([ + { fieldName: 'Downloads', dir: SortingDirection.Asc, ignoreCase: false }, + { fieldName: 'ProductName', dir: SortingDirection.Asc, ignoreCase: false } + ]); + tick(); + fix.detectChanges(); + // the two grouped columns should be hidden initially + expect(grid.getColumnByName('Downloads').hidden).toBe(true); + expect(grid.getColumnByName('ProductName').hidden).toBe(true); + grid.hideGroupedColumns = false; + tick(); + fix.detectChanges(); + // all columns, whether grouped or ungrouped, should be visible + expect(grid.getColumnByName('Downloads').hidden).toBe(false); + expect(grid.getColumnByName('ProductName').hidden).toBe(false); + expect(grid.getColumnByName('ID').hidden).toBe(false); + expect(grid.getColumnByName('ReleaseDate').hidden).toBe(false); + expect(grid.getColumnByName('Released').hidden).toBe(false); + })); - it('should hide the grouped columns when hideGroupedColumns option is set to "true" at runtime, after being "false" initially', - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - const grid = fix.componentInstance.instance; - fix.detectChanges(); - grid.groupBy([ - { fieldName: 'Downloads', dir: SortingDirection.Asc, ignoreCase: false }, - { fieldName: 'ProductName', dir: SortingDirection.Asc, ignoreCase: false } - ]); - tick(); - fix.detectChanges(); - // all columns, whether grouped or ungrouped, should be visible - expect(grid.getColumnByName('Downloads').hidden).toBe(false); - expect(grid.getColumnByName('ProductName').hidden).toBe(false); - expect(grid.getColumnByName('ID').hidden).toBe(false); - expect(grid.getColumnByName('ReleaseDate').hidden).toBe(false); - expect(grid.getColumnByName('Released').hidden).toBe(false); - grid.hideGroupedColumns = true; - tick(); - fix.detectChanges(); - // the two grouped columns should now be hidden - expect(grid.getColumnByName('Downloads').hidden).toBe(true); - expect(grid.getColumnByName('ProductName').hidden).toBe(true); - })); + it('should hide the grouped columns when hideGroupedColumns option is set to "true" at runtime, after being "false" initially', fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + const grid = fix.componentInstance.instance; + fix.detectChanges(); + grid.groupBy([ + { fieldName: 'Downloads', dir: SortingDirection.Asc, ignoreCase: false }, + { fieldName: 'ProductName', dir: SortingDirection.Asc, ignoreCase: false } + ]); + tick(); + fix.detectChanges(); + // all columns, whether grouped or ungrouped, should be visible + expect(grid.getColumnByName('Downloads').hidden).toBe(false); + expect(grid.getColumnByName('ProductName').hidden).toBe(false); + expect(grid.getColumnByName('ID').hidden).toBe(false); + expect(grid.getColumnByName('ReleaseDate').hidden).toBe(false); + expect(grid.getColumnByName('Released').hidden).toBe(false); + grid.hideGroupedColumns = true; + tick(); + fix.detectChanges(); + // the two grouped columns should now be hidden + expect(grid.getColumnByName('Downloads').hidden).toBe(true); + expect(grid.getColumnByName('ProductName').hidden).toBe(true); + })); it(`should hide the grouped columns when hideGroupedColumns option is enabled, - there are initially set groupingExpressions and columns are autogenerated`, - fakeAsync(() => { - const fix = TestBed.createComponent(DefaultGridComponent); - fix.detectChanges(); - const grid = fix.componentInstance.instance; - grid.hideGroupedColumns = true; - grid.groupingExpressions = [ - { fieldName: 'Released', dir: SortingDirection.Asc } - ]; - fix.detectChanges(); - expect(grid.getColumnByName('Released').hidden).toBe(true); - const groupRows = grid.groupsRowList.toArray(); + there are initially set groupingExpressions and columns are autogenerated`, fakeAsync(() => { + const fix = TestBed.createComponent(DefaultGridComponent); + fix.detectChanges(); + const grid = fix.componentInstance.instance; + grid.hideGroupedColumns = true; + grid.groupingExpressions = [ + { fieldName: 'Released', dir: SortingDirection.Asc } + ]; + fix.detectChanges(); + expect(grid.getColumnByName('Released').hidden).toBe(true); + const groupRows = grid.groupsRowList.toArray(); - expect(groupRows.length).toEqual(3); - })); + expect(groupRows.length).toEqual(3); + })); - it('should hide all the grouped columns when hideGroupedColumns option is "true" and columns are set runtime', - fakeAsync(() => { - const fix = TestBed.createComponent(GroupByDataMoreColumnsComponent); - fix.detectChanges(); - const grid = fix.componentInstance.instance; - fix.componentInstance.columns = []; - grid.hideGroupedColumns = true; - fix.detectChanges(); - tick(); - fix.detectChanges(); - fix.componentInstance.columns = [ - { field: 'A', width: 100 }, - { field: 'B', width: 100 }, - { field: 'C', width: 100 } - ]; - grid.groupingExpressions = [ - { fieldName: 'A', dir: SortingDirection.Asc } - ]; - fix.detectChanges(); - tick(); - - expect(grid.getColumnByName('A').hidden).toBe(true); - })); + it('should hide all the grouped columns when hideGroupedColumns option is "true" and columns are set runtime', fakeAsync(() => { + const fix = TestBed.createComponent(GroupByDataMoreColumnsComponent); + fix.detectChanges(); + const grid = fix.componentInstance.instance; + fix.componentInstance.columns = []; + grid.hideGroupedColumns = true; + fix.detectChanges(); + tick(); + fix.detectChanges(); + fix.componentInstance.columns = [ + { field: 'A', width: 100 }, + { field: 'B', width: 100 }, + { field: 'C', width: 100 } + ]; + grid.groupingExpressions = [ + { fieldName: 'A', dir: SortingDirection.Asc } + ]; + fix.detectChanges(); + tick(); + + expect(grid.getColumnByName('A').hidden).toBe(true); + })); it('should respect current sorting direction when grouping', (async () => { const fix = TestBed.createComponent(DefaultGridComponent); @@ -3629,8 +3577,8 @@ describe('IgxGrid - GroupBy #grid', () => { { fieldName: 'Released', dir: SortingDirection.Desc, ignoreCase: false, strategy: DefaultSortingStrategy.instance() } ]); expect(grid.groupingExpressions).toEqual([{ - fieldName: 'Released', dir: SortingDirection.Desc, ignoreCase: false, strategy: DefaultSortingStrategy.instance() - }]); + fieldName: 'Released', dir: SortingDirection.Desc, ignoreCase: false, strategy: DefaultSortingStrategy.instance() + }]); }); it('should not be able to group by ColumnGroup', async () => { @@ -3825,7 +3773,7 @@ describe('IgxGrid - GroupBy #grid', () => { const data = []; for (let i = 0; i < 1000000; i++) { - data.push({ + data.push({ Downloads: i, ID: 1, ProductName: 'Test' @@ -3900,10 +3848,10 @@ describe('IgxGrid - GroupBy #grid', () => { it('should restore date/time columns groupBy expansion state in nested hierarchies correctly - issue #14619', fakeAsync(() => { grid.groupBy([{ - fieldName: 'ProductName', dir: SortingDirection.Asc, ignoreCase: false - }, { - fieldName: 'DateField', dir: SortingDirection.Asc, ignoreCase: false - }]); + fieldName: 'ProductName', dir: SortingDirection.Asc, ignoreCase: false + }, { + fieldName: 'DateField', dir: SortingDirection.Asc, ignoreCase: false + }]); fix.detectChanges(); let groupRows = grid.groupsRowList.toArray(); @@ -4038,12 +3986,7 @@ const formatUnboundValueFunction = (rowData: any | undefined): string | undefine class MySortingStrategy extends IgxGrouping { - protected override getFieldValue( - obj: any, - key: string, - isDate = false, - isTime = false - ): unknown { + protected override getFieldValue(obj: any, key: string, isDate = false, isTime = false): unknown { if (key !== 'UnboundField') { return super.getFieldValue(obj, key, isDate, isTime); } diff --git a/projects/igniteui-angular/grids/grid/src/grid.master-detail.spec.ts b/projects/igniteui-angular/grids/grid/src/grid.master-detail.spec.ts index 3315c47d56c..3991b863528 100644 --- a/projects/igniteui-angular/grids/grid/src/grid.master-detail.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid.master-detail.spec.ts @@ -15,6 +15,7 @@ import { GridSummaryCalculationMode, IgxStringFilteringOperand, SortingDirection import { IgxCheckboxComponent } from 'igniteui-angular/checkbox'; import { IgxInputDirective, IgxInputGroupComponent } from 'igniteui-angular/input-group'; import { IgxPaginatorComponent } from 'igniteui-angular/paginator'; +import { describe, it, test, expect, beforeEach, vi } from 'vitest'; const DEBOUNCE_TIME = 30; const ROW_TAG = 'igx-grid-row'; @@ -82,10 +83,8 @@ describe('IgxGrid Master Detail #grid', () => { const inputElem = firstDetail.query(By.directive(IgxInputGroupComponent)); const inputElemPos = inputElem.nativeElement.getBoundingClientRect(); - const tracedCheckbox: any = - document.elementFromPoint(checkboxPos.left + checkboxPos.height / 2, checkboxPos.top + checkboxPos.height / 2); - const tracedInput: any = - document.elementFromPoint(inputElemPos.left + inputElemPos.height / 2, inputElemPos.top + inputElemPos.height / 2); + const tracedCheckbox: any = document.elementFromPoint(checkboxPos.left + checkboxPos.height / 2, checkboxPos.top + checkboxPos.height / 2); + const tracedInput: any = document.elementFromPoint(inputElemPos.left + inputElemPos.height / 2, inputElemPos.top + inputElemPos.height / 2); checkboxElem.componentInstance.nativeInput.nativeElement.click(); fix.detectChanges(); @@ -571,8 +570,10 @@ describe('IgxGrid Master Detail #grid', () => { expect(targetCellElement2.active).toBeTruthy(); }); - it('Should navigate to the correct row/cell when using the navigateTo method in a grid with expanded detail views.', async () => { - pending('This test should pass when the issue #7300 is fixed.'); + it.skip('Should navigate to the correct row/cell when using the navigateTo method in a grid with expanded detail views.', async () => { + // TODO: vitest-migration: The pending() function was converted to a skipped test (`it.skip`). See: https://vitest.dev/api/vi.html#it-skip + // pending('This test should pass when the issue #7300 is fixed.'); + ; grid.navigateTo(20, 0); await wait(DEBOUNCE_TIME); fix.detectChanges(); @@ -839,7 +840,7 @@ describe('IgxGrid Master Detail #grid', () => { it('Should exclude expanded detail views when doing range cell selection', fakeAsync(() => { grid.expandRow(fix.componentInstance.data[2].ID); - const selectionChangeSpy = spyOn(grid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(grid.rangeSelected, 'emit'); const startCell = grid.gridAPI.get_cell_by_index(1, 'ContactName'); const endCell = grid.gridAPI.get_cell_by_index(6, 'CompanyName'); const range = { rowStart: 1, rowEnd: 6, columnStart: 0, columnEnd: 1 }; @@ -853,8 +854,7 @@ describe('IgxGrid Master Detail #grid', () => { for (let i = 2; i < 6; i++) { const cell = grid.gridAPI.get_cell_by_index(i, 'ContactName'); if (!cell) { - UIInteractions.simulatePointerOverElementEvent('pointerenter', - fix.debugElement.query(By.css('.addressArea')).nativeElement); + UIInteractions.simulatePointerOverElementEvent('pointerenter', fix.debugElement.query(By.css('.addressArea')).nativeElement); continue; } UIInteractions.simulatePointerOverElementEvent('pointerenter', cell.nativeElement); @@ -1397,6 +1397,7 @@ export class AllExpandedGridMasterDetailComponent extends DefaultGridMasterDetai `, imports: [IgxGridComponent, IgxColumnComponent, IgxGridDetailTemplateDirective, IgxColumnLayoutComponent, IgxCheckboxComponent, IgxPaginatorComponent] }) -export class MRLMasterDetailComponent extends DefaultGridMasterDetailComponent { } +export class MRLMasterDetailComponent extends DefaultGridMasterDetailComponent { +} const getDetailAddressText = (detailElem) => detailElem.querySelector('.addressArea').innerText; diff --git a/projects/igniteui-angular/grids/grid/src/grid.multi-row-layout.integration.spec.ts b/projects/igniteui-angular/grids/grid/src/grid.multi-row-layout.integration.spec.ts index 5295a492f6f..065519760a3 100644 --- a/projects/igniteui-angular/grids/grid/src/grid.multi-row-layout.integration.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid.multi-row-layout.integration.spec.ts @@ -1,4 +1,4 @@ -import { TestBed, waitForAsync, ComponentFixture } from '@angular/core/testing'; +import { TestBed, waitForAsync, ComponentFixture } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxGridComponent } from './grid.component'; @@ -10,10 +10,10 @@ import { GridFunctions, GRID_MRL_BLOCK } from '../../../test-utils/grid-function import { ControlsFunction } from '../../../test-utils/controls-functions.spec'; import { IgxColumnComponent } from 'igniteui-angular/grids/core'; import { DefaultSortingStrategy, SortingDirection } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach } from 'vitest'; -type FixtureType = ColumnLayoutGroupingTestComponent | ColumnLayoutHidingTestComponent | ColumnLayoutResizingTestComponent - | ColumnLayoutPinningTestComponent; +type FixtureType = ColumnLayoutGroupingTestComponent | ColumnLayoutHidingTestComponent | ColumnLayoutResizingTestComponent | ColumnLayoutPinningTestComponent; interface ColGroupsType { group: string; hidden?: boolean; @@ -319,30 +319,29 @@ describe('IgxGrid - multi-row-layout Integration #grid - ', () => { }); - it('UI - hidden columns count and drop-down items text in hiding toolbar should be correct when group is hidden/shown. ', - waitForAsync(async () => { - // enable toolbar for hiding - fixture.componentInstance.showToolbar = true; - fixture.detectChanges(); - await fixture.whenStable(); - fixture.detectChanges(); - - const hidingButton = GridFunctions.getColumnHidingButton(fixture); - hidingButton.click(); - fixture.detectChanges(); - // should show count for actual hidden igxColumns - expect(parseInt(hidingButton.querySelector('span').textContent.trim(), 10)).toBe(4); - const columnChooserElement = GridFunctions.getColumnHidingElement(fixture); - const checkboxes = columnChooserElement.queryAll(By.css('igx-checkbox')); - // should show 2 checkboxes - one for each group - expect(checkboxes.length).toBe(2); - expect(checkboxes[0].query(By.css('.igx-checkbox__label')).nativeElement.textContent.trim()).toBe('group1'); - expect(checkboxes[1].query(By.css('.igx-checkbox__label')).nativeElement.textContent.trim()).toBe('group2'); - - // verify checked state - expect(checkboxes[0].componentInstance.checked).toBeFalse(); - expect(checkboxes[1].componentInstance.checked).toBeTrue(); - })); + it('UI - hidden columns count and drop-down items text in hiding toolbar should be correct when group is hidden/shown. ', waitForAsync(async () => { + // enable toolbar for hiding + fixture.componentInstance.showToolbar = true; + fixture.detectChanges(); + await fixture.whenStable(); + fixture.detectChanges(); + + const hidingButton = GridFunctions.getColumnHidingButton(fixture); + hidingButton.click(); + fixture.detectChanges(); + // should show count for actual hidden igxColumns + expect(parseInt(hidingButton.querySelector('span').textContent.trim(), 10)).toBe(4); + const columnChooserElement = GridFunctions.getColumnHidingElement(fixture); + const checkboxes = columnChooserElement.queryAll(By.css('igx-checkbox')); + // should show 2 checkboxes - one for each group + expect(checkboxes.length).toBe(2); + expect(checkboxes[0].query(By.css('.igx-checkbox__label')).nativeElement.textContent.trim()).toBe('group1'); + expect(checkboxes[1].query(By.css('.igx-checkbox__label')).nativeElement.textContent.trim()).toBe('group2'); + + // verify checked state + expect(checkboxes[0].componentInstance.checked).toBe(false); + expect(checkboxes[1].componentInstance.checked).toBe(true); + })); it(`UI - toggling column checkbox checked state successfully changes the column's hidden state. `, waitForAsync(async () => { // enable toolbar for hiding @@ -361,7 +360,7 @@ describe('IgxGrid - multi-row-layout Integration #grid - ', () => { verifyCheckbox('group1', false, false, columnChooserElement); const column = grid.getColumnByName('group1'); - expect(column.hidden).toBeTrue(); + expect(column.hidden).toBe(true); let gridFirstRow = grid.rowList.first; @@ -373,7 +372,7 @@ describe('IgxGrid - multi-row-layout Integration #grid - ', () => { fixture.detectChanges(); expect(checkbox.checked).toBe(true); - expect(column.hidden).toBeFalse(); + expect(column.hidden).toBe(false); gridFirstRow = grid.rowList.first; GridFunctions.verifyLayoutHeadersAreAligned(grid, gridFirstRow); @@ -383,7 +382,7 @@ describe('IgxGrid - multi-row-layout Integration #grid - ', () => { fixture.detectChanges(); expect(checkbox.checked).toBe(false); - expect(column.hidden).toBeTrue(); + expect(column.hidden).toBe(true); })); }); @@ -504,19 +503,19 @@ describe('IgxGrid - multi-row-layout Integration #grid - ', () => { expect(allArgs.length).toBe(5); expect(allArgs[0].column instanceof IgxColumnLayoutComponent).toBeTruthy(); - expect(allArgs[0].isPinned).toBeTrue(); + expect(allArgs[0].isPinned).toBe(true); expect(allArgs[1].column.field).toBe('PostalCode'); - expect(allArgs[1].isPinned).toBeTrue(); + expect(allArgs[1].isPinned).toBe(true); expect(allArgs[2].column.field).toBe('City'); - expect(allArgs[2].isPinned).toBeTrue(); + expect(allArgs[2].isPinned).toBe(true); expect(allArgs[3].column.field).toBe('Country'); - expect(allArgs[3].isPinned).toBeTrue(); + expect(allArgs[3].isPinned).toBe(true); expect(allArgs[4].column.field).toBe('Address'); - expect(allArgs[4].isPinned).toBeTrue(); + expect(allArgs[4].isPinned).toBe(true); allArgs = []; grid.pinColumn('ID'); @@ -525,19 +524,19 @@ describe('IgxGrid - multi-row-layout Integration #grid - ', () => { expect(allArgs.length).toBe(5); expect(allArgs[0].column instanceof IgxColumnLayoutComponent).toBeTruthy(); - expect(allArgs[0].isPinned).toBeFalse(); + expect(allArgs[0].isPinned).toBe(false); expect(allArgs[1].column.field).toBe('ID'); - expect(allArgs[1].isPinned).toBeFalse(); + expect(allArgs[1].isPinned).toBe(false); expect(allArgs[2].column.field).toBe('CompanyName'); - expect(allArgs[2].isPinned).toBeFalse(); + expect(allArgs[2].isPinned).toBe(false); expect(allArgs[3].column.field).toBe('ContactName'); - expect(allArgs[3].isPinned).toBeFalse(); + expect(allArgs[3].isPinned).toBe(false); expect(allArgs[4].column.field).toBe('ContactTitle'); - expect(allArgs[4].isPinned).toBeFalse(); + expect(allArgs[4].isPinned).toBe(false); }); @@ -636,31 +635,30 @@ describe('IgxGrid - multi-row-layout Integration #grid - ', () => { .toBeLessThanOrEqual(2); }); - it('UI - pinned columns count and drop-down items text in pinning toolbar should be correct when group is pinned. ', - waitForAsync(async () => { - // enable toolbar for pinning - fixture.componentInstance.showToolbar = true; - fixture.detectChanges(); - await fixture.whenStable(); - fixture.detectChanges(); - - const pinningButton = GridFunctions.getColumnPinningButton(fixture); - const pinningButtonLabel = pinningButton.querySelector('span'); - pinningButton.click(); - fixture.detectChanges(); - // should show count for actual igxColumns displayed in the pinned area - expect(parseInt(pinningButtonLabel.textContent.trim(), 10)).toBe(4); - const columnChooserElement = GridFunctions.getColumnPinningElement(fixture); - const checkboxes = columnChooserElement.queryAll(By.css('igx-checkbox')); - // should show 2 checkboxes - one for each group - expect(checkboxes.length).toBe(2); - expect(checkboxes[0].query(By.css('.igx-checkbox__label')).nativeElement.textContent.trim()).toBe('group1'); - expect(checkboxes[1].query(By.css('.igx-checkbox__label')).nativeElement.textContent.trim()).toBe('group2'); - - // verify checked state - expect(checkboxes[0].componentInstance.checked).toBeTruthy(); - expect(checkboxes[1].componentInstance.checked).toBeFalsy(); - })); + it('UI - pinned columns count and drop-down items text in pinning toolbar should be correct when group is pinned. ', waitForAsync(async () => { + // enable toolbar for pinning + fixture.componentInstance.showToolbar = true; + fixture.detectChanges(); + await fixture.whenStable(); + fixture.detectChanges(); + + const pinningButton = GridFunctions.getColumnPinningButton(fixture); + const pinningButtonLabel = pinningButton.querySelector('span'); + pinningButton.click(); + fixture.detectChanges(); + // should show count for actual igxColumns displayed in the pinned area + expect(parseInt(pinningButtonLabel.textContent.trim(), 10)).toBe(4); + const columnChooserElement = GridFunctions.getColumnPinningElement(fixture); + const checkboxes = columnChooserElement.queryAll(By.css('igx-checkbox')); + // should show 2 checkboxes - one for each group + expect(checkboxes.length).toBe(2); + expect(checkboxes[0].query(By.css('.igx-checkbox__label')).nativeElement.textContent.trim()).toBe('group1'); + expect(checkboxes[1].query(By.css('.igx-checkbox__label')).nativeElement.textContent.trim()).toBe('group2'); + + // verify checked state + expect(checkboxes[0].componentInstance.checked).toBeTruthy(); + expect(checkboxes[1].componentInstance.checked).toBeFalsy(); + })); it(`UI - toggling column checkbox checked state successfully changes the column's pinned state. `, waitForAsync(async () => { const uniqueGroups = [ @@ -808,7 +806,7 @@ describe('IgxGrid - multi-row-layout Integration #grid - ', () => { const filterIcons = fixture.debugElement.queryAll(By.css('.igx-excel-filter__icon')); expect(filterIcons.length).not.toBe(0); - const gridFirstRow = grid.rowList.first; + const gridFirstRow = grid.rowList.first; // headers are aligned to cells GridFunctions.verifyLayoutHeadersAreAligned(grid, gridFirstRow, true); @@ -939,19 +937,19 @@ describe('IgxGrid - multi-row-layout Integration #grid - ', () => { it('should correctly resize column on upper level with 3 spans and the two cols below it with span 1 that have width', async () => { grid.width = '1500px'; fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, width: '300px', resizable: true }, - { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px', resizable: true }, - { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px', resizable: true }, - { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px', resizable: true }, - { field: 'City', rowStart: 2, colStart: 3, colEnd: 5, resizable: true }, - { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px', resizable: true }, - { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px', resizable: true }, - { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px', resizable: true }, - { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, width: '300px', resizable: true }, + { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px', resizable: true }, + { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px', resizable: true }, + { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px', resizable: true }, + { field: 'City', rowStart: 2, colStart: 3, colEnd: 5, resizable: true }, + { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px', resizable: true }, + { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px', resizable: true }, + { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px', resizable: true }, + { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, + ] + }]; fixture.detectChanges(); await wait(DEBOUNCE_TIME); fixture.detectChanges(); @@ -979,19 +977,19 @@ describe('IgxGrid - multi-row-layout Integration #grid - ', () => { it('should correctly resize column with span 2 and the ones below it that have span 1 with width set', async () => { grid.width = '1500px'; fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, width: '300px', resizable: true }, - { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px', resizable: true }, - { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px', resizable: true }, - { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px', resizable: true }, - { field: 'City', rowStart: 2, colStart: 3, colEnd: 5, resizable: true }, - { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px', resizable: true }, - { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px', resizable: true }, - { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px', resizable: true }, - { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, width: '300px', resizable: true }, + { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px', resizable: true }, + { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px', resizable: true }, + { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px', resizable: true }, + { field: 'City', rowStart: 2, colStart: 3, colEnd: 5, resizable: true }, + { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px', resizable: true }, + { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px', resizable: true }, + { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px', resizable: true }, + { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, + ] + }]; fixture.detectChanges(); await wait(DEBOUNCE_TIME); fixture.detectChanges(); @@ -1019,19 +1017,19 @@ describe('IgxGrid - multi-row-layout Integration #grid - ', () => { it('should correctly resize column that spans 1 column that is used to size the column templates', async () => { grid.width = '1500px'; fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, width: '300px', resizable: true }, - { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px', resizable: true }, - { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px', resizable: true }, - { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px', resizable: true }, - { field: 'City', rowStart: 2, colStart: 3, colEnd: 5, resizable: true }, - { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px', resizable: true }, - { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px', resizable: true }, - { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px', resizable: true }, - { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, width: '300px', resizable: true }, + { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px', resizable: true }, + { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px', resizable: true }, + { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px', resizable: true }, + { field: 'City', rowStart: 2, colStart: 3, colEnd: 5, resizable: true }, + { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px', resizable: true }, + { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px', resizable: true }, + { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px', resizable: true }, + { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, + ] + }]; fixture.detectChanges(); await wait(DEBOUNCE_TIME); fixture.detectChanges(); @@ -1059,19 +1057,19 @@ describe('IgxGrid - multi-row-layout Integration #grid - ', () => { it('should correctly resize column with span 1 and bigger columns that start with same colStart with bigger span', async () => { grid.width = '1500px'; fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, width: '300px', resizable: true }, - { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px', resizable: true }, - { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px', resizable: true }, - { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px', resizable: true }, - { field: 'City', rowStart: 2, colStart: 3, colEnd: 5, resizable: true }, - { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px', resizable: true }, - { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px', resizable: true }, - { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px', resizable: true }, - { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, width: '300px', resizable: true }, + { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px', resizable: true }, + { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px', resizable: true }, + { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px', resizable: true }, + { field: 'City', rowStart: 2, colStart: 3, colEnd: 5, resizable: true }, + { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px', resizable: true }, + { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px', resizable: true }, + { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px', resizable: true }, + { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, + ] + }]; fixture.detectChanges(); await wait(DEBOUNCE_TIME); fixture.detectChanges(); @@ -1099,19 +1097,19 @@ describe('IgxGrid - multi-row-layout Integration #grid - ', () => { it('should correctly resize column while there is another column that does not have width set', async () => { grid.width = 1500 + grid.scrollSize + 'px'; fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, resizable: true }, - { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px', resizable: true }, - { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px', resizable: true }, - { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px', resizable: true }, - { field: 'City', rowStart: 2, colStart: 3, colEnd: 5, resizable: true }, - { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px', resizable: true }, - { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px', resizable: true }, - { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px', resizable: true }, - { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, resizable: true }, + { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px', resizable: true }, + { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px', resizable: true }, + { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px', resizable: true }, + { field: 'City', rowStart: 2, colStart: 3, colEnd: 5, resizable: true }, + { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px', resizable: true }, + { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px', resizable: true }, + { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px', resizable: true }, + { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, + ] + }]; fixture.detectChanges(); await wait(DEBOUNCE_TIME); fixture.detectChanges(); @@ -1142,19 +1140,19 @@ describe('IgxGrid - multi-row-layout Integration #grid - ', () => { grid.width = 1500 + grid.scrollSize + 'px'; fixture.detectChanges(); fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, resizable: true }, - { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px', resizable: true }, - { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px', resizable: true }, - { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px', resizable: true }, - { field: 'City', rowStart: 2, colStart: 3, colEnd: 5, resizable: true }, - { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px', resizable: true }, - { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px', resizable: true }, - { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px', resizable: true }, - { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, resizable: true }, + { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px', resizable: true }, + { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px', resizable: true }, + { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px', resizable: true }, + { field: 'City', rowStart: 2, colStart: 3, colEnd: 5, resizable: true }, + { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px', resizable: true }, + { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px', resizable: true }, + { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px', resizable: true }, + { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, + ] + }]; fixture.detectChanges(); await wait(DEBOUNCE_TIME); fixture.detectChanges(); @@ -1194,17 +1192,17 @@ describe('IgxGrid - multi-row-layout Integration #grid - ', () => { it('should return correct selected data via getSelectedData API.', () => { const selectedData1 = [{ - ID: 'ALFKI', - CompanyName: 'Alfreds Futterkiste', - ContactName: 'Maria Anders', - ContactTitle: 'Sales Representative' - }]; + ID: 'ALFKI', + CompanyName: 'Alfreds Futterkiste', + ContactName: 'Maria Anders', + ContactTitle: 'Sales Representative' + }]; const selectedData2 = [{ - PostalCode: '05021', - City: 'México D.F.', - Country: 'Mexico', - Address: 'Avda. de la Constitución 2222' - }]; + PostalCode: '05021', + City: 'México D.F.', + Country: 'Mexico', + Address: 'Avda. de la Constitución 2222' + }]; let cellElem = grid.gridAPI.get_cell_by_index(0, 'CompanyName'); UIInteractions.simulateClickAndSelectEvent(cellElem); fixture.detectChanges(); diff --git a/projects/igniteui-angular/grids/grid/src/grid.multi-row-layout.spec.ts b/projects/igniteui-angular/grids/grid/src/grid.multi-row-layout.spec.ts index c3f0fe67f67..d79d8eec80b 100644 --- a/projects/igniteui-angular/grids/grid/src/grid.multi-row-layout.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid.multi-row-layout.spec.ts @@ -1,4 +1,4 @@ -import { TestBed, fakeAsync, tick, waitForAsync } from '@angular/core/testing'; +import { TestBed, fakeAsync, tick, waitForAsync } from '@angular/core/testing'; import { IgxGridComponent } from './grid.component'; import { Component, ViewChild } from '@angular/core'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; @@ -11,6 +11,7 @@ import { GridFunctions, GRID_MRL_BLOCK } from '../../../test-utils/grid-function import { IgxColumnGroupComponent } from 'igniteui-angular/grids/core'; import { IgxColumnComponent } from 'igniteui-angular/grids/core'; import { DefaultSortingStrategy, SortingDirection } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach } from 'vitest'; const GRID_COL_THEAD_CLASS = '.igx-grid-th'; const GRID_MRL_BLOCK_CLASS = `.${GRID_MRL_BLOCK}`; @@ -79,17 +80,17 @@ describe('IgxGrid - multi-row-layout #grid', () => { fixture.detectChanges(); // creating an incomplete layout fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 2, colStart: 1, colEnd: 4, rowEnd: 3 }, - { field: 'CompanyName', rowStart: 1, colStart: 1 }, - { field: 'PostalCode', rowStart: 1, colStart: 2 }, - // { field: 'Fax', rowStart: 1, colStart: 3}, - { field: 'Country', rowStart: 3, colStart: 1 }, - // { field: 'Region', rowStart: 3, colStart: 2}, - { field: 'Phone', rowStart: 3, colStart: 3 } - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 2, colStart: 1, colEnd: 4, rowEnd: 3 }, + { field: 'CompanyName', rowStart: 1, colStart: 1 }, + { field: 'PostalCode', rowStart: 1, colStart: 2 }, + // { field: 'Fax', rowStart: 1, colStart: 3}, + { field: 'Country', rowStart: 3, colStart: 1 }, + // { field: 'Region', rowStart: 3, colStart: 2}, + { field: 'Phone', rowStart: 3, colStart: 3 } + ] + }]; fixture.componentInstance.grid.width = '617px'; fixture.detectChanges(); const grid = fixture.componentInstance.grid; @@ -107,14 +108,14 @@ describe('IgxGrid - multi-row-layout #grid', () => { // creating an incomplete layout 2 fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, rowEnd: 3 }, - { field: 'CompanyName', rowStart: 3, colStart: 1 }, - // { field: 'PostalCode', rowStart: 1, colStart: 2}, - { field: 'Fax', rowStart: 3, colStart: 3 } - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, rowEnd: 3 }, + { field: 'CompanyName', rowStart: 3, colStart: 1 }, + // { field: 'PostalCode', rowStart: 1, colStart: 2}, + { field: 'Fax', rowStart: 3, colStart: 3 } + ] + }]; fixture.componentInstance.grid.width = '617px'; fixture.detectChanges(); sizes = grid.columnList.first.getGridTemplate(false).split(' ').map(width => parseFloat(width).toFixed(2) + "px").join(' '); @@ -226,14 +227,14 @@ describe('IgxGrid - multi-row-layout #grid', () => { const fixture = TestBed.createComponent(ColumnLayoutTestComponent); fixture.detectChanges(); fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ID', rowStart: 1, colStart: 1, width: '100px' }, - { field: 'CompanyName', rowStart: 1, colStart: 2, width: '200px' }, - { field: 'ContactName', rowStart: 1, colStart: 3, width: '300px' }, - { field: 'ContactTitle', rowStart: 2, colStart: 1, rowEnd: 4, colEnd: 4 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ID', rowStart: 1, colStart: 1, width: '100px' }, + { field: 'CompanyName', rowStart: 1, colStart: 2, width: '200px' }, + { field: 'ContactName', rowStart: 1, colStart: 3, width: '300px' }, + { field: 'ContactTitle', rowStart: 2, colStart: 1, rowEnd: 4, colEnd: 4 }, + ] + }]; fixture.detectChanges(); fixture.detectChanges(); const grid = fixture.componentInstance.grid; @@ -321,19 +322,19 @@ describe('IgxGrid - multi-row-layout #grid', () => { // creating an incomplete layout fixture.componentInstance.grid.width = '1200px'; fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4 }, - { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px' }, - { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px' }, - { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px' }, - { field: 'City', rowStart: 2, colStart: 3, colEnd: 5 }, - { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px' }, - { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px' }, - { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px' }, - { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4 }, + { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px' }, + { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px' }, + { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px' }, + { field: 'City', rowStart: 2, colStart: 3, colEnd: 5 }, + { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px' }, + { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px' }, + { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px' }, + { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, + ] + }]; fixture.detectChanges(); const grid = fixture.componentInstance.grid; const gridFirstRow = grid.rowList.first; @@ -353,19 +354,19 @@ describe('IgxGrid - multi-row-layout #grid', () => { // creating an incomplete layout fixture.componentInstance.grid.width = '1200px'; fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, width: '300px' }, - { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px' }, - { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px' }, - { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px' }, - { field: 'City', rowStart: 2, colStart: 3, colEnd: 5 }, - { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px' }, - { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px' }, - { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px' }, - { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, width: '300px' }, + { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px' }, + { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px' }, + { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px' }, + { field: 'City', rowStart: 2, colStart: 3, colEnd: 5 }, + { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px' }, + { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px' }, + { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px' }, + { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, + ] + }]; fixture.detectChanges(); const grid = fixture.componentInstance.grid; const gridFirstRow = grid.rowList.first; @@ -377,13 +378,12 @@ describe('IgxGrid - multi-row-layout #grid', () => { expect(groupRowBlocks[0].nativeElement.style.gridTemplateColumns).toEqual('200px 200px 100px 100px 100px 200px'); })); - it('should correctly size column without width when it overlaps partially with bigger column that has width bellow it', - fakeAsync(() => { - // In this case it would be for City column and 3rd template column overlapping width ContactName. - const fixture = TestBed.createComponent(ColumnLayoutTestComponent); - // creating an incomplete layout - fixture.componentInstance.grid.width = '1200px'; - fixture.componentInstance.colGroups = [{ + it('should correctly size column without width when it overlaps partially with bigger column that has width bellow it', fakeAsync(() => { + // In this case it would be for City column and 3rd template column overlapping width ContactName. + const fixture = TestBed.createComponent(ColumnLayoutTestComponent); + // creating an incomplete layout + fixture.componentInstance.grid.width = '1200px'; + fixture.componentInstance.colGroups = [{ group: 'group1', columns: [ { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 5, width: '200px' }, @@ -397,16 +397,16 @@ describe('IgxGrid - multi-row-layout #grid', () => { { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7, width: '200px' }, ] }]; - fixture.detectChanges(); - const grid = fixture.componentInstance.grid; - const gridFirstRow = grid.rowList.first; + fixture.detectChanges(); + const grid = fixture.componentInstance.grid; + const gridFirstRow = grid.rowList.first; - // headers are aligned to cells - GridFunctions.verifyLayoutHeadersAreAligned(grid, gridFirstRow); + // headers are aligned to cells + GridFunctions.verifyLayoutHeadersAreAligned(grid, gridFirstRow); - const groupRowBlocks = fixture.debugElement.query(By.css('.igx-grid__tbody')).queryAll(By.css(GRID_MRL_BLOCK_CLASS)); - expect(groupRowBlocks[0].nativeElement.style.gridTemplateColumns).toEqual('200px 200px 100px 100px 200px 150px'); - })); + const groupRowBlocks = fixture.debugElement.query(By.css('.igx-grid__tbody')).queryAll(By.css(GRID_MRL_BLOCK_CLASS)); + expect(groupRowBlocks[0].nativeElement.style.gridTemplateColumns).toEqual('200px 200px 100px 100px 200px 150px'); + })); it('should correctly set column width when there is bigger column at the bottom where there is not width yet', fakeAsync(() => { // In this case it would be for City column and 3rd template column. @@ -414,19 +414,19 @@ describe('IgxGrid - multi-row-layout #grid', () => { // creating an incomplete layout fixture.componentInstance.grid.width = '1200px'; fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4 }, - { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px' }, - { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px' }, - { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px' }, - { field: 'City', rowStart: 2, colStart: 3, colEnd: 5 }, - { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px' }, - { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px' }, - { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px' }, - { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7, width: '400px' }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4 }, + { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px' }, + { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px' }, + { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px' }, + { field: 'City', rowStart: 2, colStart: 3, colEnd: 5 }, + { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px' }, + { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px' }, + { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px' }, + { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7, width: '400px' }, + ] + }]; fixture.detectChanges(); const grid = fixture.componentInstance.grid; const gridFirstRow = grid.rowList.first; @@ -444,19 +444,19 @@ describe('IgxGrid - multi-row-layout #grid', () => { // creating an incomplete layout fixture.componentInstance.grid.width = '1200px'; fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, width: '360px' }, - { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px' }, - { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px' }, - { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px' }, - { field: 'City', rowStart: 2, colStart: 3, colEnd: 5 }, - { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px' }, - { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px' }, - { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px' }, - { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7, width: '400px' }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, width: '360px' }, + { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px' }, + { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px' }, + { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px' }, + { field: 'City', rowStart: 2, colStart: 3, colEnd: 5 }, + { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px' }, + { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px' }, + { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px' }, + { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7, width: '400px' }, + ] + }]; fixture.detectChanges(); const grid = fixture.componentInstance.grid; const gridFirstRow = grid.rowList.first; @@ -474,19 +474,19 @@ describe('IgxGrid - multi-row-layout #grid', () => { // creating an incomplete layout fixture.componentInstance.grid.width = '700px'; fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4 }, - { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px' }, - { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px' }, - { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px' }, - { field: 'City', rowStart: 2, colStart: 3, colEnd: 5 }, - { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px' }, - { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px' }, - { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px' }, - { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4 }, + { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px' }, + { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px' }, + { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px' }, + { field: 'City', rowStart: 2, colStart: 3, colEnd: 5 }, + { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px' }, + { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px' }, + { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3, width: '200px' }, + { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, + ] + }]; fixture.detectChanges(); const grid = fixture.componentInstance.grid; const gridFirstRow = grid.rowList.first; @@ -504,19 +504,19 @@ describe('IgxGrid - multi-row-layout #grid', () => { // creating an incomplete layout fixture.componentInstance.grid.width = '700px'; fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4 }, - { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px' }, - { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px' }, - { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3 }, - { field: 'City', rowStart: 2, colStart: 3, colEnd: 5 }, - { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px' }, - { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px' }, - { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3 }, - { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4 }, + { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px' }, + { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7, width: '200px' }, + { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3 }, + { field: 'City', rowStart: 2, colStart: 3, colEnd: 5 }, + { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7, width: '200px' }, + { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2, width: '200px' }, + { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3 }, + { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, + ] + }]; fixture.detectChanges(); const grid = fixture.componentInstance.grid; const gridFirstRow = grid.rowList.first; @@ -528,13 +528,12 @@ describe('IgxGrid - multi-row-layout #grid', () => { expect(groupRowBlocks[0].nativeElement.style.gridTemplateColumns).toEqual('200px 136px 136px 100px 100px 200px'); })); - it('should use column width of a column with span 2 that has width when there are no columns with span 1 to take width from', - fakeAsync(() => { - // In this case it would be for Phone, CompanyName and PostalCode columns and first 2 template columns. - const fixture = TestBed.createComponent(ColumnLayoutTestComponent); - // creating an incomplete layout - fixture.componentInstance.grid.width = '700px'; - fixture.componentInstance.colGroups = [{ + it('should use column width of a column with span 2 that has width when there are no columns with span 1 to take width from', fakeAsync(() => { + // In this case it would be for Phone, CompanyName and PostalCode columns and first 2 template columns. + const fixture = TestBed.createComponent(ColumnLayoutTestComponent); + // creating an incomplete layout + fixture.componentInstance.grid.width = '700px'; + fixture.componentInstance.colGroups = [{ group: 'group1', columns: [ { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4 }, @@ -548,16 +547,16 @@ describe('IgxGrid - multi-row-layout #grid', () => { { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, ] }]; - fixture.detectChanges(); - const grid = fixture.componentInstance.grid; - const gridFirstRow = grid.rowList.first; + fixture.detectChanges(); + const grid = fixture.componentInstance.grid; + const gridFirstRow = grid.rowList.first; - // headers are aligned to cells - GridFunctions.verifyLayoutHeadersAreAligned(grid, gridFirstRow); + // headers are aligned to cells + GridFunctions.verifyLayoutHeadersAreAligned(grid, gridFirstRow); - const groupRowBlocks = fixture.debugElement.query(By.css('.igx-grid__tbody')).queryAll(By.css(GRID_MRL_BLOCK_CLASS)); - expect(groupRowBlocks[0].nativeElement.style.gridTemplateColumns).toEqual('100px 100px 136px 100px 100px 200px'); - })); + const groupRowBlocks = fixture.debugElement.query(By.css('.igx-grid__tbody')).queryAll(By.css(GRID_MRL_BLOCK_CLASS)); + expect(groupRowBlocks[0].nativeElement.style.gridTemplateColumns).toEqual('100px 100px 136px 100px 100px 200px'); + })); it('should use divided column width when there is stairway type of defined columns and they have widths set', fakeAsync(() => { // In this case it would be for Country and Address columns and last 3 template columns. @@ -565,19 +564,19 @@ describe('IgxGrid - multi-row-layout #grid', () => { // creating an incomplete layout fixture.componentInstance.grid.width = '700px'; fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4 }, - { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px' }, - { field: 'Country', rowStart: 1, colStart: 6, colEnd: 8, width: '200px' }, - { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px' }, - { field: 'City', rowStart: 2, colStart: 3, colEnd: 5 }, - { field: 'Address', rowStart: 2, colStart: 5, colEnd: 8, width: '150px' }, - { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2 }, - { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3 }, - { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 8 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4 }, + { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6, width: '200px' }, + { field: 'Country', rowStart: 1, colStart: 6, colEnd: 8, width: '200px' }, + { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3, width: '200px' }, + { field: 'City', rowStart: 2, colStart: 3, colEnd: 5 }, + { field: 'Address', rowStart: 2, colStart: 5, colEnd: 8, width: '150px' }, + { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2 }, + { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3 }, + { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 8 }, + ] + }]; fixture.detectChanges(); const grid = fixture.componentInstance.grid; const gridFirstRow = grid.rowList.first; @@ -595,14 +594,14 @@ describe('IgxGrid - multi-row-layout #grid', () => { const grid = fixture.componentInstance.grid; fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ID', rowStart: 1, colStart: 1, width: '10%' }, - { field: 'CompanyName', rowStart: 1, colStart: 2, width: '20%' }, - { field: 'ContactName', rowStart: 1, colStart: 3, width: '30%' }, - { field: 'ContactTitle', rowStart: 2, colStart: 1, rowEnd: 4, colEnd: 4 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ID', rowStart: 1, colStart: 1, width: '10%' }, + { field: 'CompanyName', rowStart: 1, colStart: 2, width: '20%' }, + { field: 'ContactName', rowStart: 1, colStart: 3, width: '30%' }, + { field: 'ContactTitle', rowStart: 2, colStart: 1, rowEnd: 4, colEnd: 4 }, + ] + }]; fixture.detectChanges(); fixture.componentInstance.grid.width = (1000 + grid.scrollSize) + 'px'; fixture.detectChanges(); @@ -651,16 +650,16 @@ describe('IgxGrid - multi-row-layout #grid', () => { GridFunctions.verifyDOMMatchesLayoutSettings(grid, gridFirstRow, fixture.componentInstance.colGroups); fixture.componentInstance.colGroups = [{ - group: 'group3', - columns: [ - { field: 'ID', rowStart: 1, colStart: 1 }, - { field: 'CompanyName', rowStart: 1, colStart: 2 }, - { field: 'ContactName', rowStart: 1, colStart: 3 }, - { field: 'Country', rowStart: 2, colStart: 1, colEnd: 3 }, - { field: 'Region', rowStart: 2, colStart: 3 }, - { field: 'ContactTitle', rowStart: 3, colStart: 1, rowEnd: 5, colEnd: 4, width: '60%' }, - ] - }]; + group: 'group3', + columns: [ + { field: 'ID', rowStart: 1, colStart: 1 }, + { field: 'CompanyName', rowStart: 1, colStart: 2 }, + { field: 'ContactName', rowStart: 1, colStart: 3 }, + { field: 'Country', rowStart: 2, colStart: 1, colEnd: 3 }, + { field: 'Region', rowStart: 2, colStart: 3 }, + { field: 'ContactTitle', rowStart: 3, colStart: 1, rowEnd: 5, colEnd: 4, width: '60%' }, + ] + }]; fixture.detectChanges(); fixture.detectChanges(); @@ -687,14 +686,14 @@ describe('IgxGrid - multi-row-layout #grid', () => { const fixture = TestBed.createComponent(ColumnLayoutTestComponent); const grid = fixture.componentInstance.grid; fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ID', rowStart: 1, colStart: 1 }, - { field: 'CompanyName', rowStart: 1, colStart: 2 }, - { field: 'ContactName', rowStart: 1, colStart: 3, colEnd: 5 }, - { field: 'ContactTitle', rowStart: 2, colStart: 1, rowEnd: 3, colEnd: 4 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ID', rowStart: 1, colStart: 1 }, + { field: 'CompanyName', rowStart: 1, colStart: 2 }, + { field: 'ContactName', rowStart: 1, colStart: 3, colEnd: 5 }, + { field: 'ContactTitle', rowStart: 2, colStart: 1, rowEnd: 3, colEnd: 4 }, + ] + }]; fixture.componentInstance.grid.width = '100%'; fixture.detectChanges(); @@ -712,14 +711,14 @@ describe('IgxGrid - multi-row-layout #grid', () => { const fixture = TestBed.createComponent(ColumnLayoutTestComponent); const grid = fixture.componentInstance.grid; fixture.componentInstance.colGroups = [{ - group: 'group2', - columns: [ - { field: 'ContactName', rowStart: 2, colStart: 1, colEnd: 4, rowEnd: 4, width: '500px' }, - { field: 'CompanyName', rowStart: 1, colStart: 1, width: '100px' }, - { field: 'PostalCode', rowStart: 1, colStart: 2, width: '200px' }, - { field: 'Fax', rowStart: 1, colStart: 3, width: '100px' } - ] - }]; + group: 'group2', + columns: [ + { field: 'ContactName', rowStart: 2, colStart: 1, colEnd: 4, rowEnd: 4, width: '500px' }, + { field: 'CompanyName', rowStart: 1, colStart: 1, width: '100px' }, + { field: 'PostalCode', rowStart: 1, colStart: 2, width: '200px' }, + { field: 'Fax', rowStart: 1, colStart: 3, width: '100px' } + ] + }]; fixture.detectChanges(); // check group blocks @@ -728,14 +727,14 @@ describe('IgxGrid - multi-row-layout #grid', () => { expect(groupHeaderBlocks[0].clientWidth).toBe(400); expect((groupHeaderBlocks[0] as HTMLElement).style.gridTemplateColumns).toBe('100px 200px 100px'); fixture.componentInstance.colGroups = [{ - group: 'group2', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, rowEnd: 2, width: '500px' }, - { field: 'CompanyName', rowStart: 2, colStart: 1, width: '100px' }, - { field: 'PostalCode', rowStart: 2, colStart: 2, width: '200px' }, - { field: 'Fax', rowStart: 2, colStart: 3, width: '100px' } - ] - }]; + group: 'group2', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4, rowEnd: 2, width: '500px' }, + { field: 'CompanyName', rowStart: 2, colStart: 1, width: '100px' }, + { field: 'PostalCode', rowStart: 2, colStart: 2, width: '200px' }, + { field: 'Fax', rowStart: 2, colStart: 3, width: '100px' } + ] + }]; fixture.detectChanges(); // check group blocks groupHeaderBlocks = grid.theadRow.nativeElement.querySelectorAll(GRID_MRL_BLOCK_CLASS); @@ -780,7 +779,8 @@ describe('IgxGrid - multi-row-layout #grid', () => { { field: 'PostalCode', rowStart: 2, colStart: 2 }, { field: 'Fax', rowStart: 2, colStart: 3 } ] - }]; + } + ]; fixture.detectChanges(); // check first group has height of 2 row spans in header and rows but the header itself should span 1 row @@ -881,8 +881,7 @@ describe('IgxGrid - multi-row-layout #grid', () => { const gridFirstRow = grid.rowList.first; GridFunctions.verifyLayoutHeadersAreAligned(grid, gridFirstRow); - GridFunctions.verifyDOMMatchesLayoutSettings(grid, gridFirstRow, - fixture.componentInstance.colGroups.slice(0, horizontalVirtualization.state.chunkSize)); + GridFunctions.verifyDOMMatchesLayoutSettings(grid, gridFirstRow, fixture.componentInstance.colGroups.slice(0, horizontalVirtualization.state.chunkSize)); // check last column group can be scrolled in view horizontalVirtualization.scrollTo(11); @@ -890,10 +889,7 @@ describe('IgxGrid - multi-row-layout #grid', () => { fixture.detectChanges(); // last 3 blocks should be rendered - GridFunctions.verifyDOMMatchesLayoutSettings(grid, grid.rowList.first, - fixture.componentInstance.colGroups.slice( - horizontalVirtualization.state.startIndex, - horizontalVirtualization.state.startIndex + horizontalVirtualization.state.chunkSize)); + GridFunctions.verifyDOMMatchesLayoutSettings(grid, grid.rowList.first, fixture.componentInstance.colGroups.slice(horizontalVirtualization.state.startIndex, horizontalVirtualization.state.startIndex + horizontalVirtualization.state.chunkSize)); }); @@ -901,15 +897,15 @@ describe('IgxGrid - multi-row-layout #grid', () => { const fixture = TestBed.createComponent(ColumnLayoutTestComponent); // test with px fixture.componentInstance.colGroups = [{ - group: 'group1', - // total colspan 3 - columns: [ - { field: 'Address', rowStart: 1, colStart: 1, colEnd: 4, rowEnd: 3 }, - { field: 'County', rowStart: 3, colStart: 1, width: '200px' }, - { field: 'Region', rowStart: 3, colStart: 2, width: '300px' }, - { field: 'City', rowStart: 3, colStart: 3, width: '200px' } - ] - }]; + group: 'group1', + // total colspan 3 + columns: [ + { field: 'Address', rowStart: 1, colStart: 1, colEnd: 4, rowEnd: 3 }, + { field: 'County', rowStart: 3, colStart: 1, width: '200px' }, + { field: 'Region', rowStart: 3, colStart: 2, width: '300px' }, + { field: 'City', rowStart: 3, colStart: 3, width: '200px' } + ] + }]; fixture.componentInstance.grid.width = '617px'; fixture.detectChanges(); tick(); // Required to render scrollbars @@ -985,17 +981,17 @@ describe('IgxGrid - multi-row-layout #grid', () => { const fixture = TestBed.createComponent(ColumnLayoutTestComponent); const grid = fixture.componentInstance.grid; fixture.componentInstance.colGroups = [{ - group: 'group4', - // total rowspan 3 - columns: [ - { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, - { field: 'Phone', rowStart: 1, colStart: 3, rowEnd: 3 }, - { field: 'Address', rowStart: 1, colStart: 4, rowEnd: 4 }, - { field: 'Region', rowStart: 2, colStart: 1 }, - { field: 'City', rowStart: 2, colStart: 2 }, - { field: 'ContactName', rowStart: 3, colStart: 1, colEnd: 4 }, - ] - }]; + group: 'group4', + // total rowspan 3 + columns: [ + { field: 'CompanyName', rowStart: 1, colStart: 1, colEnd: 3 }, + { field: 'Phone', rowStart: 1, colStart: 3, rowEnd: 3 }, + { field: 'Address', rowStart: 1, colStart: 4, rowEnd: 4 }, + { field: 'Region', rowStart: 2, colStart: 1 }, + { field: 'City', rowStart: 2, colStart: 2 }, + { field: 'ContactName', rowStart: 3, colStart: 1, colEnd: 4 }, + ] + }]; fixture.detectChanges(); const rows = fixture.debugElement.query(By.css('.igx-grid__tbody')).queryAll(By.css('igx-grid-row')); @@ -1040,19 +1036,19 @@ describe('IgxGrid - multi-row-layout #grid', () => { fixture.componentInstance.grid.columnWidth = '10%'; fixture.detectChanges(); fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4 }, - { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6 }, - { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7 }, - { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3 }, - { field: 'City', rowStart: 2, colStart: 3, colEnd: 5 }, - { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7 }, - { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2 }, - { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3 }, - { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4 }, + { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6 }, + { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7 }, + { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3 }, + { field: 'City', rowStart: 2, colStart: 3, colEnd: 5 }, + { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7 }, + { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2 }, + { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3 }, + { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, + ] + }]; fixture.detectChanges(); const grid = fixture.componentInstance.grid; const gridFirstRow = grid.rowList.first; @@ -1067,19 +1063,19 @@ describe('IgxGrid - multi-row-layout #grid', () => { it('should disregard hideGroupedColumns option and not hide columns when grouping when having column layouts.', fakeAsync(() => { const fixture = TestBed.createComponent(ColumnLayoutTestComponent); fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4 }, - { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6 }, - { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7 }, - { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3 }, - { field: 'City', rowStart: 2, colStart: 3, colEnd: 5 }, - { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7 }, - { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2 }, - { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3 }, - { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, - ] - }]; + group: 'group1', + columns: [ + { field: 'ContactName', rowStart: 1, colStart: 1, colEnd: 4 }, + { field: 'ContactTitle', rowStart: 1, colStart: 4, colEnd: 6 }, + { field: 'Country', rowStart: 1, colStart: 6, colEnd: 7 }, + { field: 'Phone', rowStart: 2, colStart: 1, colEnd: 3 }, + { field: 'City', rowStart: 2, colStart: 3, colEnd: 5 }, + { field: 'Address', rowStart: 2, colStart: 5, colEnd: 7 }, + { field: 'CompanyName', rowStart: 3, colStart: 1, colEnd: 2 }, + { field: 'PostalCode', rowStart: 3, colStart: 2, colEnd: 3 }, + { field: 'Fax', rowStart: 3, colStart: 3, colEnd: 7 }, + ] + }]; const grid = fixture.componentInstance.grid; grid.hideGroupedColumns = true; fixture.detectChanges(); @@ -1099,13 +1095,13 @@ describe('IgxGrid - multi-row-layout #grid', () => { it('should get the correct next and previous cell when in MRL scenario', fakeAsync(() => { const fixture = TestBed.createComponent(ColumnLayoutTestComponent); fixture.componentInstance.colGroups = [{ - group: 'group1', - columns: [ - { field: 'CompanyName', rowStart: 1, rowEnd: 2, colStart: 3, colEnd: 4, dataType: 'number', editable: true }, - { field: 'ID', rowStart: 1, rowEnd: 2, colStart: 1, colEnd: 2, dataType: 'number', editable: false }, - { field: 'ContactName', rowStart: 1, rowEnd: 2, colStart: 2, colEnd: 3, dataType: 'string', editable: false }, - ] - }]; + group: 'group1', + columns: [ + { field: 'CompanyName', rowStart: 1, rowEnd: 2, colStart: 3, colEnd: 4, dataType: 'number', editable: true }, + { field: 'ID', rowStart: 1, rowEnd: 2, colStart: 1, colEnd: 2, dataType: 'number', editable: false }, + { field: 'ContactName', rowStart: 1, rowEnd: 2, colStart: 2, colEnd: 3, dataType: 'string', editable: false }, + ] + }]; const grid = fixture.componentInstance.grid; fixture.detectChanges(); let pos: ICellPosition; @@ -1202,5 +1198,4 @@ export class ColumnLayoutTestComponent { imports: [IgxGridComponent, IgxColumnLayoutComponent, IgxColumnComponent, IgxColumnGroupComponent] }) export class ColumnLayoutAndGroupsTestComponent extends ColumnLayoutTestComponent { - } diff --git a/projects/igniteui-angular/grids/grid/src/grid.nested.props.spec.ts b/projects/igniteui-angular/grids/grid/src/grid.nested.props.spec.ts index 68ae5746d03..135b6c6d904 100644 --- a/projects/igniteui-angular/grids/grid/src/grid.nested.props.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid.nested.props.spec.ts @@ -8,6 +8,7 @@ import { IGridEditEventArgs, IgxCellEditorTemplateDirective, IgxCellTemplateDire import { FormsModule } from '@angular/forms'; import { IgxComboComponent } from 'igniteui-angular/combo'; import { cloneArray, columnFieldPath, IgxStringFilteringOperand, resolveNestedPath, SortingDirection } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const first = (array: T[]): T => array[0]; @@ -170,7 +171,10 @@ class NestedPropertyGridComponent { public combo: IgxComboComponent; public locations = LOCATIONS; - public parseArray(arr: { id: number; shop: string }[]): string { + public parseArray(arr: { + id: number; + shop: string; + }[]): string { return (arr || []).map((e) => e.shop).join(', '); } } @@ -183,12 +187,8 @@ describe('Grid - nested data source properties #grid', () => { describe('API', () => { it('should correctly resolve key paths in nested data', () => { - expect( - DATA.map(record => resolveNestedPath(record, columnFieldPath("user.name.first"))) - ).toEqual(NAMES); - expect( - DATA.map(record => resolveNestedPath(record, columnFieldPath("user.age"))) - ).toEqual(AGES); + expect(DATA.map(record => resolveNestedPath(record, columnFieldPath("user.name.first")))).toEqual(NAMES); + expect(DATA.map(record => resolveNestedPath(record, columnFieldPath("user.age")))).toEqual(AGES); }); }); @@ -516,8 +516,8 @@ describe('Edit cell with data of type Array #grid', () => { const copiedData = cloneArray(DATA2, true); setupData(copiedData); - spyOn(grid.cellEditEnter, 'emit').and.callThrough(); - spyOn(grid.cellEditExit, 'emit').and.callThrough(); + vi.spyOn(grid.cellEditEnter, 'emit'); + vi.spyOn(grid.cellEditExit, 'emit'); const cell = grid.getCellByColumn(2, 'locations'); let initialRowData = { ...cell.row.data }; @@ -538,7 +538,7 @@ describe('Edit cell with data of type Array #grid', () => { cancel: false, column: cell.column, owner: grid, - event: jasmine.anything() as any, + event: expect.anything() as any, valid: true }; @@ -579,10 +579,10 @@ describe('Edit cell with data of type Array #grid', () => { const copiedData = cloneArray(DATA2, true); setupData(copiedData); - spyOn(grid.cellEditEnter, 'emit').and.callThrough(); - spyOn(grid.cellEdit, 'emit').and.callThrough(); - spyOn(grid.cellEditDone, 'emit').and.callThrough(); - spyOn(grid.cellEditExit, 'emit').and.callThrough(); + vi.spyOn(grid.cellEditEnter, 'emit'); + vi.spyOn(grid.cellEdit, 'emit'); + vi.spyOn(grid.cellEditDone, 'emit'); + vi.spyOn(grid.cellEditExit, 'emit'); const cell = grid.getCellByColumn(2, 'locations'); let initialRowData = { ...cell.row.data }; @@ -603,7 +603,7 @@ describe('Edit cell with data of type Array #grid', () => { cancel: false, column: cell.column, owner: grid, - event: jasmine.anything() as any, + event: expect.anything() as any, valid: true }; @@ -650,8 +650,8 @@ describe('Edit cell with data of type Array #grid', () => { const copiedData = cloneArray(DATA2, true); setupData(copiedData, true); - spyOn(grid.rowEditEnter, 'emit').and.callThrough(); - spyOn(grid.rowEditExit, 'emit').and.callThrough(); + vi.spyOn(grid.rowEditEnter, 'emit'); + vi.spyOn(grid.rowEditExit, 'emit'); const cell = grid.getCellByColumn(2, 'locations'); const row = grid.gridAPI.get_row_by_index(2); @@ -673,7 +673,7 @@ describe('Edit cell with data of type Array #grid', () => { owner: grid, isAddRow: row.addRowUI, cancel: false, - event: jasmine.anything() as any, + event: expect.anything() as any, valid: true }; @@ -714,10 +714,10 @@ describe('Edit cell with data of type Array #grid', () => { const copiedData = cloneArray(DATA2, true); setupData(copiedData, true); - spyOn(grid.rowEditEnter, 'emit').and.callThrough(); - spyOn(grid.rowEdit, 'emit').and.callThrough(); - spyOn(grid.rowEditDone, 'emit').and.callThrough(); - spyOn(grid.rowEditExit, 'emit').and.callThrough(); + vi.spyOn(grid.rowEditEnter, 'emit'); + vi.spyOn(grid.rowEdit, 'emit'); + vi.spyOn(grid.rowEditDone, 'emit'); + vi.spyOn(grid.rowEditExit, 'emit'); const cell = grid.getCellByColumn(2, 'locations'); const row = grid.gridAPI.get_row_by_index(2); @@ -739,7 +739,7 @@ describe('Edit cell with data of type Array #grid', () => { owner: grid, isAddRow: row.addRowUI, cancel: false, - event: jasmine.anything() as any, + event: expect.anything() as any, valid: true }; diff --git a/projects/igniteui-angular/grids/grid/src/grid.pagination.spec.ts b/projects/igniteui-angular/grids/grid/src/grid.pagination.spec.ts index 190a428e498..0c607f62e4d 100644 --- a/projects/igniteui-angular/grids/grid/src/grid.pagination.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid.pagination.spec.ts @@ -7,12 +7,13 @@ import { wait } from '../../../test-utils/ui-interactions.spec'; import { GridFunctions, PAGER_CLASS } from '../../../test-utils/grid-functions.spec'; import { ControlsFunction, BUTTON_DISABLED_CLASS } from '../../../test-utils/controls-functions.spec'; import { IgxNumberFilteringOperand } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const verifyGridPager = (fix, rowsCount, firstCellValue, pagerText, buttonsVisibility) => { const grid = fix.componentInstance.grid; expect(grid.getCellByColumn(0, 'ID').value).toMatch(firstCellValue); - expect(grid.rowList.length).toEqual(rowsCount, 'Invalid number of rows initialized'); + expect(grid.rowList.length, 'Invalid number of rows initialized').toEqual(rowsCount); if (pagerText != null) { expect(grid.nativeElement.querySelector(PAGER_CLASS)).toBeDefined(); @@ -86,7 +87,7 @@ describe('IgxGrid - Grid Paging #grid', () => { fix.detectChanges(); // Goto page 3 through API and listen for event - spyOn(paginator.pagingDone, 'emit'); + vi.spyOn(paginator.pagingDone, 'emit'); paginator.paginate(2); fix.detectChanges(); @@ -148,14 +149,14 @@ describe('IgxGrid - Grid Paging #grid', () => { fix.detectChanges(); expect(paginator).toBeDefined(); - expect(paginator.perPage).toEqual(5, 'Invalid page size'); + expect(paginator.perPage, 'Invalid page size').toEqual(5); expect(grid.totalRecords).toBe(10); verifyGridPager(fix, 5, '1', '1\xA0of\xA02', []); grid.totalRecords = 4; fix.detectChanges(); - expect(paginator.perPage).toEqual(5, 'Invalid page size'); + expect(paginator.perPage, 'Invalid page size').toEqual(5); expect(grid.totalRecords).toBe(4); verifyGridPager(fix, 4, '1', '1\xA0of\xA01', []); }); @@ -164,7 +165,7 @@ describe('IgxGrid - Grid Paging #grid', () => { it('change paging settings UI', () => { fix.detectChanges(); expect(paginator).toBeDefined(); - expect(paginator.perPage).toEqual(3, 'Invalid page size'); + expect(paginator.perPage, 'Invalid page size').toEqual(3); verifyGridPager(fix, 3, '1', '1\xA0of\xA04', []); @@ -174,7 +175,7 @@ describe('IgxGrid - Grid Paging #grid', () => { ControlsFunction.clickDropDownItem(fix, 2); expect(paginator).toBeDefined(); - expect(paginator.perPage).toEqual(10, 'Invalid page size'); + expect(paginator.perPage, 'Invalid page size').toEqual(10); verifyGridPager(fix, 10, '1', '1\xA0of\xA01', []); }); @@ -185,7 +186,7 @@ describe('IgxGrid - Grid Paging #grid', () => { fix.detectChanges(); expect(paginator).toBeDefined(); - expect(paginator.perPage).toEqual(2, 'Invalid page size'); + expect(paginator.perPage, 'Invalid page size').toEqual(2); verifyGridPager(fix, 2, '1', '1\xA0of\xA05', []); // Turn off paging @@ -211,7 +212,7 @@ describe('IgxGrid - Grid Paging #grid', () => { fix.detectChanges(); expect(grid.paginator).toBeDefined(); - expect(paginator.perPage).toEqual(2, 'Invalid page size'); + expect(paginator.perPage, 'Invalid page size').toEqual(2); verifyGridPager(fix, 2, '3', '2\xA0of\xA05', []); // Change page size to be 5 @@ -475,7 +476,7 @@ describe('IgxGrid - Grid Paging #grid', () => { tick(); expect(grid.page).toBe(desiredPageIndex); - expect(grid.getRowByIndex(0).cells[1].value).toBe('Debra Morton') + expect(grid.getRowByIndex(0).cells[1].value).toBe('Debra Morton'); expect(grid.getRowByIndex(0).viewIndex).toBe(6); })); }); diff --git a/projects/igniteui-angular/grids/grid/src/grid.pinning.spec.ts b/projects/igniteui-angular/grids/grid/src/grid.pinning.spec.ts index a0c9814d68d..a6773acd518 100644 --- a/projects/igniteui-angular/grids/grid/src/grid.pinning.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid.pinning.spec.ts @@ -1,32 +1,15 @@ -import { TestBed, fakeAsync, tick, waitForAsync } from '@angular/core/testing'; +import { TestBed, fakeAsync, tick, waitForAsync } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { GridSelectionMode, IgxGridHeaderRowComponent, IgxGridMRLNavigationService, IPinningConfig, RowPinningPosition } from 'igniteui-angular/grids/core'; import { wait, UIInteractions } from '../../../test-utils/ui-interactions.spec'; -import { - CELL_PINNED_CLASS, - GRID_MRL_BLOCK, - GRID_SCROLL_CLASS, - GridFunctions, - GridSelectionFunctions, - GridSummaryFunctions, - HEADER_PINNED_CLASS, - PINNED_SUMMARY -} from '../../../test-utils/grid-functions.spec'; -import { - GridFeaturesComponent, - GridPinningMRLComponent, - MRLTestComponent, - MultiColumnHeadersComponent, - MultiColumnHeadersWithGroupingComponent, - PinningComponent, - PinOnBothSidesInitComponent, - PinOnInitAndSelectionComponent -} from '../../../test-utils/grid-samples.spec'; +import { CELL_PINNED_CLASS, GRID_MRL_BLOCK, GRID_SCROLL_CLASS, GridFunctions, GridSelectionFunctions, GridSummaryFunctions, HEADER_PINNED_CLASS, PINNED_SUMMARY } from '../../../test-utils/grid-functions.spec'; +import { GridFeaturesComponent, GridPinningMRLComponent, MRLTestComponent, MultiColumnHeadersComponent, MultiColumnHeadersWithGroupingComponent, PinningComponent, PinOnBothSidesInitComponent, PinOnInitAndSelectionComponent } from '../../../test-utils/grid-samples.spec'; import { IgxGridComponent } from './grid.component'; import { DropPosition } from 'igniteui-angular/grids/core'; import { clearGridSubs, setupGridScrollDetection } from '../../../test-utils/helper-utils.spec'; import { ColumnPinningPosition, IgxStringFilteringOperand, SortingDirection } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxGrid - Column Pinning #grid', () => { @@ -47,7 +30,7 @@ describe('IgxGrid - Column Pinning #grid', () => { IgxGridMRLNavigationService ] }).compileComponents(); - })) + })); describe('To Start', () => { @@ -342,7 +325,7 @@ describe('IgxGrid - Column Pinning #grid', () => { it('should emit columnPin event and allow changing the insertAtIndex param.', () => { - spyOn(grid.columnPin, 'emit').and.callThrough(); + vi.spyOn(grid.columnPin, 'emit'); const idCol = grid.getColumnByName('ID'); const idColIndex = idCol.index; @@ -619,10 +602,8 @@ describe('IgxGrid - Column Pinning #grid', () => { fix.detectChanges(); const summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 9, - ['Count'], ['27']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 10, - ['Count'], ['27']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 9, ['Count'], ['27']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 10, ['Count'], ['27']); const pinnedSummaryCells = GridSummaryFunctions.getRootPinnedSummaryCells(fix); expect(pinnedSummaryCells[0].classes[`${PINNED_SUMMARY}-first`]) @@ -732,8 +713,8 @@ describe('IgxGrid - Column Pinning #grid', () => { // check correct headers have left border const firstPinnedHeader = grid.headerGroupsList.find(group => group.isPinned); // The first child of the header is the
wrapping the MRL block - expect(firstPinnedHeader.nativeElement.firstElementChild.classList.contains(GRID_MRL_BLOCK)).toBeTrue(); - expect(firstPinnedHeader.nativeElement.firstElementChild.classList.contains(`${HEADER_PINNED_CLASS}-first`)).toBeTrue(); + expect(firstPinnedHeader.nativeElement.firstElementChild.classList.contains(GRID_MRL_BLOCK)).toBe(true); + expect(firstPinnedHeader.nativeElement.firstElementChild.classList.contains(`${HEADER_PINNED_CLASS}-first`)).toBe(true); })); it('should correctly add pinned columns to the right of the already fixed one', () => { @@ -956,7 +937,7 @@ describe('IgxGrid - Column Pinning #grid', () => { const elem = row.children[i + 1]; const rect = elem.getBoundingClientRect(); expect(rect.x).toBe(initialStart); - initialStart += rect.width + initialStart += rect.width; } // check pinnedStart cells are rendered before main display container @@ -973,8 +954,8 @@ describe('IgxGrid - Column Pinning #grid', () => { expect(pinnedHeaders.length).toBe(10); expect(pinnedHeaders.map(x => x.column.header || x.column.field)) .toEqual(['General Information', 'CompanyName', 'Person Details', - 'ContactName', 'ContactTitle', 'Address Information', - 'Country', 'Region', 'City', 'Address']); + 'ContactName', 'ContactTitle', 'Address Information', + 'Country', 'Region', 'City', 'Address']); }); @@ -1008,7 +989,7 @@ describe('IgxGrid - Column Pinning #grid', () => { expect(unpinned.length).toBe(3); // check visible indexes - expect(rootMRLGroups.map(x => x.visibleIndex)).toEqual([0, 2, 1]) + expect(rootMRLGroups.map(x => x.visibleIndex)).toEqual([0, 2, 1]); })); }); diff --git a/projects/igniteui-angular/grids/grid/src/grid.pipes.ts b/projects/igniteui-angular/grids/grid/src/grid.pipes.ts index a9adaae6fc0..9d03b2ffd32 100644 --- a/projects/igniteui-angular/grids/grid/src/grid.pipes.ts +++ b/projects/igniteui-angular/grids/grid/src/grid.pipes.ts @@ -119,7 +119,7 @@ export class IgxGridUnmergeActivePipe implements PipeTransform { return collection; } - let result = cloneArray(collection) as any; + const result = cloneArray(collection) as any; uniqueRoots.forEach(x => { const index = collection.indexOf(x); const colKeys = [...x.cellMergeMeta.keys()]; diff --git a/projects/igniteui-angular/grids/grid/src/grid.search.spec.ts b/projects/igniteui-angular/grids/grid/src/grid.search.spec.ts index 05b706b6dc8..5373bb4571e 100644 --- a/projects/igniteui-angular/grids/grid/src/grid.search.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid.search.spec.ts @@ -12,13 +12,16 @@ import { IgxTextHighlightDirective } from 'igniteui-angular/directives'; import { GridFunctions } from '../../../test-utils/grid-functions.spec'; import { firstValueFrom } from 'rxjs'; import { DefaultSortingStrategy, GridColumnDataType, IgxStringFilteringOperand, SortingDirection } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; describe('IgxGrid - search API #grid', () => { const CELL_CSS_CLASS = '.igx-grid__td'; const HIGHLIGHT_CSS_CLASS = '.igx-highlight'; const HIGHLIGHT_ACTIVE_CSS_CLASS = '.igx-highlight__active'; let fix: ComponentFixture; - let component; let grid: IgxGridComponent; let fixNativeElement; + let component; + let grid: IgxGridComponent; + let fixNativeElement; beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ @@ -30,7 +33,7 @@ describe('IgxGrid - search API #grid', () => { ScrollableGridSearchComponent ] }).compileComponents(); - })) + })); describe('BasicGrid - ', () => { beforeEach(() => { @@ -280,7 +283,7 @@ describe('IgxGrid - search API #grid', () => { expect(activeHighlight).toBe(highlights[0]); }); - xit('Should scroll properly when using paging', () => { + it.skip('Should scroll properly when using paging', () => { fix.componentInstance.paging = true; grid.height = '240px'; grid.paginator.perPage = 7; @@ -940,16 +943,16 @@ describe('IgxGrid - search API #grid', () => { expect(highlight !== null).toBeTruthy(); grid.groupBy([{ - fieldName: 'JobTitle', - dir: SortingDirection.Asc, - ignoreCase: true, - strategy: DefaultSortingStrategy.instance() - }, { - fieldName: 'Company', - dir: SortingDirection.Desc, - ignoreCase: true, - strategy: DefaultSortingStrategy.instance() - }]); + fieldName: 'JobTitle', + dir: SortingDirection.Asc, + ignoreCase: true, + strategy: DefaultSortingStrategy.instance() + }, { + fieldName: 'Company', + dir: SortingDirection.Desc, + ignoreCase: true, + strategy: DefaultSortingStrategy.instance() + }]); fix.detectChanges(); cell = grid.gridAPI.get_cell_by_index(4, 'JobTitle'); highlight = cell.nativeElement.querySelector(HIGHLIGHT_ACTIVE_CSS_CLASS); diff --git a/projects/igniteui-angular/grids/grid/src/grid.sorting.spec.ts b/projects/igniteui-angular/grids/grid/src/grid.sorting.spec.ts index dbc3a45c4cf..3a2a0dd21bd 100644 --- a/projects/igniteui-angular/grids/grid/src/grid.sorting.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid.sorting.spec.ts @@ -8,6 +8,7 @@ import { SampleTestData } from '../../../test-utils/sample-test-data.spec'; import { CellType } from 'igniteui-angular/grids/core'; import { DefaultSortingStrategy, FormattedValuesSortingStrategy, NoopSortingStrategy, SortingDirection } from 'igniteui-angular/core'; import { By } from '@angular/platform-browser'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxGrid - Grid Sorting #grid', () => { @@ -36,8 +37,8 @@ describe('IgxGrid - Grid Sorting #grid', () => { describe('API tests', () => { it('Should sort grid ascending by column name', fakeAsync(() => { - spyOn(grid.sorting, 'emit').and.callThrough(); - spyOn(grid.sortingDone, 'emit').and.callThrough(); + vi.spyOn(grid.sorting, 'emit'); + vi.spyOn(grid.sortingDone, 'emit'); const currentColumn = 'Name'; const lastNameColumn = 'LastName'; const nameHeaderCell = GridFunctions.getColumnHeader(currentColumn, fixture); @@ -225,9 +226,9 @@ describe('IgxGrid - Grid Sorting #grid', () => { it('Should sort grid by current column by expression (Ascending)', () => { const currentColumn = 'ID'; grid.sortingExpressions = [{ - fieldName: currentColumn, dir: SortingDirection.Asc, ignoreCase: true, - strategy: DefaultSortingStrategy.instance() - }]; + fieldName: currentColumn, dir: SortingDirection.Asc, ignoreCase: true, + strategy: DefaultSortingStrategy.instance() + }]; fixture.detectChanges(); @@ -238,9 +239,9 @@ describe('IgxGrid - Grid Sorting #grid', () => { const currentColumn = 'Name'; grid.sortingExpressions = [{ - fieldName: currentColumn, dir: SortingDirection.Desc, ignoreCase: true, - strategy: DefaultSortingStrategy.instance() - }]; + fieldName: currentColumn, dir: SortingDirection.Desc, ignoreCase: true, + strategy: DefaultSortingStrategy.instance() + }]; fixture.detectChanges(); @@ -358,11 +359,7 @@ describe('IgxGrid - Grid Sorting #grid', () => { it(`Should allow sorting using a custom Sorting Strategy.`, () => { fixture = TestBed.createComponent(SortByParityComponent); grid = fixture.componentInstance.grid; - fixture.componentInstance.data.push( - { ID: 8, Name: 'Brad', LastName: 'Walker', Region: 'DD' }, - { ID: 9, Name: 'Mary', LastName: 'Smith', Region: 'OC' }, - { ID: 10, Name: 'Brad', LastName: 'Smith', Region: 'BD' }, - ); + fixture.componentInstance.data.push({ ID: 8, Name: 'Brad', LastName: 'Walker', Region: 'DD' }, { ID: 9, Name: 'Mary', LastName: 'Smith', Region: 'OC' }, { ID: 10, Name: 'Brad', LastName: 'Smith', Region: 'BD' }); fixture.detectChanges(); grid.sort({ fieldName: 'ID', @@ -390,7 +387,7 @@ describe('IgxGrid - Grid Sorting #grid', () => { column.groupingComparer = (a: any, b: any, currRec: any, groupRec: any) => { return currRec.Name === groupRec.Name ? 0 : -1; - } + }; fixture.detectChanges(); grid.sortingExpressions = [ @@ -466,8 +463,8 @@ describe('IgxGrid - Grid Sorting #grid', () => { describe('UI tests', () => { it('Should sort grid ascending by clicking once on first header cell UI', fakeAsync(() => { - spyOn(grid.sorting, 'emit'); - spyOn(grid.sortingDone, 'emit'); + vi.spyOn(grid.sorting, 'emit'); + vi.spyOn(grid.sortingDone, 'emit'); const firstHeaderCell = GridFunctions.getColumnHeader('ID', fixture); GridFunctions.clickHeaderSortIcon(firstHeaderCell); @@ -496,8 +493,8 @@ describe('IgxGrid - Grid Sorting #grid', () => { })); it('Should sort grid descending by clicking twice on sort icon UI', fakeAsync(() => { - spyOn(grid.sorting, 'emit').and.callThrough(); - spyOn(grid.sortingDone, 'emit').and.callThrough(); + vi.spyOn(grid.sorting, 'emit'); + vi.spyOn(grid.sortingDone, 'emit'); const firstHeaderCell = GridFunctions.getColumnHeader('ID', fixture); @@ -538,8 +535,8 @@ describe('IgxGrid - Grid Sorting #grid', () => { })); it('Should sort grid none when we click three time on header sort icon UI', fakeAsync(() => { - spyOn(grid.sorting, 'emit'); - spyOn(grid.sortingDone, 'emit'); + vi.spyOn(grid.sorting, 'emit'); + vi.spyOn(grid.sortingDone, 'emit'); const firstHeaderCell = GridFunctions.getColumnHeader('ID', fixture); GridFunctions.clickHeaderSortIcon(firstHeaderCell); @@ -588,7 +585,7 @@ describe('IgxGrid - Grid Sorting #grid', () => { GridFunctions.verifyHeaderSortIndicator(firstHeaderCell, false, false); }); - it('Should sort grid on sorting icon click when FilterRow is visible.', fakeAsync(/** Filtering showHideArrowButtons RAF */() => { + it('Should sort grid on sorting icon click when FilterRow is visible.', fakeAsync(/** Filtering showHideArrowButtons RAF */ () => { grid.allowFiltering = true; fixture.detectChanges(); @@ -617,8 +614,8 @@ describe('IgxGrid - Grid Sorting #grid', () => { })); it('Should disable sorting feature when using NoopSortingStrategy.', fakeAsync(() => { - spyOn(grid.sorting, 'emit'); - spyOn(grid.sortingDone, 'emit'); + vi.spyOn(grid.sorting, 'emit'); + vi.spyOn(grid.sortingDone, 'emit'); grid.sortStrategy = NoopSortingStrategy.instance(); fixture.detectChanges(); diff --git a/projects/igniteui-angular/grids/grid/src/row-drag.directive.spec.ts b/projects/igniteui-angular/grids/grid/src/row-drag.directive.spec.ts index a1d179f31f4..adb573f7a2d 100644 --- a/projects/igniteui-angular/grids/grid/src/row-drag.directive.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/row-drag.directive.spec.ts @@ -20,6 +20,7 @@ import { IgxStringFilteringOperand, Point, SortingDirection } from 'igniteui-ang import { IgxHierarchicalGridComponent, IgxRowIslandComponent } from 'igniteui-angular/grids/hierarchical-grid'; import { IgxTreeGridComponent } from 'igniteui-angular/grids/tree-grid'; import { IgxIconComponent } from 'igniteui-angular/icon'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const DEBOUNCE_TIME = 50; const CSS_CLASS_DRAG_INDICATOR = '.igx-grid__drag-indicator'; @@ -89,8 +90,8 @@ describe('Row Drag Tests', () => { pointerMoveEvent = UIInteractions.createPointerEvent('pointermove', movePoint); pointerUpEvent = UIInteractions.createPointerEvent('pointerup', dropPoint); - spyOn(grid.rowDragStart, 'emit'); - spyOn(grid.rowDragEnd, 'emit'); + vi.spyOn(grid.rowDragStart, 'emit'); + vi.spyOn(grid.rowDragEnd, 'emit'); expect(rowToDrag.dragging).toBeFalsy(); expect(rowToDrag.grid.rowDragging).toBeFalsy(); @@ -123,7 +124,7 @@ describe('Row Drag Tests', () => { pointerDownEvent = UIInteractions.createPointerEvent('pointerdown', startPoint); pointerMoveEvent = UIInteractions.createPointerEvent('pointermove', movePoint); pointerUpEvent = UIInteractions.createPointerEvent('pointerup', dropPoint); - spyOn(grid.rowDragStart, 'emit'); + vi.spyOn(grid.rowDragStart, 'emit'); expect(rowToDrag.dragging).toBeFalsy(); expect(rowToDrag.grid.rowDragging).toBeFalsy(); @@ -153,8 +154,8 @@ describe('Row Drag Tests', () => { startPoint = UIInteractions.getPointFromElement(dragIndicatorElement); movePoint = UIInteractions.getPointFromElement(rows[4].nativeElement); - spyOn(grid.rowDragStart, 'emit'); - spyOn(grid.rowDragEnd, 'emit'); + vi.spyOn(grid.rowDragStart, 'emit'); + vi.spyOn(grid.rowDragEnd, 'emit'); rowDragDirective.onPointerDown(UIInteractions.createPointerEvent('pointerdown', startPoint)); rowDragDirective.onPointerMove(UIInteractions.createPointerEvent('pointermove', movePoint)); @@ -288,8 +289,8 @@ describe('Row Drag Tests', () => { pointerMoveEvent = UIInteractions.createPointerEvent('pointermove', dropPoint); pointerUpEvent = UIInteractions.createPointerEvent('pointerup', dropPoint); - spyOn(grid.rowDragStart, 'emit').and.callThrough(); - spyOn(grid.rowDragEnd, 'emit').and.callThrough(); + vi.spyOn(grid.rowDragStart, 'emit'); + vi.spyOn(grid.rowDragEnd, 'emit'); rowDragDirective.onPointerDown(pointerDownEvent); rowDragDirective.onPointerMove(pointerMoveEvent); @@ -311,8 +312,8 @@ describe('Row Drag Tests', () => { pointerMoveEvent = UIInteractions.createPointerEvent('pointermove', movePoint); pointerUpEvent = UIInteractions.createPointerEvent('pointerup', dropPoint); - spyOn(grid.rowDragStart, 'emit'); - spyOn(grid.rowDragEnd, 'emit'); + vi.spyOn(grid.rowDragStart, 'emit'); + vi.spyOn(grid.rowDragEnd, 'emit'); expect(rowToDrag.dragging).toBeFalsy(); expect(rowToDrag.grid.rowDragging).toBeFalsy(); @@ -348,8 +349,8 @@ describe('Row Drag Tests', () => { pointerMoveEvent = UIInteractions.createPointerEvent('pointermove', movePoint); pointerUpEvent = UIInteractions.createPointerEvent('pointerup', dropPoint); - spyOn(grid.rowDragStart, 'emit'); - spyOn(grid.rowDragEnd, 'emit'); + vi.spyOn(grid.rowDragStart, 'emit'); + vi.spyOn(grid.rowDragEnd, 'emit'); expect(rowToDrag.dragging).toBeFalsy(); expect(rowToDrag.grid.rowDragging).toBeFalsy(); @@ -388,8 +389,8 @@ describe('Row Drag Tests', () => { pointerMoveEvent = UIInteractions.createPointerEvent('pointermove', dropPoint); pointerUpEvent = UIInteractions.createPointerEvent('pointerup', dropPoint); - spyOn(grid.rowDragStart, 'emit').and.callThrough(); - spyOn(grid.rowDragEnd, 'emit').and.callThrough(); + vi.spyOn(grid.rowDragStart, 'emit'); + vi.spyOn(grid.rowDragEnd, 'emit'); rowDragDirective.onPointerDown(pointerDownEvent); rowDragDirective.onPointerMove(pointerMoveEvent); @@ -555,8 +556,8 @@ describe('Row Drag Tests', () => { pointerMoveEvent = UIInteractions.createPointerEvent('pointermove', movePoint); pointerUpEvent = UIInteractions.createPointerEvent('pointerup', dropPoint); - spyOn(dragGrid.rowDragStart, 'emit').and.callThrough(); - spyOn(dragGrid.rowDragEnd, 'emit').and.callThrough(); + vi.spyOn(dragGrid.rowDragStart, 'emit'); + vi.spyOn(dragGrid.rowDragEnd, 'emit'); rowDragDirective.onPointerDown(pointerDownEvent); rowDragDirective.onPointerMove(pointerMoveEvent); @@ -595,8 +596,8 @@ describe('Row Drag Tests', () => { pointerMoveEvent = UIInteractions.createPointerEvent('pointermove', movePoint); pointerUpEvent = UIInteractions.createPointerEvent('pointerup', dropPoint); - spyOn(dragGrid.rowDragStart, 'emit').and.callThrough(); - spyOn(dragGrid.rowDragEnd, 'emit').and.callThrough(); + vi.spyOn(dragGrid.rowDragStart, 'emit'); + vi.spyOn(dragGrid.rowDragEnd, 'emit'); rowDragDirective.onPointerDown(pointerDownEvent); rowDragDirective.onPointerMove(pointerMoveEvent); @@ -634,8 +635,8 @@ describe('Row Drag Tests', () => { pointerMoveEvent = UIInteractions.createPointerEvent('pointermove', movePoint); pointerUpEvent = UIInteractions.createPointerEvent('pointerup', dropPoint); - spyOn(dragGrid.rowDragStart, 'emit').and.callThrough(); - spyOn(dragGrid.rowDragEnd, 'emit').and.callThrough(); + vi.spyOn(dragGrid.rowDragStart, 'emit'); + vi.spyOn(dragGrid.rowDragEnd, 'emit'); rowDragDirective.onPointerDown(pointerDownEvent); rowDragDirective.onPointerMove(pointerMoveEvent); @@ -667,8 +668,8 @@ describe('Row Drag Tests', () => { pointerMoveEvent = UIInteractions.createPointerEvent('pointermove', movePoint); pointerUpEvent = UIInteractions.createPointerEvent('pointerup', dropPoint); - spyOn(dragGrid.rowDragStart, 'emit').and.callThrough(); - spyOn(dragGrid.rowDragEnd, 'emit').and.callThrough(); + vi.spyOn(dragGrid.rowDragStart, 'emit'); + vi.spyOn(dragGrid.rowDragEnd, 'emit'); rowDragDirective.onPointerDown(pointerDownEvent); rowDragDirective.onPointerMove(pointerMoveEvent); @@ -699,8 +700,8 @@ describe('Row Drag Tests', () => { pointerMoveEvent = UIInteractions.createPointerEvent('pointermove', movePoint); pointerUpEvent = UIInteractions.createPointerEvent('pointerup', dropPoint); - spyOn(dragGrid.rowDragStart, 'emit').and.callThrough(); - spyOn(dragGrid.rowDragEnd, 'emit').and.callThrough(); + vi.spyOn(dragGrid.rowDragStart, 'emit'); + vi.spyOn(dragGrid.rowDragEnd, 'emit'); rowDragDirective.onPointerDown(pointerDownEvent); rowDragDirective.onPointerMove(pointerMoveEvent); @@ -736,14 +737,14 @@ describe('Row Drag Tests', () => { pointerMoveEvent = UIInteractions.createPointerEvent('pointermove', movePoint); pointerUpEvent = UIInteractions.createPointerEvent('pointerup', dropPoint); - spyOn(dragGrid.rowDragStart, 'emit').and.callThrough(); - spyOn(dragGrid.rowDragEnd, 'emit').and.callThrough(); + vi.spyOn(dragGrid.rowDragStart, 'emit'); + vi.spyOn(dragGrid.rowDragEnd, 'emit'); rowDragDirective.onPointerDown(pointerDownEvent); rowDragDirective.onPointerMove(pointerMoveEvent); expect(row.dragging).toBeTruthy(); expect(row.grid.rowDragging).toBeTruthy(); - verifyRowDragStartEvent(dragGrid, dragGrid.getRowByIndex(row.index), row.nativeElement, rowDragDirective); + verifyRowDragStartEvent(dragGrid, dragGrid.getRowByIndex(row.index), row.nativeElement, rowDragDirective); pointerMoveEvent = UIInteractions.createPointerEvent('pointermove', dropPoint); rowDragDirective.onPointerMove(pointerMoveEvent); @@ -813,8 +814,8 @@ describe('Row Drag Tests', () => { pointerMoveEvent = UIInteractions.createPointerEvent('pointermove', movePoint); pointerUpEvent = UIInteractions.createPointerEvent('pointerup', dropPoint); - spyOn(dragGrid.rowDragStart, 'emit').and.callThrough(); - spyOn(dragGrid.rowDragEnd, 'emit').and.callThrough(); + vi.spyOn(dragGrid.rowDragStart, 'emit'); + vi.spyOn(dragGrid.rowDragEnd, 'emit'); rowDragDirective.onPointerDown(pointerDownEvent); rowDragDirective.onPointerMove(pointerMoveEvent); @@ -852,8 +853,8 @@ describe('Row Drag Tests', () => { pointerMoveEvent = UIInteractions.createPointerEvent('pointermove', movePoint); pointerUpEvent = UIInteractions.createPointerEvent('pointerup', dropPoint); - spyOn(dragGrid.rowDragStart, 'emit').and.callThrough(); - spyOn(dragGrid.rowDragEnd, 'emit').and.callThrough(); + vi.spyOn(dragGrid.rowDragStart, 'emit'); + vi.spyOn(dragGrid.rowDragEnd, 'emit'); rowDragDirective.onPointerDown(pointerDownEvent); rowDragDirective.onPointerMove(pointerMoveEvent); @@ -893,7 +894,7 @@ describe('Row Drag Tests', () => { const cellElement = dragCell.nativeElement; let cellInput = null; - spyOn(dragGrid.gridAPI.crudService, 'endEdit').and.callThrough(); + vi.spyOn(dragGrid.gridAPI.crudService, 'endEdit'); cellElement.dispatchEvent(new Event('focus')); fixture.detectChanges(); @@ -978,19 +979,17 @@ describe('Row Drag Tests', () => { pointerMoveToDropEvent = UIInteractions.createPointerEvent('pointermove', dropPoint); pointerUpEvent = UIInteractions.createPointerEvent('pointerup', dropPoint); - spyOn(dragGrid.rowDragStart, 'emit').and.callThrough(); - spyOn(dragGrid.rowDragEnd, 'emit').and.callThrough(); + vi.spyOn(dragGrid.rowDragStart, 'emit'); + vi.spyOn(dragGrid.rowDragEnd, 'emit'); rowDragDirective.onPointerDown(pointerDownEvent); rowDragDirective.onPointerMove(pointerMoveEvent); - verifyRowDragStartEvent(dragGrid, rowToDrag.grid.getRowByIndex(rowToDrag.index), - rowToDrag.nativeElement, rowDragDirective, 1); + verifyRowDragStartEvent(dragGrid, rowToDrag.grid.getRowByIndex(rowToDrag.index), rowToDrag.nativeElement, rowDragDirective, 1); // pointerMoveEvent = UIInteractions.createPointerEvent('pointermove', dropPoint); rowDragDirective.onPointerMove(pointerMoveToDropEvent); rowDragDirective.onPointerUp(pointerUpEvent); fixture.detectChanges(); - verifyRowDragEndEvent(dragGrid, rowToDrag.grid.getRowByIndex(rowToDrag.index), - rowToDrag.nativeElement, rowDragDirective, false, 1); + verifyRowDragEndEvent(dragGrid, rowToDrag.grid.getRowByIndex(rowToDrag.index), rowToDrag.nativeElement, rowDragDirective, false, 1); // second level row const childGrid = dragGrid.gridAPI.getChildGrids(false)[0]; @@ -1000,18 +999,16 @@ describe('Row Drag Tests', () => { startPoint = UIInteractions.getPointFromElement(dragIndicatorElement); pointerDownEvent = UIInteractions.createPointerEvent('pointerdown', startPoint); - spyOn(childGrid.rowDragStart, 'emit').and.callThrough(); - spyOn(childGrid.rowDragEnd, 'emit').and.callThrough(); + vi.spyOn(childGrid.rowDragStart, 'emit'); + vi.spyOn(childGrid.rowDragEnd, 'emit'); rowDragDirective.onPointerDown(pointerDownEvent); rowDragDirective.onPointerMove(pointerMoveEvent); - verifyRowDragStartEvent(childGrid, rowToDrag.grid.getRowByIndex(rowToDrag.index), - rowToDrag.nativeElement, rowDragDirective, 1); + verifyRowDragStartEvent(childGrid, rowToDrag.grid.getRowByIndex(rowToDrag.index), rowToDrag.nativeElement, rowDragDirective, 1); rowDragDirective.onPointerMove(pointerMoveToDropEvent); rowDragDirective.onPointerUp(pointerUpEvent); fixture.detectChanges(); - verifyRowDragEndEvent(childGrid, rowToDrag.grid.getRowByIndex(rowToDrag.index), - rowToDrag.nativeElement, rowDragDirective, false, 1); + verifyRowDragEndEvent(childGrid, rowToDrag.grid.getRowByIndex(rowToDrag.index), rowToDrag.nativeElement, rowDragDirective, false, 1); // third level row const nestedChildGrid = childGrid.gridAPI.getChildGrids(false)[0]; @@ -1021,18 +1018,16 @@ describe('Row Drag Tests', () => { startPoint = UIInteractions.getPointFromElement(dragIndicatorElement); pointerDownEvent = UIInteractions.createPointerEvent('pointerdown', startPoint); - spyOn(nestedChildGrid.rowDragStart, 'emit').and.callThrough(); - spyOn(nestedChildGrid.rowDragEnd, 'emit').and.callThrough(); + vi.spyOn(nestedChildGrid.rowDragStart, 'emit'); + vi.spyOn(nestedChildGrid.rowDragEnd, 'emit'); rowDragDirective.onPointerDown(pointerDownEvent); rowDragDirective.onPointerMove(pointerMoveEvent); - verifyRowDragStartEvent(nestedChildGrid, rowToDrag.grid.getRowByIndex(rowToDrag.index), - rowToDrag.nativeElement, rowDragDirective, 1); + verifyRowDragStartEvent(nestedChildGrid, rowToDrag.grid.getRowByIndex(rowToDrag.index), rowToDrag.nativeElement, rowDragDirective, 1); rowDragDirective.onPointerMove(pointerMoveToDropEvent); rowDragDirective.onPointerUp(pointerUpEvent); fixture.detectChanges(); - verifyRowDragEndEvent(nestedChildGrid, rowToDrag.grid.getRowByIndex(rowToDrag.index), - rowToDrag.nativeElement, rowDragDirective, false, 1); + verifyRowDragEndEvent(nestedChildGrid, rowToDrag.grid.getRowByIndex(rowToDrag.index), rowToDrag.nativeElement, rowDragDirective, false, 1); }); it('should correctly create custom ghost element', () => { @@ -1130,18 +1125,16 @@ describe('Row Drag Tests', () => { pointerMoveToDropEvent = UIInteractions.createPointerEvent('pointermove', dropPoint); pointerUpEvent = UIInteractions.createPointerEvent('pointerup', dropPoint); - spyOn(dragGrid.rowDragStart, 'emit').and.callThrough(); - spyOn(dragGrid.rowDragEnd, 'emit').and.callThrough(); + vi.spyOn(dragGrid.rowDragStart, 'emit'); + vi.spyOn(dragGrid.rowDragEnd, 'emit'); rowDragDirective.onPointerDown(pointerDownEvent); rowDragDirective.onPointerMove(pointerMoveEvent); - verifyRowDragStartEvent(dragGrid, dragGrid.getRowByKey(rowToDrag.key), - rowToDrag.nativeElement, rowDragDirective, 1); + verifyRowDragStartEvent(dragGrid, dragGrid.getRowByKey(rowToDrag.key), rowToDrag.nativeElement, rowDragDirective, 1); rowDragDirective.onPointerMove(pointerMoveToDropEvent); rowDragDirective.onPointerUp(pointerUpEvent); fixture.detectChanges(); - verifyRowDragEndEvent(dragGrid, dragGrid.getRowByKey(rowToDrag.key), - rowToDrag.nativeElement, rowDragDirective, false, 1); + verifyRowDragEndEvent(dragGrid, dragGrid.getRowByKey(rowToDrag.key), rowToDrag.nativeElement, rowDragDirective, false, 1); // second level row dragIndicatorElement = dragIndicatorElements[2].nativeElement; @@ -1167,13 +1160,11 @@ describe('Row Drag Tests', () => { rowDragDirective.onPointerDown(pointerDownEvent); rowDragDirective.onPointerMove(pointerMoveEvent); - verifyRowDragStartEvent(dragGrid, dragGrid.getRowByKey(rowToDrag.key), - rowToDrag.nativeElement, rowDragDirective, 3); + verifyRowDragStartEvent(dragGrid, dragGrid.getRowByKey(rowToDrag.key), rowToDrag.nativeElement, rowDragDirective, 3); rowDragDirective.onPointerMove(pointerMoveToDropEvent); rowDragDirective.onPointerUp(pointerUpEvent); fixture.detectChanges(); - verifyRowDragEndEvent(dragGrid, dragGrid.getRowByKey(rowToDrag.key), - rowToDrag.nativeElement, rowDragDirective, false, 3); + verifyRowDragEndEvent(dragGrid, dragGrid.getRowByKey(rowToDrag.key), rowToDrag.nativeElement, rowDragDirective, false, 3); }); }); }); @@ -1271,10 +1262,10 @@ export class IgxGridRowCustomGhostDraggableComponent extends DataParent { @ViewChild(IgxGridComponent, { read: IgxGridComponent, static: true }) public instance: IgxGridComponent; - @ViewChild('rowDragGhostTemplate', {read: TemplateRef, static: true }) + @ViewChild('rowDragGhostTemplate', { read: TemplateRef, static: true }) public rowDragGhostTemplate: TemplateRef; - @ViewChild('rowDragTemplate', {read: TemplateRef, static: true }) + @ViewChild('rowDragTemplate', { read: TemplateRef, static: true }) public rowDragTemplate: TemplateRef; @ViewChild('dropArea', { read: IgxDropDirective, static: true }) @@ -1371,10 +1362,14 @@ export class IgxGridFeaturesRowDragComponent extends DataParent { imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent, IgxDropDirective] }) export class IgxHierarchicalGridTestComponent { - @ViewChild('hierarchicalDragGrid', { read: IgxHierarchicalGridComponent, static: true }) public hDragGrid: IgxHierarchicalGridComponent; - @ViewChild('hierarchicalDropGrid', { read: IgxHierarchicalGridComponent, static: true }) public hDropGrid: IgxHierarchicalGridComponent; - @ViewChild('rowIsland', { read: IgxRowIslandComponent, static: true }) public rowIsland: IgxRowIslandComponent; - @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) public rowIsland2: IgxRowIslandComponent; + @ViewChild('hierarchicalDragGrid', { read: IgxHierarchicalGridComponent, static: true }) + public hDragGrid: IgxHierarchicalGridComponent; + @ViewChild('hierarchicalDropGrid', { read: IgxHierarchicalGridComponent, static: true }) + public hDropGrid: IgxHierarchicalGridComponent; + @ViewChild('rowIsland', { read: IgxRowIslandComponent, static: true }) + public rowIsland: IgxRowIslandComponent; + @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) + public rowIsland2: IgxRowIslandComponent; public data; public newData = []; @@ -1411,9 +1406,12 @@ export class IgxHierarchicalGridTestComponent { imports: [IgxHierarchicalGridComponent, IgxRowIslandComponent, IgxRowDragGhostDirective] }) export class IgxHierarchicalGridCustomGhostTestComponent { - @ViewChild('hierarchicalDragGrid', { read: IgxHierarchicalGridComponent, static: true }) public hDragGrid: IgxHierarchicalGridComponent; - @ViewChild('rowIsland', { read: IgxRowIslandComponent, static: true }) public rowIsland: IgxRowIslandComponent; - @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) public rowIsland2: IgxRowIslandComponent; + @ViewChild('hierarchicalDragGrid', { read: IgxHierarchicalGridComponent, static: true }) + public hDragGrid: IgxHierarchicalGridComponent; + @ViewChild('rowIsland', { read: IgxRowIslandComponent, static: true }) + public rowIsland: IgxRowIslandComponent; + @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) + public rowIsland2: IgxRowIslandComponent; public data; public newData = []; @@ -1443,8 +1441,10 @@ export class IgxHierarchicalGridCustomGhostTestComponent { imports: [IgxTreeGridComponent, IgxGridComponent, IgxColumnComponent, IgxDropDirective] }) export class IgxTreeGridTestComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; - @ViewChild(IgxGridComponent, { static: true }) public dropGrid: IgxGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxGridComponent, { static: true }) + public dropGrid: IgxGridComponent; public data = SampleTestData.employeeScrollingData(); public newData = []; @@ -1508,13 +1508,7 @@ const pointerUp = async (element: Element, startPoint: Point, fixture: Component * @param timesCalled The number of times the rowDragStart event has been emitted. Defaults to 1. * @param cancel Indicates weather the rowDragStart event is cancelled. Default value is false. */ -const verifyRowDragStartEvent =( - grid: GridType, - dragRow: RowType, - dragElement: HTMLElement, - dragDirective: IgxRowDragDirective, - timesCalled = 1, - cancel = false) => { +const verifyRowDragStartEvent = (grid: GridType, dragRow: RowType, dragElement: HTMLElement, dragDirective: IgxRowDragDirective, timesCalled = 1, cancel = false) => { expect(grid.rowDragStart.emit).toHaveBeenCalledTimes(timesCalled); expect(grid.rowDragStart.emit).toHaveBeenCalledWith({ dragData: dragRow, @@ -1533,13 +1527,7 @@ const verifyRowDragStartEvent =( * @param dragDirective IgxRowDragDirective of the dragged row * @param timesCalled The number of times the rowDragEnd event has been emitted. Defaults to 1. */ -const verifyRowDragEndEvent = ( - grid: GridType, - dragRow: RowType, - dragElement: HTMLElement, - dragDirective: IgxRowDragDirective, - animations: boolean, - timesCalled = 1) => { +const verifyRowDragEndEvent = (grid: GridType, dragRow: RowType, dragElement: HTMLElement, dragDirective: IgxRowDragDirective, animations: boolean, timesCalled = 1) => { expect(grid.rowDragEnd.emit).toHaveBeenCalledTimes(timesCalled); expect(grid.rowDragEnd.emit).toHaveBeenCalledWith({ dragDirective, diff --git a/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid-add-row.spec.ts b/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid-add-row.spec.ts index b1cc31bd3d0..b907e69f265 100644 --- a/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid-add-row.spec.ts +++ b/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid-add-row.spec.ts @@ -6,6 +6,7 @@ import { wait } from '../../../test-utils/ui-interactions.spec'; import { By } from '@angular/platform-browser'; import { IgxHierarchicalGridComponent } from './hierarchical-grid.component'; import { IgxGridNavigationService } from 'igniteui-angular/grids/core'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('IgxHierarchicalGrid - Add Row UI #tGrid', () => { let fixture; @@ -41,26 +42,26 @@ describe('IgxHierarchicalGrid - Add Row UI #tGrid', () => { const row = hierarchicalGrid.rowList.first; hierarchicalGrid.expandRow(row.key); fixture.detectChanges(); - expect(row.expanded).toBeTrue(); + expect(row.expanded).toBe(true); row.beginAddRow(); fixture.detectChanges(); - expect(row.expanded).toBeFalse(); - expect(hierarchicalGrid.gridAPI.get_row_by_index(1).addRowUI).toBeTrue(); + expect(row.expanded).toBe(false); + expect(hierarchicalGrid.gridAPI.get_row_by_index(1).addRowUI).toBe(true); }); it('Should allow the expansion of a newly added (commited) record', async () => { const row = hierarchicalGrid.rowList.first; hierarchicalGrid.expandRow(row.key); fixture.detectChanges(); - expect(row.expanded).toBeTrue(); + expect(row.expanded).toBe(true); row.beginAddRow(); fixture.detectChanges(); endTransition(); - expect(row.expanded).toBeFalse(); + expect(row.expanded).toBe(false); - expect(hierarchicalGrid.gridAPI.get_row_by_index(1).addRowUI).toBeTrue(); + expect(hierarchicalGrid.gridAPI.get_row_by_index(1).addRowUI).toBe(true); hierarchicalGrid.gridAPI.crudService.endEdit(true); fixture.detectChanges(); hierarchicalGrid.addRowSnackbar.triggerAction(); @@ -71,10 +72,10 @@ describe('IgxHierarchicalGrid - Add Row UI #tGrid', () => { const newRowData = hierarchicalGrid.data[hierarchicalGrid.data.length - 1]; const newRow = hierarchicalGrid.rowList.find(r => r.key === newRowData[hierarchicalGrid.primaryKey]); - expect(newRow.expanded).toBeFalse(); + expect(newRow.expanded).toBe(false); hierarchicalGrid.expandRow(newRow.key); fixture.detectChanges(); - expect(newRow.expanded).toBeTrue(); + expect(newRow.expanded).toBe(true); }); it('Should allow adding to child grid for parent row that has null/undefined child collection.', async () => { diff --git a/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.integration.spec.ts b/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.integration.spec.ts index cc973c6df89..3eb56eaa889 100644 --- a/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.integration.spec.ts +++ b/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.integration.spec.ts @@ -6,13 +6,7 @@ import { wait, UIInteractions } from '../../../test-utils/ui-interactions.spec'; import { IgxColumnMovingDragDirective, IgxGridNavigationService } from 'igniteui-angular/grids/core'; import { IgxHierarchicalRowComponent } from './hierarchical-row.component'; import { take } from 'rxjs/operators'; -import { - IgxHierarchicalGridTestBaseComponent, - IgxHierarchicalGridTestCustomToolbarComponent, - IgxHierarchicalGridTestInputPaginatorComponent, - IgxHierarchicalGridTestInputToolbarComponent, - IgxHierarchicalGridWithTransactionProviderComponent -} from '../../../test-utils/hierarchical-grid-components.spec'; +import { IgxHierarchicalGridTestBaseComponent, IgxHierarchicalGridTestCustomToolbarComponent, IgxHierarchicalGridTestInputPaginatorComponent, IgxHierarchicalGridTestInputToolbarComponent, IgxHierarchicalGridWithTransactionProviderComponent } from '../../../test-utils/hierarchical-grid-components.spec'; import { GridFunctions, GridSelectionFunctions } from '../../../test-utils/grid-functions.spec'; import { HierarchicalGridFunctions } from '../../../test-utils/hierarchical-grid-functions.spec'; import { GridSelectionMode, RowPinningPosition } from 'igniteui-angular/grids/core'; @@ -20,6 +14,7 @@ import { SampleTestData } from '../../../test-utils/sample-test-data.spec'; import { setElementSize } from '../../../test-utils/helper-utils.spec'; import { ColumnPinningPosition, DefaultSortingStrategy, IgxStringFilteringOperand, ɵSize, SortingDirection } from 'igniteui-angular/core'; import { IgxPaginatorComponent } from 'igniteui-angular/paginator'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('IgxHierarchicalGrid Integration #hGrid', () => { let fixture: ComponentFixture; @@ -45,7 +40,7 @@ describe('IgxHierarchicalGrid Integration #hGrid', () => { IgxGridNavigationService ] }).compileComponents(); - })) + })); beforeEach(waitForAsync(() => { fixture = TestBed.createComponent(IgxHierarchicalGridTestBaseComponent); @@ -220,10 +215,10 @@ describe('IgxHierarchicalGrid Integration #hGrid', () => { fixture.detectChanges(); const rows = HierarchicalGridFunctions.getHierarchicalRows(fixture); const lastRow = rows[rows.length - 1]; - expect(lastRow.query(By.css('igx-icon')).nativeElement).toHaveClass('igx-icon--inactive'); + expect(lastRow.query(By.css('igx-icon')).nativeElement.classList.contains('igx-icon--inactive')).toBe(true); hierarchicalGrid.transactions.commit(hierarchicalGrid.data); fixture.detectChanges(); - expect(lastRow.query(By.css('igx-icon')).nativeElement).not.toHaveClass('igx-icon--inactive'); + expect(lastRow.query(By.css('igx-icon')).nativeElement.classList.contains('igx-icon--inactive')).toBe(false); })); it('should now allow expanding uncommitted added rows', fakeAsync(() => { @@ -440,7 +435,7 @@ describe('IgxHierarchicalGrid Integration #hGrid', () => { expect(summaryRowIndentation.offsetWidth).toEqual(expander.nativeElement.offsetWidth); const gridHeight = childGrid.nativeElement.offsetHeight; - const childElements: HTMLElement[] = Array.from(childGrid.nativeElement.children) as HTMLElement []; + const childElements: HTMLElement[] = Array.from(childGrid.nativeElement.children) as HTMLElement[]; const elementsHeight = childElements.map(elem => elem.offsetHeight).reduce((total, height) => total + height, 0); // Expect the combined height of all elements (header, body, footer etc) to equal the calculated height of the grid. @@ -486,7 +481,7 @@ describe('IgxHierarchicalGrid Integration #hGrid', () => { })); it('should size summaries for parent and child grids correctly when grid size is changed and summaryRowHeight is set to falsy value', () => { - setElementSize(hierarchicalGrid.nativeElement, ɵSize.Large) + setElementSize(hierarchicalGrid.nativeElement, ɵSize.Large); fixture.detectChanges(); hierarchicalGrid.expandRow(hierarchicalGrid.dataRowList.first.key); @@ -501,7 +496,7 @@ describe('IgxHierarchicalGrid Integration #hGrid', () => { expect(childTFoot.getBoundingClientRect().height).toBe(hierarchicalGrid.defaultSummaryHeight); - setElementSize(hierarchicalGrid.nativeElement, ɵSize.Medium) + setElementSize(hierarchicalGrid.nativeElement, ɵSize.Medium); hierarchicalGrid.summaryRowHeight = 0; childGrid.summaryRowHeight = 0; fixture.detectChanges(); @@ -513,7 +508,7 @@ describe('IgxHierarchicalGrid Integration #hGrid', () => { expect(tFoot.getBoundingClientRect().height).toBe(hierarchicalGrid.defaultSummaryHeight); expect(childTFoot.getBoundingClientRect().height).toBe(hierarchicalGrid.defaultSummaryHeight); - setElementSize(hierarchicalGrid.nativeElement, ɵSize.Small) + setElementSize(hierarchicalGrid.nativeElement, ɵSize.Small); hierarchicalGrid.summaryRowHeight = 0; childGrid.summaryRowHeight = 0; fixture.detectChanges(); @@ -524,7 +519,7 @@ describe('IgxHierarchicalGrid Integration #hGrid', () => { expect(tFoot.getBoundingClientRect().height).toBe(hierarchicalGrid.defaultSummaryHeight); expect(childTFoot.getBoundingClientRect().height).toBe(hierarchicalGrid.defaultSummaryHeight); - }) + }); it('should render summaries for column inside a column group.', fakeAsync(() => { const count = fixture.componentInstance.rowIsland.columns.length - 1; @@ -692,7 +687,7 @@ describe('IgxHierarchicalGrid Integration #hGrid', () => { const paginators = fixture.debugElement.queryAll(By.css('igx-paginator')); expect(paginators[0].query(By.css('button')).nativeElement.innerText.trim()).toEqual('childData1 Button'); expect(paginators[1].query(By.css('button')).nativeElement.innerText.trim()).toEqual('childData2 Button'); - })) + })); }); describe('Hiding', () => { @@ -842,16 +837,16 @@ describe('IgxHierarchicalGrid Integration #hGrid', () => { const toolbars = fixture.debugElement.queryAll(By.css('igx-grid-toolbar')); expect(toolbars[1].query(By.css('button')).nativeElement.innerText.trim()).toEqual('childData1 Button'); expect(toolbars[2].query(By.css('button')).nativeElement.innerText.trim()).toEqual('childData2 Button'); - })) + })); }); describe('Moving', () => { // TODO: Revise this test! That DOM digging is sloppy - xit('should not be possible to drag move a column from another grid.', (async () => { + it.skip('should not be possible to drag move a column from another grid.', (async () => { hierarchicalGrid.expandRow(hierarchicalGrid.dataRowList.first.key); - const childGrids = fixture.debugElement.queryAll(By.css('igx-child-grid-row')); + const childGrids = fixture.debugElement.queryAll(By.css('igx-child-grid-row')); const childHeader = childGrids[0].queryAll(By.css('igx-grid-header'))[0].nativeElement; const mainHeaders = hierarchicalGrid.nativeElement .querySelectorAll('igx-grid-header[ng-reflect-grid-i-d="' + hierarchicalGrid.id + '"]'); @@ -1158,7 +1153,7 @@ describe('IgxHierarchicalGrid Integration #hGrid', () => { fixture.detectChanges(); let selectedData = hierarchicalGrid.getSelectedData(); - expect(selectedData).toEqual([{ID: '1', ChildLevels: 3}, {ID: '0', ChildLevels: 3}, {ID: '1', ChildLevels: 3}]); + expect(selectedData).toEqual([{ ID: '1', ChildLevels: 3 }, { ID: '0', ChildLevels: 3 }, { ID: '1', ChildLevels: 3 }]); fixture.componentInstance.pinningConfig = { columns: ColumnPinningPosition.Start, rows: RowPinningPosition.Bottom }; fixture.detectChanges(); @@ -1172,7 +1167,7 @@ describe('IgxHierarchicalGrid Integration #hGrid', () => { fixture.detectChanges(); selectedData = hierarchicalGrid.getSelectedData(); - expect(selectedData).toEqual([{ID: '38', ChildLevels: 3}, {ID: '39', ChildLevels: 3}, {ID: '1', ChildLevels: 3}]); + expect(selectedData).toEqual([{ ID: '38', ChildLevels: 3 }, { ID: '39', ChildLevels: 3 }, { ID: '1', ChildLevels: 3 }]); }); it('should return correct filterData collection after filtering.', () => { diff --git a/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.navigation.spec.ts b/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.navigation.spec.ts index e9b7ef3f5cc..395cdc0ee2c 100644 --- a/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.navigation.spec.ts +++ b/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.navigation.spec.ts @@ -1,6 +1,6 @@ import { TestBed, waitForAsync } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { Component, ViewChild, DebugElement} from '@angular/core'; +import { Component, ViewChild, DebugElement } from '@angular/core'; import { IgxChildGridRowComponent, IgxHierarchicalGridComponent } from './hierarchical-grid.component'; import { wait, UIInteractions, waitForSelectionChange } from '../../../test-utils/ui-interactions.spec'; import { IgxRowIslandComponent } from './row-island.component'; @@ -10,6 +10,7 @@ import { clearGridSubs, setupHierarchicalGridScrollDetection } from '../../../te import { GridFunctions } from '../../../test-utils/grid-functions.spec'; import { IGridCellEventArgs, IgxColumnComponent, IgxGridCellComponent, IgxGridNavigationService } from 'igniteui-angular/grids/core'; import { IPathSegment } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, afterEach, afterAll, vi } from 'vitest'; const DEBOUNCE_TIME = 50; const GRID_CONTENT_CLASS = '.igx-grid__tbody-content'; @@ -34,7 +35,7 @@ describe('IgxHierarchicalGrid Navigation', () => { IgxGridNavigationService ] }).compileComponents(); - jasmine.DEFAULT_TIMEOUT_INTERVAL = defaultTimeout * 2; + vi.setConfig({ testTimeout: defaultTimeout * 2 }); })); afterAll(() => jasmine.DEFAULT_TIMEOUT_INTERVAL = defaultTimeout); @@ -85,11 +86,11 @@ describe('IgxHierarchicalGrid Navigation', () => { it('should allow navigating up from child row into parent grid.', () => { const childGrid = hierarchicalGrid.gridAPI.getChildGrids(false)[0]; - const childFirstCell = childGrid.dataRowList.first.cells.first; + const childFirstCell = childGrid.dataRowList.first.cells.first; GridFunctions.focusCell(fixture, childFirstCell); // arrow up in child - const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; + const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; UIInteractions.triggerEventHandlerKeyDown('arrowup', childGridContent, false, false, false); fixture.detectChanges(); @@ -101,11 +102,11 @@ describe('IgxHierarchicalGrid Navigation', () => { it('should allow navigating down in child grid when child grid selected cell moves outside the parent view port.', async () => { const childGrid = hierarchicalGrid.gridAPI.getChildGrids(false)[0]; - const childCell = childGrid.dataRowList.toArray()[3].cells.first; + const childCell = childGrid.dataRowList.toArray()[3].cells.first; GridFunctions.focusCell(fixture, childCell); // arrow down in child - const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; + const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; UIInteractions.triggerEventHandlerKeyDown('arrowdown', childGridContent, false, false, false); fixture.detectChanges(); await wait(); @@ -117,7 +118,7 @@ describe('IgxHierarchicalGrid Navigation', () => { expect(rowOffsets.top >= gridOffsets.top && rowOffsets.bottom <= gridOffsets.bottom).toBeTruthy(); }); - it('should allow navigating up in child grid when child grid selected cell moves outside the parent view port.', async () => { + it('should allow navigating up in child grid when child grid selected cell moves outside the parent view port.', async () => { await wait(DEBOUNCE_TIME); fixture.detectChanges(); hierarchicalGrid.verticalScrollContainer.scrollTo(2); @@ -125,12 +126,12 @@ describe('IgxHierarchicalGrid Navigation', () => { fixture.detectChanges(); const childGrid = hierarchicalGrid.gridAPI.getChildGrids(false)[0]; - const childCell = childGrid.dataRowList.toArray()[4].cells.first; + const childCell = childGrid.dataRowList.toArray()[4].cells.first; GridFunctions.focusCell(fixture, childCell); const prevScrTop = hierarchicalGrid.verticalScrollContainer.getScroll().scrollTop; - const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; + const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; UIInteractions.triggerEventHandlerKeyDown('arrowup', childGridContent, false, false, false); fixture.detectChanges(); await wait(DEBOUNCE_TIME); @@ -141,10 +142,10 @@ describe('IgxHierarchicalGrid Navigation', () => { it('should allow navigating to end in child grid when child grid target row moves outside the parent view port.', async () => { const childGrid = hierarchicalGrid.gridAPI.getChildGrids(false)[0]; - const childCell = childGrid.dataRowList.toArray()[0].cells.toArray()[0]; + const childCell = childGrid.dataRowList.toArray()[0].cells.toArray()[0]; GridFunctions.focusCell(fixture, childCell); - const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; + const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; UIInteractions.triggerEventHandlerKeyDown('end', childGridContent, false, false, true); fixture.detectChanges(); await wait(); @@ -170,10 +171,10 @@ describe('IgxHierarchicalGrid Navigation', () => { fixture.detectChanges(); await wait(); - const childLastCell = childGrid.dataRowList.toArray()[9].cells.toArray()[3]; + const childLastCell = childGrid.dataRowList.toArray()[9].cells.toArray()[3]; GridFunctions.focusCell(fixture, childLastCell); - const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; + const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; UIInteractions.triggerEventHandlerKeyDown('home', childGridContent, false, false, true); await wait(DEBOUNCE_TIME * 3); fixture.detectChanges(); @@ -193,10 +194,10 @@ describe('IgxHierarchicalGrid Navigation', () => { it('should allow navigating to bottom in child grid when child grid target row moves outside the parent view port.', async () => { const childGrid = hierarchicalGrid.gridAPI.getChildGrids(false)[0]; - const childCell = childGrid.dataRowList.first.cells.first; + const childCell = childGrid.dataRowList.first.cells.first; GridFunctions.focusCell(fixture, childCell); - const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; + const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; UIInteractions.triggerEventHandlerKeyDown('arrowdown', childGridContent, false, false, true); // wait for parent grid to complete scroll to child cell. await wait(); @@ -226,15 +227,15 @@ describe('IgxHierarchicalGrid Navigation', () => { fixture.detectChanges(); await wait(); - const childCell = childGrid.dataRowList.toArray()[4].cells.toArray()[0]; + const childCell = childGrid.dataRowList.toArray()[4].cells.toArray()[0]; GridFunctions.focusCell(fixture, childCell); - const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; + const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; UIInteractions.triggerEventHandlerKeyDown('arrowdown', childGridContent, false, false, true); await wait(); fixture.detectChanges(); - const childLastRowCell = childGrid.dataRowList.toArray()[4].cells.toArray()[0]; + const childLastRowCell = childGrid.dataRowList.toArray()[4].cells.toArray()[0]; const selectedCell = fixture.componentInstance.selectedCell; expect(selectedCell.row.index).toBe(childLastRowCell.row.index); expect(selectedCell.column.visibleIndex).toBe(childLastRowCell.column.visibleIndex); @@ -251,27 +252,27 @@ describe('IgxHierarchicalGrid Navigation', () => { await wait(DEBOUNCE_TIME); const childGrid = hierarchicalGrid.gridAPI.getChildGrids(false)[0]; - const childLastRowCell = childGrid.dataRowList.toArray()[9].cells.first; - const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; + const childLastRowCell = childGrid.dataRowList.toArray()[9].cells.first; + const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; GridFunctions.focusCell(fixture, childLastRowCell); UIInteractions.triggerEventHandlerKeyDown('arrowup', childGridContent, false, false, true); fixture.detectChanges(); await wait(DEBOUNCE_TIME); - const childFirstRowCell = childGrid.dataRowList.first.cells.first; + const childFirstRowCell = childGrid.dataRowList.first.cells.first; const selectedCell = fixture.componentInstance.selectedCell; expect(selectedCell.row.index).toBe(childFirstRowCell.row.index); expect(selectedCell.column.visibleIndex).toBe(childFirstRowCell.column.visibleIndex); expect(selectedCell.column.index).toBe(childFirstRowCell.column.index); expect(selectedCell.value).toBe(childFirstRowCell.value); - // check if child row is in view of parent. - const gridOffsets = hierarchicalGrid.tbody.nativeElement.getBoundingClientRect(); - const selectedCellElem = childGrid.gridAPI.get_cell_by_index(selectedCell.row.index, selectedCell.column.field) as IgxGridCellComponent; - const rowOffsets = selectedCellElem.intRow.nativeElement.getBoundingClientRect(); - expect(rowOffsets.top).toBeGreaterThanOrEqual(gridOffsets.top); - expect(rowOffsets.bottom).toBeLessThanOrEqual(gridOffsets.bottom); + // check if child row is in view of parent. + const gridOffsets = hierarchicalGrid.tbody.nativeElement.getBoundingClientRect(); + const selectedCellElem = childGrid.gridAPI.get_cell_by_index(selectedCell.row.index, selectedCell.column.field) as IgxGridCellComponent; + const rowOffsets = selectedCellElem.intRow.nativeElement.getBoundingClientRect(); + expect(rowOffsets.top).toBeGreaterThanOrEqual(gridOffsets.top); + expect(rowOffsets.bottom).toBeLessThanOrEqual(gridOffsets.bottom); }); it('should scroll top of child grid into view when pressing Ctrl + Arrow Up when cell is selected in it.', async () => { @@ -280,15 +281,15 @@ describe('IgxHierarchicalGrid Navigation', () => { await wait(DEBOUNCE_TIME); const childGrid = hierarchicalGrid.gridAPI.getChildGrids(false)[0]; - const childLastRowCell = childGrid.dataRowList.toArray()[9].cells.first; - const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; + const childLastRowCell = childGrid.dataRowList.toArray()[9].cells.first; + const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; GridFunctions.focusCell(fixture, childLastRowCell); UIInteractions.triggerEventHandlerKeyDown('arrowup', childGridContent, false, false, true); fixture.detectChanges(); await wait(DEBOUNCE_TIME); - const childFirstRowCell = childGrid.dataRowList.first.cells.first; + const childFirstRowCell = childGrid.dataRowList.first.cells.first; const selectedCell = fixture.componentInstance.selectedCell; expect(selectedCell.row.index).toBe(childFirstRowCell.row.index); expect(selectedCell.column.visibleIndex).toBe(childFirstRowCell.column.visibleIndex); @@ -323,7 +324,7 @@ describe('IgxHierarchicalGrid Navigation', () => { await wait(DEBOUNCE_TIME); fixture.detectChanges(); - const childFirstCell = childGrid.dataRowList.toArray()[0].cells.toArray()[0]; + const childFirstCell = childGrid.dataRowList.toArray()[0].cells.toArray()[0]; const selectedCell = fixture.componentInstance.selectedCell; expect(selectedCell.row.index).toBe(childFirstCell.row.index); expect(selectedCell.column.index).toBe(childFirstCell.column.index); @@ -424,7 +425,7 @@ describe('IgxHierarchicalGrid Navigation', () => { let parentCell = hierarchicalGrid.gridAPI.get_cell_by_index(38, 'ID'); GridFunctions.focusCell(fixture, parentCell); - // collapse + // collapse UIInteractions.triggerEventHandlerKeyDown('arrowleft', baseHGridContent, true, false, false); fixture.detectChanges(); await wait(); @@ -514,7 +515,7 @@ describe('IgxHierarchicalGrid Navigation', () => { const fchildRowCell = row.cells.first; GridFunctions.focusCell(fixture, fchildRowCell); - const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; + const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; UIInteractions.triggerEventHandlerKeyDown('arrowdown', childGridContent, false, false, false); fixture.detectChanges(); await wait(DEBOUNCE_TIME); @@ -542,7 +543,7 @@ describe('IgxHierarchicalGrid Navigation', () => { let summaryCells = hierarchicalGrid.summariesRowList.toArray()[0].summaryCells.toArray(); - const firstCell = summaryCells[0]; + const firstCell = summaryCells[0]; GridFunctions.focusCell(fixture, firstCell); const footerContent = fixture.debugElement.queryAll(By.css(GRID_FOOTER_CLASS))[2].children[0]; @@ -597,7 +598,7 @@ describe('IgxHierarchicalGrid Navigation', () => { fixture.detectChanges(); await wait(DEBOUNCE_TIME); - expect(document.activeElement.tagName.toLowerCase()).toBe('input'); + expect(document.activeElement.tagName.toLowerCase()).toBe('input'); }); it('should navigate to row edit button "Done" on shift + tab', async () => { @@ -633,7 +634,7 @@ describe('IgxHierarchicalGrid Navigation', () => { fixture.detectChanges(); await wait(DEBOUNCE_TIME); - expect(document.activeElement.tagName.toLowerCase()).toBe('input'); + expect(document.activeElement.tagName.toLowerCase()).toBe('input'); }); }); @@ -671,12 +672,12 @@ describe('IgxHierarchicalGrid Navigation', () => { fixture.detectChanges(); // navigate up - const nestedChildGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[2]; + const nestedChildGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[2]; UIInteractions.triggerEventHandlerKeyDown('arrowup', nestedChildGridContent, false, false, false); fixture.detectChanges(); await wait(DEBOUNCE_TIME); - let nextCell = nestedChild.dataRowList.toArray()[0].cells.toArray()[0]; + let nextCell = nestedChild.dataRowList.toArray()[0].cells.toArray()[0]; let currScrTop = hierarchicalGrid.verticalScrollContainer.getScroll().scrollTop; const elemHeight = nestedChildCell.intRow.nativeElement.clientHeight; // check if parent of parent has been scroll up so that the focused cell is in view @@ -692,7 +693,7 @@ describe('IgxHierarchicalGrid Navigation', () => { fixture.detectChanges(); await wait(DEBOUNCE_TIME); - nextCell = child.dataRowList.toArray()[0].cells.toArray()[0]; + nextCell = child.dataRowList.toArray()[0].cells.toArray()[0]; currScrTop = hierarchicalGrid.verticalScrollContainer.getScroll().scrollTop; expect(oldScrTop - currScrTop).toBeGreaterThanOrEqual(100); @@ -709,7 +710,7 @@ describe('IgxHierarchicalGrid Navigation', () => { // navigate down in nested child GridFunctions.focusCell(fixture, nestedChildCell); - const nestedChildGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[2]; + const nestedChildGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[2]; UIInteractions.triggerEventHandlerKeyDown('arrowdown', nestedChildGridContent, false, false, false); fixture.detectChanges(); await wait(DEBOUNCE_TIME); @@ -729,7 +730,7 @@ describe('IgxHierarchicalGrid Navigation', () => { fixture.detectChanges(); const child = hierarchicalGrid.gridAPI.getChildGrids(false)[0]; - const lastIndex = child.dataView.length - 1; + const lastIndex = child.dataView.length - 1; child.verticalScrollContainer.scrollTo(lastIndex); await wait(); fixture.detectChanges(); @@ -741,7 +742,7 @@ describe('IgxHierarchicalGrid Navigation', () => { const parentCell = hierarchicalGrid.gridAPI.get_cell_by_index(2, 'ID'); GridFunctions.focusCell(fixture, parentCell); - UIInteractions.triggerEventHandlerKeyDown('arrowup', baseHGridContent , false, false, false); + UIInteractions.triggerEventHandlerKeyDown('arrowup', baseHGridContent, false, false, false); await wait(DEBOUNCE_TIME); fixture.detectChanges(); @@ -779,7 +780,7 @@ describe('IgxHierarchicalGrid Navigation', () => { const child2Cell = child2.dataRowList.first.cells.first; GridFunctions.focusCell(fixture, child2Cell); - const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[2]; + const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[2]; UIInteractions.triggerEventHandlerKeyDown('arrowup', childGridContent, false, false, false); fixture.detectChanges(); await wait(DEBOUNCE_TIME); @@ -807,7 +808,7 @@ describe('IgxHierarchicalGrid Navigation', () => { const lastCellPrevRI = child1.dataRowList.last.cells.toArray()[0]; GridFunctions.focusCell(fixture, lastCellPrevRI); - const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; + const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; UIInteractions.triggerEventHandlerKeyDown('arrowdown', childGridContent, false, false, false); await wait(DEBOUNCE_TIME); fixture.detectChanges(); @@ -900,7 +901,7 @@ describe('IgxHierarchicalGrid Navigation', () => { // last cell in child should be focused const childGrid = hierarchicalGrid.gridAPI.getChildGrids(false)[0]; - const childLastCell = childGrid.gridAPI.get_cell_by_index(0, 'Col1'); + const childLastCell = childGrid.gridAPI.get_cell_by_index(0, 'Col1'); expect(childLastCell.selected).toBe(true); expect(childLastCell.active).toBe(true); @@ -920,16 +921,16 @@ describe('IgxHierarchicalGrid Navigation', () => { await wait(DEBOUNCE_TIME); // last cell in child should be focused - const childGrids = fixture.debugElement.queryAll(By.directive(IgxChildGridRowComponent)); + const childGrids = fixture.debugElement.queryAll(By.directive(IgxChildGridRowComponent)); const childGrid = childGrids[1].query(By.directive(IgxHierarchicalGridComponent)).componentInstance; - const childLastCell = childGrid.gridAPI.get_cell_by_index(9, 'ProductName'); + const childLastCell = childGrid.gridAPI.get_cell_by_index(9, 'ProductName'); expect(childLastCell.selected).toBe(true); expect(childLastCell.active).toBe(true); }); it('should navigate to last cell in next child using Arrow Down from last cell of previous child with more columns', async () => { - const childGrids = fixture.debugElement.queryAll(By.directive(IgxChildGridRowComponent)); + const childGrids = fixture.debugElement.queryAll(By.directive(IgxChildGridRowComponent)); const firstChildGrid = childGrids[0].query(By.directive(IgxHierarchicalGridComponent)).componentInstance; const secondChildGrid = childGrids[1].query(By.directive(IgxHierarchicalGridComponent)).componentInstance; @@ -937,16 +938,16 @@ describe('IgxHierarchicalGrid Navigation', () => { fixture.detectChanges(); await wait(); - const firstChildCell = firstChildGrid.gridAPI.get_cell_by_index(9, 'Col1'); + const firstChildCell = firstChildGrid.gridAPI.get_cell_by_index(9, 'Col1'); GridFunctions.focusCell(fixture, firstChildCell); - const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; + const childGridContent = fixture.debugElement.queryAll(By.css(GRID_CONTENT_CLASS))[1]; UIInteractions.triggerEventHandlerKeyDown('arrowdown', childGridContent, false, false, false); fixture.detectChanges(); await wait(DEBOUNCE_TIME); - const secondChildCell = secondChildGrid.gridAPI.get_cell_by_index(0, 'ProductName'); + const secondChildCell = secondChildGrid.gridAPI.get_cell_by_index(0, 'ProductName'); expect(secondChildCell.selected).toBe(true); expect(secondChildCell.active).toBe(true); }); @@ -966,7 +967,7 @@ describe('IgxHierarchicalGrid Navigation', () => { clearGridSubs(); }); - it('should navigate to exact child grid with navigateToChildGrid.', (done) => { + it('should navigate to exact child grid with navigateToChildGrid.', async () => { hierarchicalGrid.primaryKey = 'ID'; hierarchicalGrid.expandChildren = false; fixture.detectChanges(); @@ -977,17 +978,17 @@ describe('IgxHierarchicalGrid Navigation', () => { }; hierarchicalGrid.navigation.navigateToChildGrid([path], () => { fixture.detectChanges(); - const childGrid = hierarchicalGrid.gridAPI.getChildGrid([path]).nativeElement; + const childGrid = hierarchicalGrid.gridAPI.getChildGrid([path]).nativeElement; expect(childGrid).not.toBe(undefined); const parentBottom = hierarchicalGrid.tbody.nativeElement.getBoundingClientRect().bottom; const parentTop = hierarchicalGrid.tbody.nativeElement.getBoundingClientRect().top; // check it's in view within its parent expect(childGrid.getBoundingClientRect().bottom <= parentBottom && childGrid.getBoundingClientRect().top >= parentTop); - done(); + ; }); }); - it('should navigate to exact nested child grid with navigateToChildGrid.', (done) => { + it('should navigate to exact nested child grid with navigateToChildGrid.', async () => { hierarchicalGrid.expandChildren = false; hierarchicalGrid.primaryKey = 'ID'; hierarchicalGrid.childLayoutList.toArray()[0].primaryKey = 'ID'; @@ -1005,16 +1006,16 @@ describe('IgxHierarchicalGrid Navigation', () => { hierarchicalGrid.navigation.navigateToChildGrid([targetRoot, targetNested], () => { fixture.detectChanges(); - const childGrid = hierarchicalGrid.gridAPI.getChildGrid([targetRoot]).nativeElement; + const childGrid = hierarchicalGrid.gridAPI.getChildGrid([targetRoot]).nativeElement; expect(childGrid).not.toBe(undefined); - const childGridNested = hierarchicalGrid.gridAPI.getChildGrid([targetRoot, targetNested]).nativeElement; + const childGridNested = hierarchicalGrid.gridAPI.getChildGrid([targetRoot, targetNested]).nativeElement; expect(childGridNested).not.toBe(undefined); const parentBottom = childGrid.getBoundingClientRect().bottom; const parentTop = childGrid.getBoundingClientRect().top; // check it's in view within its parent expect(childGridNested.getBoundingClientRect().bottom <= parentBottom && childGridNested.getBoundingClientRect().top >= parentTop); - done(); + ; }); }); }); @@ -1033,9 +1034,12 @@ describe('IgxHierarchicalGrid Navigation', () => { imports: [IgxHierarchicalGridComponent, IgxRowIslandComponent] }) export class IgxHierarchicalGridTestBaseComponent { - @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) public hgrid: IgxHierarchicalGridComponent; - @ViewChild('rowIsland', { read: IgxRowIslandComponent, static: true }) public rowIsland: IgxRowIslandComponent; - @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) public rowIsland2: IgxRowIslandComponent; + @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) + public hgrid: IgxHierarchicalGridComponent; + @ViewChild('rowIsland', { read: IgxRowIslandComponent, static: true }) + public rowIsland: IgxRowIslandComponent; + @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) + public rowIsland2: IgxRowIslandComponent; public data; public selectedCell; @@ -1053,12 +1057,13 @@ export class IgxHierarchicalGridTestBaseComponent { const currLevel = level; let children; for (let i = 0; i < count; i++) { - if (level > 0 ) { - children = this.generateData(count / 2 , currLevel - 1); - } - prods.push({ - ID: i, ChildLevels: currLevel, ProductName: 'Product: A' + i, Col1: i, - Col2: i, Col3: i, childData: children, childData2: children }); + if (level > 0) { + children = this.generateData(count / 2, currLevel - 1); + } + prods.push({ + ID: i, ChildLevels: currLevel, ProductName: 'Product: A' + i, Col1: i, + Col2: i, Col3: i, childData: children, childData2: children + }); } return prods; } @@ -1096,7 +1101,8 @@ export class IgxHierarchicalGridTestComplexComponent extends IgxHierarchicalGrid `, imports: [IgxHierarchicalGridComponent, IgxRowIslandComponent] }) -export class IgxHierarchicalGridMultiLayoutComponent extends IgxHierarchicalGridTestBaseComponent {} +export class IgxHierarchicalGridMultiLayoutComponent extends IgxHierarchicalGridTestBaseComponent { +} @Component({ template: ` @@ -1126,4 +1132,5 @@ export class IgxHierarchicalGridMultiLayoutComponent extends IgxHierarchicalGrid `, imports: [IgxHierarchicalGridComponent, IgxRowIslandComponent, IgxColumnComponent] }) -export class IgxHierarchicalGridSmallerChildComponent extends IgxHierarchicalGridTestBaseComponent {} +export class IgxHierarchicalGridSmallerChildComponent extends IgxHierarchicalGridTestBaseComponent { +} diff --git a/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.selection.spec.ts b/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.selection.spec.ts index 7291eab9e8c..ab2de3efec1 100644 --- a/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.selection.spec.ts +++ b/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.selection.spec.ts @@ -3,20 +3,14 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxHierarchicalGridComponent } from './hierarchical-grid.component'; import { UIInteractions, wait } from '../../../test-utils/ui-interactions.spec'; import { IgxHierarchicalRowComponent } from './hierarchical-row.component'; -import { - IgxHierarchicalGridTestBaseComponent, - IgxHierarchicalGridRowSelectionComponent, - IgxHierarchicalGridRowSelectionTestSelectRowOnClickComponent, - IgxHierarchicalGridCustomSelectorsComponent, - IgxHierarchicalGridRowSelectionNoTransactionsComponent, - IgxHierGridExternalAdvancedFilteringComponent -} from '../../../test-utils/hierarchical-grid-components.spec'; +import { IgxHierarchicalGridTestBaseComponent, IgxHierarchicalGridRowSelectionComponent, IgxHierarchicalGridRowSelectionTestSelectRowOnClickComponent, IgxHierarchicalGridCustomSelectorsComponent, IgxHierarchicalGridRowSelectionNoTransactionsComponent, IgxHierGridExternalAdvancedFilteringComponent } from '../../../test-utils/hierarchical-grid-components.spec'; import { GridSelectionFunctions, GridFunctions } from '../../../test-utils/grid-functions.spec'; import { CellType, GridSelectionMode, IgxGridNavigationService } from 'igniteui-angular/grids/core'; import { QueryList } from '@angular/core'; import { SampleTestData } from '../../../test-utils/sample-test-data.spec'; import { setElementSize } from '../../../test-utils/helper-utils.spec'; import { IgxStringFilteringOperand, ɵSize } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxHierarchicalGrid selection #hGrid', () => { let fix; @@ -40,7 +34,7 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { IgxGridNavigationService ] }).compileComponents(); - })) + })); describe('Cell selection', () => { beforeEach(() => { @@ -80,7 +74,7 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { expect(fCell.selected).toBeFalsy(); // select parent cell - const parentSpy = spyOn(hierarchicalGrid.selected, 'emit').and.callThrough(); + const parentSpy = vi.spyOn(hierarchicalGrid.selected, 'emit'); firstRow = hierarchicalGrid.gridAPI.get_row_by_index(0) as IgxHierarchicalRowComponent; fCell = firstRow.cells.toArray()[0]; GridFunctions.focusCell(fix, fCell); @@ -154,8 +148,8 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { UIInteractions.simulateClickAndSelectEvent(cell.nativeElement, true); fix.detectChanges(); - expect(cell.active).toBeTrue(); - expect(cell.selected).toBeFalse(); + expect(cell.active).toBe(true); + expect(cell.selected).toBe(false); expect(childGridLevel1.getSelectedRanges().length).toBe(0); cell = hierarchicalGrid.gridAPI.get_cell_by_index(2, 'ID'); @@ -289,7 +283,7 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { fix.detectChanges(); GridSelectionFunctions.verifyCellSelected(cell, true); - expect(cell.active).toBeFalse(); + expect(cell.active).toBe(false); GridSelectionFunctions.verifyCellsRegionSelected(hierarchicalGrid, 1, 3, 1, 2); GridSelectionFunctions.verifySelectedRange(hierarchicalGrid, 1, 3, 1, 2); })); @@ -324,7 +318,7 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { fix.detectChanges(); GridSelectionFunctions.verifyCellSelected(cell, true); - expect(cell.active).toBeFalse(); + expect(cell.active).toBe(false); GridSelectionFunctions.verifyCellsRegionSelected(childGridLevel1, 1, 3, 1, 2); GridSelectionFunctions.verifySelectedRange(childGridLevel1, 1, 3, 1, 2); })); @@ -342,8 +336,8 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { UIInteractions.simulateClickAndSelectEvent(cell); fix.detectChanges(); - expect(cell.selected).toBeTrue(); - expect(cell.active).toBeTrue(); + expect(cell.selected).toBe(true); + expect(cell.active).toBe(true); hierarchicalGrid.navigateTo(5, -1); fix.detectChanges(); @@ -353,7 +347,7 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { fix.detectChanges(); GridSelectionFunctions.verifyCellSelected(cell, true); - expect(cell.active).toBeTrue(); + expect(cell.active).toBe(true); GridSelectionFunctions.verifyCellsRegionSelected(hierarchicalGrid, 1, 5, 1, 2); GridSelectionFunctions.verifySelectedRange(hierarchicalGrid, 1, 5, 1, 2); }); @@ -371,8 +365,8 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { UIInteractions.simulateClickAndSelectEvent(cell); fix.detectChanges(); - expect(cell.selected).toBeTrue(); - expect(cell.active).toBeTrue(); + expect(cell.selected).toBe(true); + expect(cell.active).toBe(true); hierarchicalGrid.navigateTo(5, -1); fix.detectChanges(); @@ -382,7 +376,7 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { fix.detectChanges(); GridSelectionFunctions.verifyCellSelected(cell, true); - expect(cell.active).toBeTrue(); + expect(cell.active).toBe(true); GridSelectionFunctions.verifyCellsRegionSelected(hierarchicalGrid, 1, 5, 1, 2); GridSelectionFunctions.verifySelectedRange(hierarchicalGrid, 1, 5, 1, 2); @@ -413,7 +407,7 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { fix.detectChanges(); expect(hierarchicalGrid.getSelectedRanges().length).toBe(0); - expect(cell.selected).toBeTrue(); + expect(cell.selected).toBe(true); GridSelectionFunctions.verifySelectedRange(childGridLevel1, 0, 0, 2, 2); cell = hierarchicalGrid.gridAPI.get_cell_by_index(0, 'ProductName'); @@ -426,7 +420,7 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { }); it('should clear the selection in parent grid when continue navigation in the child grid', fakeAsync(() => { - setElementSize(hierarchicalGrid.nativeElement, ɵSize.Small) + setElementSize(hierarchicalGrid.nativeElement, ɵSize.Small); fix.detectChanges(); const row = hierarchicalGrid.gridAPI.get_row_by_index(4) as IgxHierarchicalRowComponent; @@ -438,8 +432,8 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { UIInteractions.simulateClickAndSelectEvent(cell); fix.detectChanges(); - expect(cell.selected).toBeTrue(); - expect(cell.active).toBeTrue(); + expect(cell.selected).toBe(true); + expect(cell.active).toBe(true); cell = hierarchicalGrid.gridAPI.get_cell_by_index(4, 'ChildLevels'); @@ -457,7 +451,7 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { })); it('should NOT be able to create range selection between parent and child grid on mouse click + shift key', fakeAsync(() => { - setElementSize(hierarchicalGrid.nativeElement, ɵSize.Small) + setElementSize(hierarchicalGrid.nativeElement, ɵSize.Small); fix.detectChanges(); const row = hierarchicalGrid.gridAPI.get_row_by_index(2) as IgxHierarchicalRowComponent; @@ -498,7 +492,7 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { column.bodyTemplate = component.customCell; fix.detectChanges(); - const selectionChangeSpy = spyOn(hierarchicalGrid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(hierarchicalGrid.rangeSelected, 'emit'); const cell = hierarchicalGrid.gridAPI.get_cell_by_index(0, 'ID'); const cellElement = cell.nativeElement; const span = cellElement.querySelector('span'); @@ -554,7 +548,7 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { } })); - it('should able to change rowSelection at runtime', async() => { + it('should able to change rowSelection at runtime', async () => { hierarchicalGrid.width = '1000px'; fix.detectChanges(); hierarchicalGrid.expandChildren = true; @@ -648,9 +642,9 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { fix.detectChanges(); const childGrid = hierarchicalGrid.gridAPI.getChildGrids(false)[0]; const secondChildGrid = hierarchicalGrid.gridAPI.getChildGrids(false)[1]; - const parentSpy = spyOn(hierarchicalGrid.rowSelectionChanging, 'emit').and.callThrough(); - const childSpy = spyOn(childGrid.rowSelectionChanging, 'emit').and.callThrough(); - const secondChildSpy = spyOn(secondChildGrid.rowSelectionChanging, 'emit').and.callThrough(); + const parentSpy = vi.spyOn(hierarchicalGrid.rowSelectionChanging, 'emit'); + const childSpy = vi.spyOn(childGrid.rowSelectionChanging, 'emit'); + const secondChildSpy = vi.spyOn(secondChildGrid.rowSelectionChanging, 'emit'); const mockEvent = new MouseEvent('click'); // Click on a row in child grid @@ -774,8 +768,7 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { UIInteractions.simulateClickEvent(fourthRow.nativeElement, true); fix.detectChanges(); - GridSelectionFunctions.verifyRowsArraySelected( - [firstRow, hierarchicalGrid.gridAPI.get_row_by_index(2), hierarchicalGrid.gridAPI.get_row_by_index(3), fourthRow]); + GridSelectionFunctions.verifyRowsArraySelected([firstRow, hierarchicalGrid.gridAPI.get_row_by_index(2), hierarchicalGrid.gridAPI.get_row_by_index(3), fourthRow]); expect(hierarchicalGrid.selectedRows).toEqual(['0', '1', '2', '3']); // Verify no rows are selected in the child grid @@ -805,8 +798,7 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { UIInteractions.simulateClickEvent(fourthRow.nativeElement, true); fix.detectChanges(); - GridSelectionFunctions.verifyRowsArraySelected( - [firstRow, hierarchicalGrid.gridAPI.get_row_by_index(2), hierarchicalGrid.gridAPI.get_row_by_index(3), fourthRow], false); + GridSelectionFunctions.verifyRowsArraySelected([firstRow, hierarchicalGrid.gridAPI.get_row_by_index(2), hierarchicalGrid.gridAPI.get_row_by_index(3), fourthRow], false); expect(hierarchicalGrid.selectedRows).toEqual([]); // Verify no rows are selected in the child grid @@ -1298,21 +1290,21 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { fix.componentInstance.selectedRows = ['0', '2', '3']; fix.detectChanges(); - expect(hierarchicalGrid.getRowByKey('0').selected).toBeTrue(); - expect(hierarchicalGrid.getRowByKey('1').selected).toBeFalse(); + expect(hierarchicalGrid.getRowByKey('0').selected).toBe(true); + expect(hierarchicalGrid.getRowByKey('1').selected).toBe(false); fix.componentInstance.selectedRows = ['2']; fix.detectChanges(); - expect(hierarchicalGrid.getRowByKey('2').selected).toBeTrue(); - expect(hierarchicalGrid.getRowByKey('0').selected).toBeFalse(); + expect(hierarchicalGrid.getRowByKey('2').selected).toBe(true); + expect(hierarchicalGrid.getRowByKey('0').selected).toBe(false); }); it('Should not clear root selection state when changing selection mode of child grid', () => { rowIsland1.rowSelection = GridSelectionMode.multiple; fix.componentInstance.selectedRows = ['0', '1']; fix.detectChanges(); - expect(hierarchicalGrid.getRowByKey('0').selected).toBeTrue(); + expect(hierarchicalGrid.getRowByKey('0').selected).toBe(true); const thirdRow = hierarchicalGrid.gridAPI.get_row_by_index(2) as IgxHierarchicalRowComponent; thirdRow.toggle(); @@ -1518,7 +1510,7 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { }); it('Should have the correct properties in the custom row selector header template context', () => { - spyOn(fix.componentInstance, 'handleHeadSelectorClick').and.callThrough(); + vi.spyOn(fix.componentInstance, 'handleHeadSelectorClick'); GridSelectionFunctions.headerCheckboxClick(hGrid); fix.detectChanges(); @@ -1526,13 +1518,13 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { expect(fix.componentInstance.handleHeadSelectorClick).toHaveBeenCalledWith({ selectedCount: 0, totalCount: hGrid.data.length, - selectAll: jasmine.anything(), - deselectAll: jasmine.anything() + selectAll: expect.anything(), + deselectAll: expect.anything() }); }); it('Should have the correct properties in the custom row selector template context', () => { - spyOn(fix.componentInstance, 'handleRowSelectorClick').and.callThrough(); + vi.spyOn(fix.componentInstance, 'handleRowSelectorClick'); GridSelectionFunctions.rowCheckboxClick(hGrid.gridAPI.get_row_by_index(1)); fix.detectChanges(); @@ -1542,8 +1534,8 @@ describe('IgxHierarchicalGrid selection #hGrid', () => { rowID: '1', key: '1', selected: false, - select: jasmine.anything(), - deselect: jasmine.anything() + select: expect.anything(), + deselect: expect.anything() }); }); diff --git a/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.spec.ts b/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.spec.ts index 0bfe2bcab69..ef4466d99c4 100644 --- a/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.spec.ts +++ b/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.spec.ts @@ -18,6 +18,7 @@ import { setElementSize } from '../../../test-utils/helper-utils.spec'; import { ColumnType, IgxStringFilteringOperand, ɵSize, getComponentSize } from 'igniteui-angular/core'; import { IgxIconComponent } from 'igniteui-angular/icon'; import { IGridCreatedEventArgs } from './events'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('Basic IgxHierarchicalGrid #hGrid', () => { @@ -43,7 +44,7 @@ describe('Basic IgxHierarchicalGrid #hGrid', () => { IgxGridNavigationService ] }).compileComponents(); - })) + })); describe('Init IgxHierarchicalGrid #hGrid', () => { let fixture; @@ -397,13 +398,13 @@ describe('Basic IgxHierarchicalGrid #hGrid', () => { expect(hierarchicalGrid.gridSize).toEqual(ɵSize.Large); expect(getComponentSize(hierarchicalGrid.nativeElement)).toEqual('3'); - setElementSize(hierarchicalGrid.nativeElement, ɵSize.Medium) + setElementSize(hierarchicalGrid.nativeElement, ɵSize.Medium); fixture.detectChanges(); expect(childGrid.gridSize).toBe(ɵSize.Medium); expect(getComponentSize(hierarchicalGrid.nativeElement)).toEqual('2'); - setElementSize(hierarchicalGrid.nativeElement, ɵSize.Small) + setElementSize(hierarchicalGrid.nativeElement, ɵSize.Small); fixture.detectChanges(); expect(childGrid.gridSize).toBe(ɵSize.Small); @@ -626,7 +627,7 @@ describe('Basic IgxHierarchicalGrid #hGrid', () => { }); it('should emit columnInit when a column is added runtime.', async () => { - spyOn(hierarchicalGrid.columnInit, 'emit').and.callThrough(); + vi.spyOn(hierarchicalGrid.columnInit, 'emit'); fixture.detectChanges(); fixture.componentInstance.showAnotherCol = true; fixture.detectChanges(); @@ -636,25 +637,20 @@ describe('Basic IgxHierarchicalGrid #hGrid', () => { }); it('should throw a warning when primaryKey is set to a non-existing data field', () => { - jasmine.getEnv().allowRespy(true); - spyOn(console, 'warn'); + vi.spyOn(console, 'warn'); hierarchicalGrid.primaryKey = 'testField'; fixture.componentInstance.rowIsland.primaryKey = 'testField-rowIsland'; fixture.componentInstance.rowIsland2.primaryKey = 'testField-rowIsland2'; fixture.detectChanges(); - expect(console.warn).toHaveBeenCalledWith( - `Field "${hierarchicalGrid.primaryKey}" is not defined in the data. Set \`primaryKey\` to a valid field.` - ); + expect(console.warn).toHaveBeenCalledWith(`Field "${hierarchicalGrid.primaryKey}" is not defined in the data. Set \`primaryKey\` to a valid field.`); let row1 = hierarchicalGrid.gridAPI.get_row_by_index(0) as IgxHierarchicalRowComponent; UIInteractions.simulateClickAndSelectEvent(row1.expander); fixture.detectChanges(); let rowIsland = fixture.componentInstance.rowIsland; - expect(console.warn).toHaveBeenCalledWith( - `Field "${rowIsland.primaryKey}" is not defined in the data. Set \`primaryKey\` to a valid field.` - ); + expect(console.warn).toHaveBeenCalledWith(`Field "${rowIsland.primaryKey}" is not defined in the data. Set \`primaryKey\` to a valid field.`); const secondLevelGrid = hierarchicalGrid.gridAPI.getChildGrids()[0]; row1 = secondLevelGrid.gridAPI.get_row_by_index(0) as IgxHierarchicalRowComponent; @@ -662,10 +658,7 @@ describe('Basic IgxHierarchicalGrid #hGrid', () => { fixture.detectChanges(); rowIsland = fixture.componentInstance.rowIsland2; - expect(console.warn).toHaveBeenCalledWith( - `Field "${rowIsland.primaryKey}" is not defined in the data. Set \`primaryKey\` to a valid field.` - ); - jasmine.getEnv().allowRespy(false); + expect(console.warn).toHaveBeenCalledWith(`Field "${rowIsland.primaryKey}" is not defined in the data. Set \`primaryKey\` to a valid field.`); }); it('should calculate correct column headers width when rowSelection + expand indicators', () => { @@ -676,7 +669,7 @@ describe('Basic IgxHierarchicalGrid #hGrid', () => { const headerRowDiv = headerRowElement.querySelector(".igx-grid__tr"); const headerRowChildren = Array.from(headerRowDiv.children); - const elementsWidth = headerRowChildren.reduce((acc,el) => acc+(el as HTMLElement).offsetWidth, 0); + const elementsWidth = headerRowChildren.reduce((acc, el) => acc + (el as HTMLElement).offsetWidth, 0); expect(elementsWidth).toEqual((headerRowDiv as HTMLElement).offsetWidth); }); }); @@ -909,10 +902,10 @@ describe('Basic IgxHierarchicalGrid #hGrid', () => { const cell = childGrid.getRowByIndex(0).cells[0] as CellType; const ri1 = fixture.componentInstance.rowIsland1; - expect(cell.active).toBeFalse(); - expect(cell.selected).toBeFalse(); + expect(cell.active).toBe(false); + expect(cell.selected).toBe(false); - spyOn(ri1.cellClick, 'emit').and.callThrough(); + vi.spyOn(ri1.cellClick, 'emit'); const event = new Event('click'); cellElem.nativeElement.dispatchEvent(event); @@ -929,7 +922,7 @@ describe('Basic IgxHierarchicalGrid #hGrid', () => { cell.selected = true; fixture.detectChanges(); - expect(cell.selected).toBeTrue(); + expect(cell.selected).toBe(true); expect(childGrid.selectedCells[0].row.index).toEqual(cell.row.index); expect(childGrid.selectedCells[0].column.field).toEqual(cell.column.field); }); @@ -1069,15 +1062,15 @@ describe('Basic IgxHierarchicalGrid #hGrid', () => { it('should update columns property of row islands on columns change.', fakeAsync(() => { - expect(hierarchicalGrid.childLayoutList.first.columns.length).toEqual(2, 'Initial columns length should be 2'); - expect(hierarchicalGrid.childLayoutList.first.columnList.length).toEqual(2, 'Initial columnList length should be 2'); + expect(hierarchicalGrid.childLayoutList.first.columns.length, 'Initial columns length should be 2').toEqual(2); + expect(hierarchicalGrid.childLayoutList.first.columnList.length, 'Initial columnList length should be 2').toEqual(2); fixture.componentInstance.toggleColumns = false; fixture.detectChanges(); tick(); - expect(hierarchicalGrid.childLayoutList.first.columns.length).toEqual(0, 'Columns length should be 0 after toggle'); - expect(hierarchicalGrid.childLayoutList.first.columnList.length).toEqual(0, 'ColumnList length should be 0 after toggle'); + expect(hierarchicalGrid.childLayoutList.first.columns.length, 'Columns length should be 0 after toggle').toEqual(0); + expect(hierarchicalGrid.childLayoutList.first.columnList.length, 'ColumnList length should be 0 after toggle').toEqual(0); })); it('should resolve child grid cols default editable prop correctly based on row island\'s rowEditable.', () => { @@ -1093,8 +1086,8 @@ describe('Basic IgxHierarchicalGrid #hGrid', () => { const childGrids = fixture.debugElement.queryAll(By.css('igx-child-grid-row')); const childGrid1 = childGrids[0].query(By.css('igx-hierarchical-grid')).componentInstance; - expect(childGrid1.columns[0].editable).toBeTrue(); - expect(childGrid1.columns[1].editable).toBeTrue(); + expect(childGrid1.columns[0].editable).toBe(true); + expect(childGrid1.columns[1].editable).toBe(true); }); it('should update the row island summary UI when disabledSummaries is changed at runtime', fakeAsync(() => { @@ -1120,7 +1113,7 @@ describe('Basic IgxHierarchicalGrid #hGrid', () => { expect(summaryCell).toBeDefined(); expect(summaryCell.textContent.trim().length).toBeGreaterThan(0); - const getterSpy = spyOnProperty(column, 'disabledSummaries', 'get').and.callThrough(); + const getterSpy = vi.spyOn(column, 'disabledSummaries', 'get'); column.disabledSummaries = ['count']; fixture.detectChanges(); @@ -1135,16 +1128,16 @@ describe('Basic IgxHierarchicalGrid #hGrid', () => { const row = hierarchicalGrid.gridAPI.get_row_by_index(0) as IgxHierarchicalRowComponent; const rowIsland = fixture.componentInstance.rowIsland1; - spyOn(rowIsland.gridCreated, 'emit').and.callThrough(); - spyOn(rowIsland.gridInitialized, 'emit').and.callThrough(); + vi.spyOn(rowIsland.gridCreated, 'emit'); + vi.spyOn(rowIsland.gridInitialized, 'emit'); UIInteractions.simulateClickAndSelectEvent(row.expander); fixture.detectChanges(); expect(rowIsland.gridCreated.emit).toHaveBeenCalledTimes(1); - expect(rowIsland.gridCreated.emit).toHaveBeenCalledWith(jasmine.objectContaining({ parentRowData: row.data })); + expect(rowIsland.gridCreated.emit).toHaveBeenCalledWith(expect.objectContaining({ parentRowData: row.data })); expect(rowIsland.gridInitialized.emit).toHaveBeenCalledTimes(1); - expect(rowIsland.gridInitialized.emit).toHaveBeenCalledWith(jasmine.objectContaining({ parentRowData: row.data })); + expect(rowIsland.gridInitialized.emit).toHaveBeenCalledWith(expect.objectContaining({ parentRowData: row.data })); }); }); @@ -1592,7 +1585,7 @@ describe('Basic IgxHierarchicalGrid #hGrid', () => { const firstHeaderIcon = childHeader1.query(By.css('.igx-icon')); - spyOn(child1Grid.componentInstance.columns[0].pinnedChange, 'emit').and.callThrough(); + vi.spyOn(child1Grid.componentInstance.columns[0].pinnedChange, 'emit'); expect(GridFunctions.isHeaderPinned(childHeader1.parent)).toBeFalsy(); expect(child1Grid.componentInstance.columns[0].pinned).toBeFalsy(); @@ -1611,7 +1604,7 @@ describe('Basic IgxHierarchicalGrid #hGrid', () => { const secondHeaderIcon = childHeader2.query(By.css('.igx-icon')); const lastIndex = child1Grid.componentInstance.columns.length - 1; - spyOn(child1Grid.componentInstance.columns[lastIndex].hiddenChange, 'emit').and.callThrough(); + vi.spyOn(child1Grid.componentInstance.columns[lastIndex].hiddenChange, 'emit'); expect(child1Grid.componentInstance.columns[lastIndex].hidden).toBeFalsy(); expect(secondHeaderIcon).toBeDefined(); @@ -1943,25 +1936,25 @@ describe('Basic IgxHierarchicalGrid #hGrid', () => { const expandIcon = columnGroup2Header.queryAll(By.css('.igx-icon'))[0]; const pinIcon = columnGroup2Header.queryAll(By.css('.igx-icon'))[1]; - expect(columnGroup2.expanded).toBeFalse(); - expect(columnGroup2.pinned).toBeFalse(); + expect(columnGroup2.expanded).toBe(false); + expect(columnGroup2.pinned).toBe(false); UIInteractions.simulateClickEvent(expandIcon.nativeElement); fixture.detectChanges(); - expect(columnGroup2.expanded).toBeTrue(); + expect(columnGroup2.expanded).toBe(true); expect(fixture.componentInstance.expandedArgs).toBeDefined(); - expect(fixture.componentInstance.expandedArgs.args).toBeTrue(); + expect(fixture.componentInstance.expandedArgs.args).toBe(true); expect(fixture.componentInstance.hiddenArgs).toBeDefined(); - expect(fixture.componentInstance.hiddenArgs.args).toBeTrue(); + expect(fixture.componentInstance.hiddenArgs.args).toBe(true); UIInteractions.simulateClickEvent(pinIcon.nativeElement); fixture.detectChanges(); - expect(columnGroup2.pinned).toBeTrue(); + expect(columnGroup2.pinned).toBe(true); expect(fixture.componentInstance.pinnedArgs).toBeDefined(); - expect(fixture.componentInstance.pinnedArgs.args).toBeTrue(); + expect(fixture.componentInstance.pinnedArgs.args).toBe(true); }); }); }); @@ -1988,9 +1981,12 @@ describe('Basic IgxHierarchicalGrid #hGrid', () => { imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent] }) export class IgxHierarchicalGridTestBaseComponent { - @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) public hgrid: IgxHierarchicalGridComponent; - @ViewChild('rowIsland', { read: IgxRowIslandComponent, static: true }) public rowIsland: IgxRowIslandComponent; - @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) public rowIsland2: IgxRowIslandComponent; + @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) + public hgrid: IgxHierarchicalGridComponent; + @ViewChild('rowIsland', { read: IgxRowIslandComponent, static: true }) + public rowIsland: IgxRowIslandComponent; + @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) + public rowIsland2: IgxRowIslandComponent; public data; public width = '500px'; public showAnotherCol = false; @@ -2043,8 +2039,10 @@ export class IgxHierarchicalGridTestBaseComponent { imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent] }) export class IgxHierarchicalGridMultiLayoutComponent extends IgxHierarchicalGridTestBaseComponent { - @ViewChild('rowIsland1', { read: IgxRowIslandComponent, static: true }) public rowIsland1: IgxRowIslandComponent; - @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) public override rowIsland2: IgxRowIslandComponent; + @ViewChild('rowIsland1', { read: IgxRowIslandComponent, static: true }) + public rowIsland1: IgxRowIslandComponent; + @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) + public override rowIsland2: IgxRowIslandComponent; public height = '100px'; public toggleColumns = true; } @@ -2251,7 +2249,8 @@ export class IgxHierarchicalGridToggleRIAndColsComponent extends IgxHierarchical `, imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent, IgxRowExpandedIndicatorDirective, IgxRowCollapsedIndicatorDirective, IgxHeaderExpandedIndicatorDirective, IgxHeaderCollapsedIndicatorDirective] }) -export class IgxHierarchicalGridCustomTemplateComponent extends IgxHierarchicalGridTestBaseComponent { } +export class IgxHierarchicalGridCustomTemplateComponent extends IgxHierarchicalGridTestBaseComponent { +} @Component({ template: ` @@ -2312,7 +2311,8 @@ export class IgxHierarchicalGridCustomTemplateComponent extends IgxHierarchicalG IgxHeaderCollapsedIndicatorDirective ] }) -export class IgxHierarchicalGridCustomFilteringTemplateComponent extends IgxHierarchicalGridTestBaseComponent { } +export class IgxHierarchicalGridCustomFilteringTemplateComponent extends IgxHierarchicalGridTestBaseComponent { +} @Component({ template: ` @@ -2374,7 +2374,8 @@ export class IgxHierarchicalGridHidingPinningColumnsComponent extends IgxHierarc `, imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent, IgxRowEditTextDirective, IgxRowEditActionsDirective] }) -export class IgxHierarchicalGridCustomRowEditOverlayComponent extends IgxHierarchicalGridTestBaseComponent { } +export class IgxHierarchicalGridCustomRowEditOverlayComponent extends IgxHierarchicalGridTestBaseComponent { +} @Component({ template: ` @@ -2398,7 +2399,8 @@ export class IgxHierarchicalGridCustomRowEditOverlayComponent extends IgxHierarc `, imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent, IgxRowEditTextDirective, IgxRowEditActionsDirective] }) -export class IgxHierarchicalGridAutoSizeColumnsComponent extends IgxHierarchicalGridTestBaseComponent { } +export class IgxHierarchicalGridAutoSizeColumnsComponent extends IgxHierarchicalGridTestBaseComponent { +} @Component({ template: ` diff --git a/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.virtualization.spec.ts b/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.virtualization.spec.ts index 59dab92f738..374083ca4af 100644 --- a/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.virtualization.spec.ts +++ b/projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.virtualization.spec.ts @@ -14,6 +14,7 @@ import { IgxHierarchicalGridDefaultComponent } from '../../../test-utils/hierarc import { firstValueFrom } from 'rxjs'; import { FilteringExpressionsTree, FilteringLogic, IgxStringFilteringOperand } from 'igniteui-angular/core'; import { IgxGridNavigationService } from 'igniteui-angular/grids/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxHierarchicalGrid Virtualization #hGrid', () => { let fixture; @@ -181,20 +182,16 @@ describe('IgxHierarchicalGrid Virtualization #hGrid', () => { fixture.detectChanges(); expect(hierarchicalGrid.verticalScrollContainer.state.startIndex).toEqual(startIndex); - expect( - parseInt(GridFunctions.getGridDisplayContainer(fixture).nativeElement.style.top, 10) - - parseInt(topOffset, 10) - ).toBeLessThanOrEqual(1); + expect(parseInt(GridFunctions.getGridDisplayContainer(fixture).nativeElement.style.top, 10) - + parseInt(topOffset, 10)).toBeLessThanOrEqual(1); (secondRow.nativeElement.children[0] as HTMLElement).click(); await wait(100); fixture.detectChanges(); // collapse second row expect(hierarchicalGrid.verticalScrollContainer.state.startIndex).toEqual(startIndex); - expect( - parseInt(GridFunctions.getGridDisplayContainer(fixture).nativeElement.style.top, 10) - - parseInt(topOffset, 10) - ).toBeLessThanOrEqual(1); + expect(parseInt(GridFunctions.getGridDisplayContainer(fixture).nativeElement.style.top, 10) - + parseInt(topOffset, 10)).toBeLessThanOrEqual(1); }); it('should not lose scroll position after expanding a row when there are already expanded rows above.', async () => { @@ -239,20 +236,16 @@ describe('IgxHierarchicalGrid Virtualization #hGrid', () => { fixture.detectChanges(); expect(hierarchicalGrid.verticalScrollContainer.state.startIndex).toEqual(startIndex); - expect( - parseInt(GridFunctions.getGridDisplayContainer(fixture).nativeElement.style.top, 10) - - parseInt(topOffset, 10) - ).toBeLessThanOrEqual(1); + expect(parseInt(GridFunctions.getGridDisplayContainer(fixture).nativeElement.style.top, 10) - + parseInt(topOffset, 10)).toBeLessThanOrEqual(1); (secondRow.nativeElement.children[0] as HTMLElement).click(); await wait(); fixture.detectChanges(); // collapse second row expect(hierarchicalGrid.verticalScrollContainer.state.startIndex).toEqual(startIndex); - expect( - parseInt(GridFunctions.getGridDisplayContainer(fixture).nativeElement.style.top, 10) - - parseInt(topOffset, 10) - ).toBeLessThanOrEqual(1); + expect(parseInt(GridFunctions.getGridDisplayContainer(fixture).nativeElement.style.top, 10) - + parseInt(topOffset, 10)).toBeLessThanOrEqual(1); }); it('should be able to scroll last row in view after all rows get expanded.', async () => { @@ -266,12 +259,11 @@ describe('IgxHierarchicalGrid Virtualization #hGrid', () => { await wait(100); fixture.detectChanges(); - expect( - hierarchicalGrid.verticalScrollContainer.state.startIndex + + expect(hierarchicalGrid.verticalScrollContainer.state.startIndex + hierarchicalGrid.verticalScrollContainer.state.chunkSize).toBe(80); expect(hierarchicalGrid.verticalScrollContainer.getScroll().scrollTop) .toEqual(hierarchicalGrid.verticalScrollContainer.getScroll().scrollHeight - - parseInt(hierarchicalGrid.verticalScrollContainer.igxForContainerSize, 10)); + parseInt(hierarchicalGrid.verticalScrollContainer.igxForContainerSize, 10)); }); it('should update scroll height after expanding/collapsing rows.', async () => { @@ -299,7 +291,8 @@ describe('IgxHierarchicalGrid Virtualization #hGrid', () => { childData: fixture.componentInstance.generateData(100, 0) } ] - }]; + } + ]; fixture.detectChanges(); let scrHeight = hierarchicalGrid.verticalScrollContainer.getScroll().scrollHeight; @@ -350,20 +343,18 @@ describe('IgxHierarchicalGrid Virtualization #hGrid', () => { expect(childRowComponent.index).toBe(4); }); - it('should update scrollbar when expanding a row with data loaded after initial view initialization', (done) => { + it('should update scrollbar when expanding a row with data loaded after initial view initialization', async () => { fixture.componentInstance.data = fixture.componentInstance.generateData(10, 0); fixture.detectChanges(); - fixture.componentInstance.rowIsland.gridCreated.pipe(first(), delay(200)).subscribe( - async (args) => { - args.grid.data = fixture.componentInstance.generateData(10, 0); - await wait(200); - fixture.detectChanges(); + fixture.componentInstance.rowIsland.gridCreated.pipe(first(), delay(200)).subscribe(async (args) => { + args.grid.data = fixture.componentInstance.generateData(10, 0); + await wait(200); + fixture.detectChanges(); - expect((hierarchicalGrid.verticalScrollContainer.getScroll().children[0] as HTMLElement).offsetHeight).toEqual(958); - done(); - } - ); + expect((hierarchicalGrid.verticalScrollContainer.getScroll().children[0] as HTMLElement).offsetHeight).toEqual(958); + ; + }); expect((hierarchicalGrid.verticalScrollContainer.getScroll().children[0] as HTMLElement).offsetHeight).toEqual(510); @@ -386,8 +377,8 @@ describe('IgxHierarchicalGrid Virtualization #hGrid', () => { const elem = verticalScroll['scrollComponent'].elementRef.nativeElement; - spyOn(ri.gridScroll, 'emit').and.callThrough(); - spyOn(ri.dataPreLoad, 'emit').and.callThrough(); + vi.spyOn(ri.gridScroll, 'emit'); + vi.spyOn(ri.dataPreLoad, 'emit'); // scroll down @@ -497,9 +488,12 @@ describe('IgxHierarchicalGrid Virtualization Custom Scenarios #hGrid', () => { imports: [IgxHierarchicalGridComponent, IgxRowIslandComponent] }) export class IgxHierarchicalGridTestBaseComponent { - @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) public hgrid: IgxHierarchicalGridComponent; - @ViewChild('rowIsland', { read: IgxRowIslandComponent, static: true }) public rowIsland: IgxRowIslandComponent; - @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) public rowIsland2: IgxRowIslandComponent; + @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) + public hgrid: IgxHierarchicalGridComponent; + @ViewChild('rowIsland', { read: IgxRowIslandComponent, static: true }) + public rowIsland: IgxRowIslandComponent; + @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) + public rowIsland2: IgxRowIslandComponent; public data; diff --git a/projects/igniteui-angular/grids/pivot-grid/src/pivot-data-selector.spec.ts b/projects/igniteui-angular/grids/pivot-grid/src/pivot-data-selector.spec.ts index e5d1ac8f61b..2da67dfe3ce 100644 --- a/projects/igniteui-angular/grids/pivot-grid/src/pivot-data-selector.spec.ts +++ b/projects/igniteui-angular/grids/pivot-grid/src/pivot-data-selector.spec.ts @@ -8,16 +8,11 @@ import { IgxInputDirective } from 'igniteui-angular/input-group'; import { IgxPivotGridTestBaseComponent } from "../../../test-utils/pivot-grid-samples.spec"; import { UIInteractions, wait } from "../../../test-utils/ui-interactions.spec"; import { IgxPivotDataSelectorComponent } from "./pivot-data-selector.component"; -import { - IgxGridNavigationService, - IPivotDimension, - IPivotValue, - PivotDimensionType, - PivotGridType -} from "igniteui-angular/grids/core"; +import { IgxGridNavigationService, IPivotDimension, IPivotValue, PivotDimensionType, PivotGridType } from "igniteui-angular/grids/core"; import { setElementSize } from '../../../test-utils/helper-utils.spec'; import { ɵSize, SortingDirection } from 'igniteui-angular/core'; import { IgxCheckboxComponent } from 'igniteui-angular/checkbox'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe("Pivot data selector", () => { @@ -68,55 +63,55 @@ describe("Pivot data selector integration", () => { })); it("should set its size based on the passed grid instance size", () => { - setElementSize(grid.nativeElement, ɵSize.Small) + setElementSize(grid.nativeElement, ɵSize.Small); fixture.detectChanges(); expect((selector as any).size).toEqual(ɵSize.Small); }); it("should set through API expand states for panels with two way data binding", () => { - spyOn(selector.filtersExpandedChange, "emit"); - spyOn(selector.columnsExpandedChange, "emit"); - spyOn(selector.rowsExpandedChange, "emit"); - spyOn(selector.valuesExpandedChange, "emit"); + vi.spyOn(selector.filtersExpandedChange, "emit"); + vi.spyOn(selector.columnsExpandedChange, "emit"); + vi.spyOn(selector.rowsExpandedChange, "emit"); + vi.spyOn(selector.valuesExpandedChange, "emit"); const expansionPanels = fixture.debugElement.queryAll(By.directive(IgxExpansionPanelComponent)); expect(expansionPanels.length).toEqual(4); - expect(expansionPanels[0].componentInstance.collapsed).toBeFalse(); - expect(expansionPanels[1].componentInstance.collapsed).toBeFalse(); - expect(expansionPanels[2].componentInstance.collapsed).toBeFalse(); - expect(expansionPanels[3].componentInstance.collapsed).toBeFalse(); + expect(expansionPanels[0].componentInstance.collapsed).toBe(false); + expect(expansionPanels[1].componentInstance.collapsed).toBe(false); + expect(expansionPanels[2].componentInstance.collapsed).toBe(false); + expect(expansionPanels[3].componentInstance.collapsed).toBe(false); fixture.componentInstance.filterExpandState = false; fixture.detectChanges(); expect(expansionPanels[0].componentInstance.collapsed).toBeTruthy(); - expect(expansionPanels[1].componentInstance.collapsed).toBeFalse(); - expect(expansionPanels[2].componentInstance.collapsed).toBeFalse(); - expect(expansionPanels[3].componentInstance.collapsed).toBeFalse(); + expect(expansionPanels[1].componentInstance.collapsed).toBe(false); + expect(expansionPanels[2].componentInstance.collapsed).toBe(false); + expect(expansionPanels[3].componentInstance.collapsed).toBe(false); fixture.componentInstance.columnExpandState = false; fixture.detectChanges(); - expect(expansionPanels[0].componentInstance.collapsed).toBeTrue(); - expect(expansionPanels[1].componentInstance.collapsed).toBeTrue(); - expect(expansionPanels[2].componentInstance.collapsed).toBeFalse(); - expect(expansionPanels[3].componentInstance.collapsed).toBeFalse(); + expect(expansionPanels[0].componentInstance.collapsed).toBe(true); + expect(expansionPanels[1].componentInstance.collapsed).toBe(true); + expect(expansionPanels[2].componentInstance.collapsed).toBe(false); + expect(expansionPanels[3].componentInstance.collapsed).toBe(false); fixture.componentInstance.rowExpandState = false; fixture.detectChanges(); - expect(expansionPanels[0].componentInstance.collapsed).toBeTrue(); - expect(expansionPanels[1].componentInstance.collapsed).toBeTrue(); - expect(expansionPanels[2].componentInstance.collapsed).toBeTrue(); - expect(expansionPanels[3].componentInstance.collapsed).toBeFalse(); + expect(expansionPanels[0].componentInstance.collapsed).toBe(true); + expect(expansionPanels[1].componentInstance.collapsed).toBe(true); + expect(expansionPanels[2].componentInstance.collapsed).toBe(true); + expect(expansionPanels[3].componentInstance.collapsed).toBe(false); fixture.componentInstance.valueExpandState = false; fixture.detectChanges(); - expect(expansionPanels[0].componentInstance.collapsed).toBeTrue(); - expect(expansionPanels[1].componentInstance.collapsed).toBeTrue(); - expect(expansionPanels[2].componentInstance.collapsed).toBeTrue(); - expect(expansionPanels[3].componentInstance.collapsed).toBeTrue(); + expect(expansionPanels[0].componentInstance.collapsed).toBe(true); + expect(expansionPanels[1].componentInstance.collapsed).toBe(true); + expect(expansionPanels[2].componentInstance.collapsed).toBe(true); + expect(expansionPanels[3].componentInstance.collapsed).toBe(true); expect(selector.filtersExpandedChange.emit).not.toHaveBeenCalled(); expect(selector.columnsExpandedChange.emit).not.toHaveBeenCalled(); @@ -124,72 +119,62 @@ describe("Pivot data selector integration", () => { expect(selector.valuesExpandedChange.emit).not.toHaveBeenCalled(); }); - it("should reflect expansion of panels through two way data binding", async() => { + it("should reflect expansion of panels through two way data binding", async () => { const expansionPanels = fixture.debugElement.queryAll(By.directive(IgxExpansionPanelComponent)); const panelHeaders = fixture.debugElement.queryAll(By.directive(IgxExpansionPanelHeaderComponent)); expect(expansionPanels.length).toEqual(4); - expect(fixture.componentInstance.filterExpandState).toBeTrue(); - expect(fixture.componentInstance.columnExpandState).toBeTrue(); - expect(fixture.componentInstance.rowExpandState).toBeTrue(); - expect(fixture.componentInstance.valueExpandState).toBeTrue(); - expect(expansionPanels[0].componentInstance.collapsed).toBeFalse(); - expect(expansionPanels[1].componentInstance.collapsed).toBeFalse(); - expect(expansionPanels[2].componentInstance.collapsed).toBeFalse(); - expect(expansionPanels[3].componentInstance.collapsed).toBeFalse(); + expect(fixture.componentInstance.filterExpandState).toBe(true); + expect(fixture.componentInstance.columnExpandState).toBe(true); + expect(fixture.componentInstance.rowExpandState).toBe(true); + expect(fixture.componentInstance.valueExpandState).toBe(true); + expect(expansionPanels[0].componentInstance.collapsed).toBe(false); + expect(expansionPanels[1].componentInstance.collapsed).toBe(false); + expect(expansionPanels[2].componentInstance.collapsed).toBe(false); + expect(expansionPanels[3].componentInstance.collapsed).toBe(false); UIInteractions.simulateClickEvent(panelHeaders[0].nativeElement); fixture.detectChanges(); await wait(100); - expect(fixture.componentInstance.filterExpandState).toBeFalse(); - expect(expansionPanels[0].componentInstance.collapsed).toBeTrue(); + expect(fixture.componentInstance.filterExpandState).toBe(false); + expect(expansionPanels[0].componentInstance.collapsed).toBe(true); UIInteractions.simulateClickEvent(panelHeaders[1].nativeElement); fixture.detectChanges(); await wait(100); - expect(fixture.componentInstance.columnExpandState).toBeFalse(); - expect(expansionPanels[1].componentInstance.collapsed).toBeTrue(); + expect(fixture.componentInstance.columnExpandState).toBe(false); + expect(expansionPanels[1].componentInstance.collapsed).toBe(true); UIInteractions.simulateClickEvent(panelHeaders[2].nativeElement); fixture.detectChanges(); await wait(100); - expect(fixture.componentInstance.rowExpandState).toBeFalse(); - expect(expansionPanels[2].componentInstance.collapsed).toBeTrue(); + expect(fixture.componentInstance.rowExpandState).toBe(false); + expect(expansionPanels[2].componentInstance.collapsed).toBe(true); UIInteractions.simulateClickEvent(panelHeaders[3].nativeElement); fixture.detectChanges(); await wait(100); - expect(fixture.componentInstance.valueExpandState).toBeFalse(); - expect(expansionPanels[3].componentInstance.collapsed).toBeTrue(); + expect(fixture.componentInstance.valueExpandState).toBe(false); + expect(expansionPanels[3].componentInstance.collapsed).toBe(true); }); it("should render a list of all row, column, filter, and value dimensions", () => { - const valueList = Array.from( - fixture.debugElement - .query(By.directive(IgxPivotDataSelectorComponent)) - .nativeElement.querySelectorAll( - ".igx-pivot-data-selector__filter > igx-list > igx-list-item" - ) as NodeList - ); + const valueList = Array.from(fixture.debugElement + .query(By.directive(IgxPivotDataSelectorComponent)) + .nativeElement.querySelectorAll(".igx-pivot-data-selector__filter > igx-list > igx-list-item") as NodeList); valueList.forEach((li, index) => { - expect(li.textContent).toEqual( - (pivotItems[index] as any).memberName || - (pivotItems[index] as any).member - ); + expect(li.textContent).toEqual((pivotItems[index] as any).memberName || + (pivotItems[index] as any).member); }); }); it("should filter the dimension list based on a search term", () => { - const term = ( - Object.values( - fixture.componentInstance.pivotConfigHierarchy - )[0][0] as IPivotDimension - ).memberName; + const term = (Object.values(fixture.componentInstance.pivotConfigHierarchy)[0][0] as IPivotDimension).memberName; const inputElement = fixture.debugElement .query(By.directive(IgxPivotDataSelectorComponent)) @@ -199,13 +184,9 @@ describe("Pivot data selector integration", () => { inputElement.dispatchEvent(new Event("input")); fixture.detectChanges(); - const valueList = Array.from( - fixture.debugElement - .query(By.directive(IgxPivotDataSelectorComponent)) - .nativeElement.querySelectorAll( - ".igx-pivot-data-selector__filter > igx-list > igx-list-item" - ) as NodeList - ); + const valueList = Array.from(fixture.debugElement + .query(By.directive(IgxPivotDataSelectorComponent)) + .nativeElement.querySelectorAll(".igx-pivot-data-selector__filter > igx-list > igx-list-item") as NodeList); valueList.forEach((li) => { expect(li.textContent).toContain(term); @@ -226,10 +207,7 @@ describe("Pivot data selector integration", () => { const checkbox = fixture.debugElement .query(By.directive(IgxPivotDataSelectorComponent)) .queryAll(By.directive(IgxCheckboxComponent)) - .find( - (el: DebugElement) => - el.componentInstance.ariaLabelledBy === dimension.memberName - ); + .find((el: DebugElement) => el.componentInstance.ariaLabelledBy === dimension.memberName); // Initial State expect(dimension.enabled).toBe(true); @@ -241,17 +219,13 @@ describe("Pivot data selector integration", () => { // After clicking on the checkbox items = getPanelItemsByDimensionType(PivotDimensionType.Column); expect(dimension.enabled).toBe(false); - expect(items.length).toEqual( - grid.pivotConfiguration.columns.length - 1 - ); + expect(items.length).toEqual(grid.pivotConfiguration.columns.length - 1); }); it("should sort column and row dimensions on item click", () => { const colDimension = grid.pivotConfiguration.columns[0]; const rowDimension = grid.pivotConfiguration.rows[0]; - const colSortEl = getPanelItemsByDimensionType( - PivotDimensionType.Column - ) + const colSortEl = getPanelItemsByDimensionType(PivotDimensionType.Column) .find((item) => item.textContent.includes(colDimension.memberName)) .parentNode.querySelector(".igx-pivot-data-selector__action-sort"); const rowSortEl = getPanelItemsByDimensionType(PivotDimensionType.Row) @@ -282,16 +256,11 @@ describe("Pivot data selector integration", () => { it("should render panel header sections for all pivot dimensions", () => { Object.values(PivotDimensionType).forEach((dt) => { - if (isNaN(Number(dt))) return; - const headerNode = getPanelHeaderByDimensionType( - dt as PivotDimensionType - ); - const headerTitle = selector._panels.find( - (panel) => panel.type === (dt as PivotDimensionType) - ).name; - const dimensionSize = grid.getDimensionsByType( - dt as PivotDimensionType - ).length; + if (isNaN(Number(dt))) + return; + const headerNode = getPanelHeaderByDimensionType(dt as PivotDimensionType); + const headerTitle = selector._panels.find((panel) => panel.type === (dt as PivotDimensionType)).name; + const dimensionSize = grid.getDimensionsByType(dt as PivotDimensionType).length; expect(headerNode.textContent).toContain(headerTitle); expect(headerNode.textContent).toContain(dimensionSize); @@ -300,9 +269,7 @@ describe("Pivot data selector integration", () => { it("should render panel header section for the values", () => { const headerNode = getPanelHeaderByDimensionType(null); - const headerTitle = selector._panels.find( - (panel) => panel.type === null - ).name; + const headerTitle = selector._panels.find((panel) => panel.type === null).name; const valuesSize = grid.pivotConfiguration.values?.length; expect(headerNode.textContent).toContain(headerTitle); @@ -311,7 +278,8 @@ describe("Pivot data selector integration", () => { it("should render a section of all dimension items in a panel", () => { Object.values(PivotDimensionType).forEach((dt) => { - if (isNaN(Number(dt))) return; + if (isNaN(Number(dt))) + return; expectConfigToMatchPanels(dt as PivotDimensionType); }); }); @@ -324,10 +292,10 @@ describe("Pivot data selector integration", () => { // Get all value items const items = getPanelItemsByDimensionType(null); - spyOn(selector, "ghostCreated"); - spyOn(selector, "onItemDragMove"); - spyOn(selector, "onItemDragEnd"); - spyOn(selector, "onItemDropped"); + vi.spyOn(selector, "ghostCreated"); + vi.spyOn(selector, "onItemDragMove"); + vi.spyOn(selector, "onItemDragEnd"); + vi.spyOn(selector, "onItemDropped"); // Get the drag handle of the last item in the panel const dragHandle = items[0].parentNode @@ -338,7 +306,7 @@ describe("Pivot data selector integration", () => { let { x: handleX, y: handleY } = dragHandle.getBoundingClientRect(); // Take into account that the window offset, since pointer events automatically add it. - handleY = handleY + window.pageYOffset + handleY = handleY + window.pageYOffset; UIInteractions.simulatePointerEvent("pointerdown", dragHandle, handleX, handleY); fixture.detectChanges(); @@ -376,7 +344,7 @@ describe("Pivot data selector integration", () => { let { x: handleX, y: handleY } = dragHandle.getBoundingClientRect(); // Take into account that the window offset, since pointer events automatically add it. - handleY = handleY + window.pageYOffset + handleY = handleY + window.pageYOffset; UIInteractions.simulatePointerEvent("pointerdown", dragHandle, handleX, handleY); fixture.detectChanges(); @@ -398,17 +366,14 @@ describe("Pivot data selector integration", () => { }); it("should call filtering menu on column and row filter click", () => { - spyOn(grid.filteringService, "toggleFilterDropdown"); + vi.spyOn(grid.filteringService, "toggleFilterDropdown"); - const columnItems = getPanelItemsByDimensionType( - PivotDimensionType.Column - ); + const columnItems = getPanelItemsByDimensionType(PivotDimensionType.Column); const rowItems = getPanelItemsByDimensionType(PivotDimensionType.Row); - const getFilteringIcon = (item: Node) => - item.parentNode - .querySelector("igx-list-item") - .querySelector(".igx-pivot-data-selector__action-filter"); + const getFilteringIcon = (item: Node) => item.parentNode + .querySelector("igx-list-item") + .querySelector(".igx-pivot-data-selector__action-filter"); const colFilterActions = columnItems.map(getFilteringIcon); const rowFilterActions = rowItems.map(getFilteringIcon); @@ -451,31 +416,19 @@ describe("Pivot data selector integration", () => { }); }; - const getPanelHeaderByDimensionType = ( - dimensionType: PivotDimensionType - ) => { - const panelIndex = selector._panels.findIndex( - (panel) => panel.type === dimensionType - ); + const getPanelHeaderByDimensionType = (dimensionType: PivotDimensionType) => { + const panelIndex = selector._panels.findIndex((panel) => panel.type === dimensionType); return fixture.debugElement .query(By.directive(IgxPivotDataSelectorComponent)) - .nativeElement.querySelectorAll("igx-expansion-panel-header")[ - panelIndex - ] as Node; + .nativeElement.querySelectorAll("igx-expansion-panel-header")[panelIndex] as Node; }; - const getPanelItemsByDimensionType = ( - dimensionType: PivotDimensionType - ) => { - const panelIndex = selector._panels.findIndex( - (panel) => panel.type === dimensionType - ); - - return Array.from( - fixture.debugElement - .query(By.directive(IgxPivotDataSelectorComponent)) - .nativeElement.querySelectorAll("igx-expansion-panel-body")[panelIndex].querySelectorAll("igx-list-item") as NodeList - ); + const getPanelItemsByDimensionType = (dimensionType: PivotDimensionType) => { + const panelIndex = selector._panels.findIndex((panel) => panel.type === dimensionType); + + return Array.from(fixture.debugElement + .query(By.directive(IgxPivotDataSelectorComponent)) + .nativeElement.querySelectorAll("igx-expansion-panel-body")[panelIndex].querySelectorAll("igx-list-item") as NodeList); }; }); diff --git a/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid-keyboard-nav.spec.ts b/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid-keyboard-nav.spec.ts index b3a85254b9b..716660acece 100644 --- a/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid-keyboard-nav.spec.ts +++ b/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid-keyboard-nav.spec.ts @@ -9,6 +9,7 @@ import { IgxPivotRowDimensionHeaderComponent } from './pivot-row-dimension-heade import { DebugElement } from '@angular/core'; import { IgxPivotHeaderRowComponent } from './pivot-header-row.component'; import { IgxGridNavigationService, PivotRowLayoutType } from 'igniteui-angular/grids/core'; +import { describe, it, expect, beforeEach } from 'vitest'; const DEBOUNCE_TIME = 250; const PIVOT_TBODY_CSS_CLASS = '.igx-grid__tbody'; @@ -16,7 +17,7 @@ const PIVOT_ROW_DIMENSION_CONTENT = 'igx-pivot-row-dimension-content'; const PIVOT_HEADER_ROW = 'igx-pivot-header-row'; const HEADER_CELL_CSS_CLASS = '.igx-grid-th'; const ACTIVE_CELL_CSS_CLASS = '.igx-grid-th--active'; -const CSS_CLASS_ROW_DIMENSION_CONTAINER = '.igx-grid__tbody-pivot-dimension' +const CSS_CLASS_ROW_DIMENSION_CONTAINER = '.igx-grid__tbody-pivot-dimension'; const CSS_CLASS_TBODY_CONTENT = '.igx-grid__tbody-content'; describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => { @@ -43,14 +44,12 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => { fixture.detectChanges(); pivotGrid = fixture.componentInstance.pivotGrid; await fixture.whenStable(); - rowDimension = fixture.debugElement.query( - By.css(CSS_CLASS_ROW_DIMENSION_CONTAINER)); + rowDimension = fixture.debugElement.query(By.css(CSS_CLASS_ROW_DIMENSION_CONTAINER)); headerRow = fixture.debugElement.query(By.directive(IgxPivotHeaderRowComponent)); })); it('should allow navigating between row headers', () => { - const allGroups = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + const allGroups = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); const firstCell = allGroups[0]; const secondCell = allGroups.filter(x => x.componentInstance.column.field === 'Country')[0]; UIInteractions.simulateClickAndSelectEvent(firstCell); @@ -86,8 +85,7 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => { }); it('should not go outside of the boundaries of the row dimensions content', () => { - const allGroups = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + const allGroups = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); const firstCell = allGroups[0]; const thirdCell = allGroups.filter(x => x.componentInstance.column.field === 'Date')[0]; UIInteractions.simulateClickAndSelectEvent(firstCell); @@ -114,8 +112,7 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => { }); it('should allow navigating from first to last row headers in a row(Home/End)', () => { - const allGroups = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + const allGroups = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); const firstCell = allGroups[0]; const thirdCell = allGroups.filter(x => x.componentInstance.column.field === 'Date')[0]; UIInteractions.simulateClickAndSelectEvent(firstCell); @@ -137,8 +134,7 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => { }); it('should allow navigating from first to last row headers(Ctrl + ArrowDown)', () => { - let allGroups = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + let allGroups = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); const thirdCell = allGroups.filter(x => x.componentInstance.column.field === 'Date')[0]; UIInteractions.simulateClickAndSelectEvent(thirdCell); fixture.detectChanges(); @@ -146,8 +142,7 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => { UIInteractions.triggerKeyDownEvtUponElem('ArrowDown', thirdCell.nativeElement, true, false, false, true); fixture.detectChanges(); - allGroups = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + allGroups = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); const lastCell = allGroups[allGroups.length - 1]; GridFunctions.verifyHeaderIsFocused(lastCell.parent); GridFunctions.verifyPivotElementActiveDescendant(rowDimension, lastCell.nativeElement.id); @@ -157,17 +152,15 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => { it('should allow navigating from any to first row headers(Ctrl + ArrowUp)', () => { // Ctrl + arrowup - let allGroups = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); - const thirdCell = allGroups.filter(x => x.componentInstance.column.field === 'ProductCategory')[2] + let allGroups = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); + const thirdCell = allGroups.filter(x => x.componentInstance.column.field === 'ProductCategory')[2]; UIInteractions.simulateClickAndSelectEvent(thirdCell); fixture.detectChanges(); UIInteractions.triggerKeyDownEvtUponElem('ArrowUp', thirdCell.nativeElement, true, false, false, true); fixture.detectChanges(); - allGroups = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + allGroups = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); const firstCell = allGroups[0]; GridFunctions.verifyHeaderIsFocused(firstCell.parent); GridFunctions.verifyPivotElementActiveDescendant(rowDimension, firstCell.nativeElement.id); @@ -180,8 +173,7 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => { UIInteractions.triggerKeyDownEvtUponElem('ArrowUp', thirdCell.nativeElement, true, false, false, false); fixture.detectChanges(); - allGroups = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + allGroups = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); const secondCell = allGroups.filter(x => x.componentInstance.column.field === 'ProductCategory')[1]; GridFunctions.verifyHeaderIsFocused(secondCell.parent); GridFunctions.verifyPivotElementActiveDescendant(rowDimension, secondCell.nativeElement.id); @@ -191,13 +183,11 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => { }); it('should allow navigating between column headers', () => { - let firstHeader = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; + let firstHeader = fixture.debugElement.queryAll(By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; UIInteractions.simulateClickAndSelectEvent(firstHeader); fixture.detectChanges(); - firstHeader = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; + firstHeader = fixture.debugElement.queryAll(By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; GridFunctions.verifyHeaderIsFocused(firstHeader.parent); // for the column headers, the active descendant is set on the header row element GridFunctions.verifyPivotElementActiveDescendant(headerRow, firstHeader.nativeElement.id); @@ -207,8 +197,7 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => { UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', pivotGrid.theadRow.nativeElement); fixture.detectChanges(); - const secondHeader = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[1]; + const secondHeader = fixture.debugElement.queryAll(By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[1]; GridFunctions.verifyHeaderIsFocused(secondHeader.parent); GridFunctions.verifyPivotElementActiveDescendant(headerRow, secondHeader.nativeElement.id); activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); @@ -216,13 +205,11 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => { }); it('should allow navigating from first to last column headers', async () => { - let firstHeader = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; + let firstHeader = fixture.debugElement.queryAll(By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; UIInteractions.simulateClickAndSelectEvent(firstHeader); fixture.detectChanges(); - firstHeader = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; + firstHeader = fixture.debugElement.queryAll(By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; GridFunctions.verifyHeaderIsFocused(firstHeader.parent); GridFunctions.verifyPivotElementActiveDescendant(headerRow, firstHeader.nativeElement.id); @@ -233,8 +220,7 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => { await wait(DEBOUNCE_TIME); fixture.detectChanges(); - const allHeaders = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`)); + const allHeaders = fixture.debugElement.queryAll(By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`)); const lastHeader = allHeaders[allHeaders.length - 1]; GridFunctions.verifyHeaderIsFocused(lastHeader.parent); GridFunctions.verifyPivotElementActiveDescendant(headerRow, lastHeader.nativeElement.id); @@ -243,18 +229,15 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => { }); it('should allow navigating in column headers when switching focus from rows to columns', () => { - const [firstCell] = fixture.debugElement.queryAll( - By.css(`${PIVOT_TBODY_CSS_CLASS} ${PIVOT_ROW_DIMENSION_CONTENT} ${HEADER_CELL_CSS_CLASS}`)); + const [firstCell] = fixture.debugElement.queryAll(By.css(`${PIVOT_TBODY_CSS_CLASS} ${PIVOT_ROW_DIMENSION_CONTENT} ${HEADER_CELL_CSS_CLASS}`)); UIInteractions.simulateClickAndSelectEvent(firstCell); fixture.detectChanges(); - let firstHeader = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; + let firstHeader = fixture.debugElement.queryAll(By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; UIInteractions.simulateClickAndSelectEvent(firstHeader); fixture.detectChanges(); - firstHeader = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; + firstHeader = fixture.debugElement.queryAll(By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; GridFunctions.verifyHeaderIsFocused(firstHeader.parent); GridFunctions.verifyPivotElementActiveDescendant(headerRow, firstHeader.nativeElement.id); let activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); @@ -262,8 +245,7 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => { UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', firstHeader.nativeElement); fixture.detectChanges(); - const secondHeader = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[1]; + const secondHeader = fixture.debugElement.queryAll(By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[1]; GridFunctions.verifyHeaderIsFocused(secondHeader.parent); GridFunctions.verifyPivotElementActiveDescendant(headerRow, secondHeader.nativeElement.id); activeCells = fixture.debugElement.queryAll(By.css(`${ACTIVE_CELL_CSS_CLASS}`)); @@ -278,13 +260,11 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => { }; fixture.detectChanges(); - let firstHeader = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; + let firstHeader = fixture.debugElement.queryAll(By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; UIInteractions.simulateClickAndSelectEvent(firstHeader); fixture.detectChanges(); - firstHeader = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; + firstHeader = fixture.debugElement.queryAll(By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[0]; GridFunctions.verifyHeaderIsFocused(firstHeader.parent); // for the row dimensions column headers in horizontal layout, // the active descendant is set on the header row element. @@ -296,8 +276,7 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => { UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', pivotGrid.theadRow.nativeElement); fixture.detectChanges(); - const secondHeader = fixture.debugElement.queryAll( - By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[1]; + const secondHeader = fixture.debugElement.queryAll(By.css(`${PIVOT_HEADER_ROW} ${HEADER_CELL_CSS_CLASS}`))[1]; GridFunctions.verifyHeaderIsFocused(secondHeader.parent); GridFunctions.verifyPivotElementActiveDescendant(headerRow, secondHeader.nativeElement.id); expect(firstHeader.nativeElement.getAttribute('role')).toBe('columnheader'); @@ -335,7 +314,7 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => { activeCells = fixture.debugElement.queryAll(By.css(`.igx-grid__td--active`)); expect(activeCells.length).toBe(1); - expect(activeCells[0].componentInstance.column.field).toEqual('Stanley-UnitPrice') + expect(activeCells[0].componentInstance.column.field).toEqual('Stanley-UnitPrice'); GridFunctions.verifyPivotElementActiveDescendant(tBodyContent, activeCells[0].nativeElement.id); }); }); @@ -360,48 +339,42 @@ describe('IgxPivotGrid - Keyboard navigation #pivotGrid', () => { })); it('should allow row dimension expand(Alt + ArrowDown/ArrowRight) and collapse(Alt + ArrowUp/ArrowLeft)', async () => { - const rowDimension = fixture.debugElement.queryAll( - By.css(CSS_CLASS_ROW_DIMENSION_CONTAINER)); - let allHeaders = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + const rowDimension = fixture.debugElement.queryAll(By.css(CSS_CLASS_ROW_DIMENSION_CONTAINER)); + let allHeaders = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); - expect(allHeaders.length).toBe(5, 'There should initially be 5 row dimension headers'); + expect(allHeaders.length, 'There should initially be 5 row dimension headers').toBe(5); UIInteractions.simulateClickAndSelectEvent(allHeaders[0]); UIInteractions.triggerEventHandlerKeyDown('ArrowUp', rowDimension[0], true); fixture.detectChanges(); - allHeaders = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + allHeaders = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); - expect(allHeaders.length).toBe(1, 'There should be only 1 row dimension header after collapse with Alt + ArrowUp'); + expect(allHeaders.length, 'There should be only 1 row dimension header after collapse with Alt + ArrowUp').toBe(1); UIInteractions.simulateClickAndSelectEvent(allHeaders[0]); UIInteractions.triggerEventHandlerKeyDown('ArrowDown', rowDimension[0], true); fixture.detectChanges(); - allHeaders = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + allHeaders = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); - expect(allHeaders.length).toBe(5, 'There should be 5 row dimension headers after expand with Alt + ArrowDown'); + expect(allHeaders.length, 'There should be 5 row dimension headers after expand with Alt + ArrowDown').toBe(5); UIInteractions.simulateClickAndSelectEvent(allHeaders[0]); UIInteractions.triggerEventHandlerKeyDown('ArrowLeft', rowDimension[0], true); fixture.detectChanges(); - allHeaders = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + allHeaders = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); - expect(allHeaders.length).toBe(1, 'There should be 1 row dimension header after collapse with Alt + ArrowLeft'); + expect(allHeaders.length, 'There should be 1 row dimension header after collapse with Alt + ArrowLeft').toBe(1); UIInteractions.simulateClickAndSelectEvent(allHeaders[0]); UIInteractions.triggerEventHandlerKeyDown('ArrowRight', rowDimension[0], true); fixture.detectChanges(); - allHeaders = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + allHeaders = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); - expect(allHeaders.length).toBe(5, 'There should be 5 row dimension headers after expand with Alt + ArrowRight'); + expect(allHeaders.length, 'There should be 5 row dimension headers after expand with Alt + ArrowRight').toBe(5); }); }); }); diff --git a/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.pipes.spec.ts b/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.pipes.spec.ts index 31fda83a400..10a396339c2 100644 --- a/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.pipes.spec.ts +++ b/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.pipes.spec.ts @@ -4,6 +4,7 @@ import { PivotGridFunctions } from '../../../test-utils/pivot-grid-functions.spe import { DATA } from 'src/app/shared/pivot-data'; import { DefaultDataCloneStrategy, IDataCloneStrategy } from 'igniteui-angular/core'; import { TestBed } from '@angular/core/testing'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Pivot pipes #pivotGrid', () => { let rowPipe: IgxPivotRowPipe; @@ -31,27 +32,28 @@ describe('Pivot pipes #pivotGrid', () => { { ProductCategory: 'Clothing', UnitPrice: 16.05, SellerName: 'Walter', Country: 'Bulgaria', Date: '02/19/2020', UnitsSold: 492 - }]; + } + ]; pivotConfig = { columns: [{ - memberName: 'All', - memberFunction: () => 'All', - enabled: true, - childLevel: { - memberName: 'Country', - enabled: true - } - }], + memberName: 'All', + memberFunction: () => 'All', + enabled: true, + childLevel: { + memberName: 'Country', + enabled: true + } + }], rows: [{ - memberName: 'AllCategory', - memberFunction: () => 'All', - enabled: true, - childLevel: { - memberName: 'ProductCategory', - memberFunction: (d) => d.ProductCategory, - enabled: true - } - }], + memberName: 'AllCategory', + memberFunction: () => 'All', + enabled: true, + childLevel: { + memberName: 'ProductCategory', + memberFunction: (d) => d.ProductCategory, + enabled: true + } + }], values: [ { member: 'UnitsSold', @@ -91,7 +93,8 @@ describe('Pivot pipes #pivotGrid', () => { { 'ProductCategory': 'Clothing' }, { 'ProductCategory': 'Bikes' }, { 'ProductCategory': 'Accessories' }, - { 'ProductCategory': 'Components' }]); + { 'ProductCategory': 'Components' } + ]); const aggregations = PivotGridFunctions.getAggregationValues(rowStatePipeResult); expect(aggregations).toEqual([ @@ -99,14 +102,15 @@ describe('Pivot pipes #pivotGrid', () => { { 'All-Bulgaria': 774, 'All-USA': 296, 'All-Uruguay': 456, 'All': 1526 }, { 'All-Uruguay': 68, 'All': 68 }, { 'All-USA': 293, 'All': 293 }, - { 'All-USA': 240, 'All': 240 }]); + { 'All-USA': 240, 'All': 240 } + ]); }); it('transforms flat data to pivot data single row dimension and no children are defined', () => { pivotConfig.rows = [{ - memberName: 'ProductCategory', - enabled: true - }]; + memberName: 'ProductCategory', + enabled: true + }]; const rowPipeResult = rowPipe.transform(data, pivotConfig, cloneStrategy, expansionStates); const columnPipeResult = columnPipe.transform(rowPipeResult, pivotConfig, cloneStrategy, expansionStates); const rowStatePipeResult = rowStatePipe.transform(columnPipeResult, pivotConfig, expansionStates, true); @@ -116,7 +120,8 @@ describe('Pivot pipes #pivotGrid', () => { { 'ProductCategory': 'Clothing' }, { 'ProductCategory': 'Bikes' }, { 'ProductCategory': 'Accessories' }, - { 'ProductCategory': 'Components' }]); + { 'ProductCategory': 'Components' } + ]); }); it('allows setting expand/collapse state.', () => { @@ -138,7 +143,8 @@ describe('Pivot pipes #pivotGrid', () => { { 'ProductCategory': 'Clothing' }, { 'ProductCategory': 'Bikes' }, { 'ProductCategory': 'Accessories' }, - { 'ProductCategory': 'Components' }]); + { 'ProductCategory': 'Components' } + ]); }); it('transforms flat data to pivot data multiple row dimensions', () => { @@ -156,38 +162,36 @@ describe('Pivot pipes #pivotGrid', () => { const columnPipeResult = columnPipe.transform(rowPipeResult, pivotConfig, cloneStrategy, expansionStates); const rowStatePipeResult = rowStatePipe.transform(columnPipeResult, pivotConfig, expansionStates, true); const dimensionValues = PivotGridFunctions.getDimensionValues(rowStatePipeResult); - expect(dimensionValues).toEqual( - [ - { 'ProductCategory': 'Clothing', 'Date': '01/01/2021' }, - { 'ProductCategory': 'Clothing', 'Date': '01/05/2019' }, - { 'ProductCategory': 'Clothing', 'Date': '05/12/2020' }, - { 'ProductCategory': 'Clothing', 'Date': '02/19/2020', }, - { 'ProductCategory': 'Bikes', 'Date': '01/06/2020' }, - { 'ProductCategory': 'Accessories', 'Date': '04/07/2021' }, - { 'ProductCategory': 'Components', 'Date': '12/08/2021' } - ] - ); + expect(dimensionValues).toEqual([ + { 'ProductCategory': 'Clothing', 'Date': '01/01/2021' }, + { 'ProductCategory': 'Clothing', 'Date': '01/05/2019' }, + { 'ProductCategory': 'Clothing', 'Date': '05/12/2020' }, + { 'ProductCategory': 'Clothing', 'Date': '02/19/2020', }, + { 'ProductCategory': 'Bikes', 'Date': '01/06/2020' }, + { 'ProductCategory': 'Accessories', 'Date': '04/07/2021' }, + { 'ProductCategory': 'Components', 'Date': '12/08/2021' } + ]); }); it('transforms flat data to pivot data with multiple nested row dimensions', () => { pivotConfig.rows = [{ - memberName: 'AllProd', - memberFunction: () => 'AllProd', - enabled: true, - childLevel: { - memberName: 'ProductCategory', - enabled: true - } - }, - { - memberName: 'AllDate', - memberFunction: () => 'AllDate', - enabled: true, - childLevel: { - memberName: 'Date', - enabled: true - } - }]; + memberName: 'AllProd', + memberFunction: () => 'AllProd', + enabled: true, + childLevel: { + memberName: 'ProductCategory', + enabled: true + } + }, + { + memberName: 'AllDate', + memberFunction: () => 'AllDate', + enabled: true, + childLevel: { + memberName: 'Date', + enabled: true + } + }]; const rowPipeResult = rowPipe.transform(data, pivotConfig, cloneStrategy, expansionStates); const columnPipeResult = columnPipe.transform(rowPipeResult, pivotConfig, cloneStrategy, expansionStates); const rowStatePipeResult = rowStatePipe.transform(columnPipeResult, pivotConfig, expansionStates, true); @@ -211,18 +215,19 @@ describe('Pivot pipes #pivotGrid', () => { { 'ProductCategory': 'Accessories', 'AllDate': 'AllDate' }, { 'ProductCategory': 'Accessories', 'Date': '04/07/2021' }, { 'ProductCategory': 'Components', 'AllDate': 'AllDate' }, - { 'ProductCategory': 'Components', 'Date': '12/08/2021' }]); + { 'ProductCategory': 'Components', 'Date': '12/08/2021' } + ]); }); it('transforms flat data to pivot data 2 column dimensions', () => { pivotConfig.columns = [{ - memberName: 'Country', - enabled: true - }, - { - memberName: 'Date', - enabled: true - }]; + memberName: 'Country', + enabled: true + }, + { + memberName: 'Date', + enabled: true + }]; const rowPipeResult = rowPipe.transform(data, pivotConfig, cloneStrategy, new Map()); const columnPipeResult = columnPipe.transform(rowPipeResult, pivotConfig, cloneStrategy, new Map()); const rowStatePipeResult = rowStatePipe.transform(columnPipeResult, pivotConfig, new Map(), true); @@ -232,7 +237,8 @@ describe('Pivot pipes #pivotGrid', () => { { 'ProductCategory': 'Clothing' }, { 'ProductCategory': 'Bikes' }, { 'ProductCategory': 'Accessories' }, - { 'ProductCategory': 'Components' }]); + { 'ProductCategory': 'Components' } + ]); // for columns we need to check aggregations const aggregations = PivotGridFunctions.getAggregationValues(rowStatePipeResult); expect(aggregations).toEqual([ @@ -246,17 +252,17 @@ describe('Pivot pipes #pivotGrid', () => { it('transforms flat data to pivot data 3 column dimensions', () => { pivotConfig.columns = [{ - memberName: 'Country', - enabled: true - }, - { - memberName: 'SellerName', - enabled: true - }, - { - memberName: 'Date', - enabled: true - }]; + memberName: 'Country', + enabled: true + }, + { + memberName: 'SellerName', + enabled: true + }, + { + memberName: 'Date', + enabled: true + }]; const rowPipeResult = rowPipe.transform(data, pivotConfig, cloneStrategy, new Map()); const columnPipeResult = columnPipe.transform(rowPipeResult, pivotConfig, cloneStrategy, new Map()); const rowStateResult = rowStatePipe.transform(columnPipeResult, pivotConfig, new Map(), true); @@ -266,7 +272,8 @@ describe('Pivot pipes #pivotGrid', () => { { 'Bulgaria-Stanley-01/01/2021': 282, 'Bulgaria-Stanley': 282, 'Bulgaria-Walter-02/19/2020': 492, 'Bulgaria-Walter': 492, 'Bulgaria': 774, 'USA-Elisa-01/05/2019': 296, 'USA-Elisa': 296, 'USA': 296, 'Uruguay-Larry-05/12/2020': 456, 'Uruguay-Larry': 456, 'Uruguay': 456 }, { 'Uruguay-Lydia-01/06/2020': 68, 'Uruguay-Lydia': 68, 'Uruguay': 68 }, { 'USA-David-04/07/2021': 293, 'USA-David': 293, 'USA': 293 }, - { 'USA-John-12/08/2021': 240, 'USA-John': 240, 'USA': 240 }]); + { 'USA-John-12/08/2021': 240, 'USA-John': 240, 'USA': 240 } + ]); }); it('transforms flat data to pivot data 2 value dimensions', () => { @@ -299,7 +306,8 @@ describe('Pivot pipes #pivotGrid', () => { { 'All-Bulgaria-UnitsSold': 774, 'All-Bulgaria-UnitPrice': 28.86, 'All-USA-UnitsSold': 829, 'All-USA-UnitPrice': 153.28, 'All-Uruguay-UnitsSold': 524, 'All-Uruguay-UnitPrice': 71.89, 'All-UnitsSold': 2127, 'All-UnitPrice': 254.02999999999997 }, { 'All-Bulgaria-UnitsSold': 774, 'All-Bulgaria-UnitPrice': 28.86, 'All-USA-UnitsSold': 296, 'All-USA-UnitPrice': 49.57, 'All-Uruguay-UnitsSold': 456, 'All-Uruguay-UnitPrice': 68.33, 'All-UnitsSold': 1526, 'All-UnitPrice': 146.76 }, { 'All-Uruguay-UnitsSold': 68, 'All-Uruguay-UnitPrice': 3.56, 'All-UnitsSold': 68, 'All-UnitPrice': 3.56 }, { 'All-USA-UnitsSold': 293, 'All-USA-UnitPrice': 85.58, 'All-UnitsSold': 293, 'All-UnitPrice': 85.58 }, - { 'All-USA-UnitsSold': 240, 'All-USA-UnitPrice': 18.13, 'All-UnitsSold': 240, 'All-UnitPrice': 18.13 }]); + { 'All-USA-UnitsSold': 240, 'All-USA-UnitPrice': 18.13, 'All-UnitsSold': 240, 'All-UnitPrice': 18.13 } + ]); }); it('should return correct values for each pivot aggregation type', () => { @@ -339,9 +347,11 @@ describe('Pivot pipes #pivotGrid', () => { { ProductCategory: 'Clothing', All: 1526, 'All-Bulgaria': 774, 'All-USA': 296, 'All-Uruguay': 456 }, { ProductCategory: 'Bikes', All: 68, 'All-Uruguay': 68 }, { ProductCategory: 'Accessories', All: 293, 'All-USA': 293 }, - { ProductCategory: 'Components', All: 240, 'All-USA': 240 }] - , 'All-Bulgaria': 774, 'All-USA': 829, 'All-Uruguay': 524 - }]; + { ProductCategory: 'Components', All: 240, 'All-USA': 240 } + ], + 'All-Bulgaria': 774, 'All-USA': 829, 'All-Uruguay': 524 + } + ]; pivotConfig.columnStrategy = NoopPivotDimensionsStrategy.instance(); pivotConfig.columns[0].memberName = 'All'; pivotConfig.rowStrategy = NoopPivotDimensionsStrategy.instance(); @@ -359,7 +369,8 @@ describe('Pivot pipes #pivotGrid', () => { { 'ProductCategory': 'Clothing' }, { 'ProductCategory': 'Bikes' }, { 'ProductCategory': 'Accessories' }, - { 'ProductCategory': 'Components' }]); + { 'ProductCategory': 'Components' } + ]); }); it('should generate correct levels when using predefined date dimension', () => { @@ -391,37 +402,34 @@ describe('Pivot pipes #pivotGrid', () => { { ProductCategory: 'Clothing', UnitPrice: 16.05, SellerName: 'Walter', Country: 'Bulgaria', City: 'Plovdiv', Date: '02/19/2020', UnitsSold: 492 - }]; + } + ]; pivotConfig.rows = [ - new IgxPivotDateDimension( - { - memberName: 'Date', - enabled: true - }, - { - months: false - } - ) + new IgxPivotDateDimension({ + memberName: 'Date', + enabled: true + }, { + months: false + }) ]; const rowPipeResult = rowPipe.transform(data, pivotConfig, cloneStrategy, expansionStates); const rowStateResult = rowStatePipe.transform(rowPipeResult, pivotConfig, new Map(), true); const dimensionValues = PivotGridFunctions.getDimensionValues(rowStateResult); - expect(dimensionValues).toEqual( - [ - { 'AllPeriods': 'All Periods' }, - { 'Years': '2021' }, - { 'Date': '01/01/2021' }, - { 'Date': '04/07/2021' }, - { 'Date': '12/08/2021' }, - { 'Years': '2019' }, - { 'Date': '01/05/2019' }, - { 'Years': '2020' }, - { 'Date': '01/06/2020' }, - { 'Date': '05/12/2020' }, - { 'Date': '02/19/2020' }] - ); + expect(dimensionValues).toEqual([ + { 'AllPeriods': 'All Periods' }, + { 'Years': '2021' }, + { 'Date': '01/01/2021' }, + { 'Date': '04/07/2021' }, + { 'Date': '12/08/2021' }, + { 'Years': '2019' }, + { 'Date': '01/05/2019' }, + { 'Years': '2020' }, + { 'Date': '01/06/2020' }, + { 'Date': '05/12/2020' }, + { 'Date': '02/19/2020' } + ]); }); it('should generate correct levels when using predefined date dimension with other row dimensions', () => { @@ -453,17 +461,15 @@ describe('Pivot pipes #pivotGrid', () => { { ProductCategory: 'Clothing', UnitPrice: 16.05, SellerName: 'Walter', Country: 'Bulgaria', City: 'Plovdiv', Date: '02/19/2020', UnitsSold: 492 - }]; + } + ]; pivotConfig.rows = [ - new IgxPivotDateDimension( - { - memberName: 'Date', - enabled: true - }, - { - months: false - } - ), + new IgxPivotDateDimension({ + memberName: 'Date', + enabled: true + }, { + months: false + }), { memberName: 'City', enabled: true @@ -518,20 +524,18 @@ describe('Pivot pipes #pivotGrid', () => { it('should generate correct row data with 2 dimensions with varying depth.', () => { // one dimension with 4 depth and one with 1 depth pivotConfig.rows = [ - new IgxPivotDateDimension( - { - memberName: 'Date', - enabled: true - }, - { - months: true, - total: true - } - ), + new IgxPivotDateDimension({ + memberName: 'Date', + enabled: true + }, { + months: true, + total: true + }), { memberName: 'ProductCategory', enabled: true - }]; + } + ]; let rowPipeResult = rowPipe.transform(data, pivotConfig, cloneStrategy, expansionStates); let columnPipeResult = columnPipe.transform(rowPipeResult, pivotConfig, cloneStrategy, new Map()); @@ -540,50 +544,45 @@ describe('Pivot pipes #pivotGrid', () => { const date_product = PivotGridFunctions.getDimensionValues(rowStatePipeResult); - expect(date_product).toEqual( - [ - { AllPeriods: 'All Periods', ProductCategory: 'Clothing' }, - { AllPeriods: 'All Periods', ProductCategory: 'Accessories' }, - { AllPeriods: 'All Periods', ProductCategory: 'Components' }, - { AllPeriods: 'All Periods', ProductCategory: 'Bikes' }, - { Years: '2021', ProductCategory: 'Clothing' }, - { Years: '2021', ProductCategory: 'Accessories' }, - { Years: '2021', ProductCategory: 'Components' }, - { Months: 'January', ProductCategory: 'Clothing' }, - { Date: '01/01/2021', ProductCategory: 'Clothing' }, - { Months: 'April', ProductCategory: 'Accessories' }, - { Date: '04/07/2021', ProductCategory: 'Accessories' }, - { Months: 'December', ProductCategory: 'Components' }, - { Date: '12/08/2021', ProductCategory: 'Components' }, - { Years: '2019', ProductCategory: 'Clothing' }, - { Months: 'January', ProductCategory: 'Clothing' }, - { Date: '01/05/2019', ProductCategory: 'Clothing' }, - { Years: '2020', ProductCategory: 'Bikes' }, - { Years: '2020', ProductCategory: 'Clothing' }, - { Months: 'January', ProductCategory: 'Bikes' }, - { Date: '01/06/2020', ProductCategory: 'Bikes' }, - { Months: 'May', ProductCategory: 'Clothing' }, - { Date: '05/12/2020', ProductCategory: 'Clothing' }, - { Months: 'February', ProductCategory: 'Clothing' }, - { Date: '02/19/2020', ProductCategory: 'Clothing' } - ] - ); + expect(date_product).toEqual([ + { AllPeriods: 'All Periods', ProductCategory: 'Clothing' }, + { AllPeriods: 'All Periods', ProductCategory: 'Accessories' }, + { AllPeriods: 'All Periods', ProductCategory: 'Components' }, + { AllPeriods: 'All Periods', ProductCategory: 'Bikes' }, + { Years: '2021', ProductCategory: 'Clothing' }, + { Years: '2021', ProductCategory: 'Accessories' }, + { Years: '2021', ProductCategory: 'Components' }, + { Months: 'January', ProductCategory: 'Clothing' }, + { Date: '01/01/2021', ProductCategory: 'Clothing' }, + { Months: 'April', ProductCategory: 'Accessories' }, + { Date: '04/07/2021', ProductCategory: 'Accessories' }, + { Months: 'December', ProductCategory: 'Components' }, + { Date: '12/08/2021', ProductCategory: 'Components' }, + { Years: '2019', ProductCategory: 'Clothing' }, + { Months: 'January', ProductCategory: 'Clothing' }, + { Date: '01/05/2019', ProductCategory: 'Clothing' }, + { Years: '2020', ProductCategory: 'Bikes' }, + { Years: '2020', ProductCategory: 'Clothing' }, + { Months: 'January', ProductCategory: 'Bikes' }, + { Date: '01/06/2020', ProductCategory: 'Bikes' }, + { Months: 'May', ProductCategory: 'Clothing' }, + { Date: '05/12/2020', ProductCategory: 'Clothing' }, + { Months: 'February', ProductCategory: 'Clothing' }, + { Date: '02/19/2020', ProductCategory: 'Clothing' } + ]); pivotConfig.rows = [ { memberName: 'ProductCategory', enabled: true }, - new IgxPivotDateDimension( - { - memberName: 'Date', - enabled: true - }, - { - months: true, - total: true - } - ) + new IgxPivotDateDimension({ + memberName: 'Date', + enabled: true + }, { + months: true, + total: true + }) ]; rowPipeResult = rowPipe.transform(data, pivotConfig, cloneStrategy, expansionStates); @@ -592,48 +591,43 @@ describe('Pivot pipes #pivotGrid', () => { expect(rowStatePipeResult.length).toBe(24); const product_date = PivotGridFunctions.getDimensionValues(rowStatePipeResult); - expect(product_date).toEqual( - [ - { ProductCategory: 'Clothing', AllPeriods: 'All Periods' }, - { ProductCategory: 'Clothing', Years: '2021' }, - { ProductCategory: 'Clothing', Months: 'January' }, - { ProductCategory: 'Clothing', Date: '01/01/2021' }, - { ProductCategory: 'Clothing', Years: '2019' }, - { ProductCategory: 'Clothing', Months: 'January' }, - { ProductCategory: 'Clothing', Date: '01/05/2019' }, - { ProductCategory: 'Clothing', Years: '2020' }, - { ProductCategory: 'Clothing', Months: 'May' }, - { ProductCategory: 'Clothing', Date: '05/12/2020' }, - { ProductCategory: 'Clothing', Months: 'February' }, - { ProductCategory: 'Clothing', Date: '02/19/2020' }, - { ProductCategory: 'Bikes', AllPeriods: 'All Periods' }, - { ProductCategory: 'Bikes', Years: '2020' }, - { ProductCategory: 'Bikes', Months: 'January' }, - { ProductCategory: 'Bikes', Date: '01/06/2020' }, - { ProductCategory: 'Accessories', AllPeriods: 'All Periods' }, - { ProductCategory: 'Accessories', Years: '2021' }, - { ProductCategory: 'Accessories', Months: 'April' }, - { ProductCategory: 'Accessories', Date: '04/07/2021' }, - { ProductCategory: 'Components', AllPeriods: 'All Periods' }, - { ProductCategory: 'Components', Years: '2021' }, - { ProductCategory: 'Components', Months: 'December' }, - { ProductCategory: 'Components', Date: '12/08/2021' } - ] - ); + expect(product_date).toEqual([ + { ProductCategory: 'Clothing', AllPeriods: 'All Periods' }, + { ProductCategory: 'Clothing', Years: '2021' }, + { ProductCategory: 'Clothing', Months: 'January' }, + { ProductCategory: 'Clothing', Date: '01/01/2021' }, + { ProductCategory: 'Clothing', Years: '2019' }, + { ProductCategory: 'Clothing', Months: 'January' }, + { ProductCategory: 'Clothing', Date: '01/05/2019' }, + { ProductCategory: 'Clothing', Years: '2020' }, + { ProductCategory: 'Clothing', Months: 'May' }, + { ProductCategory: 'Clothing', Date: '05/12/2020' }, + { ProductCategory: 'Clothing', Months: 'February' }, + { ProductCategory: 'Clothing', Date: '02/19/2020' }, + { ProductCategory: 'Bikes', AllPeriods: 'All Periods' }, + { ProductCategory: 'Bikes', Years: '2020' }, + { ProductCategory: 'Bikes', Months: 'January' }, + { ProductCategory: 'Bikes', Date: '01/06/2020' }, + { ProductCategory: 'Accessories', AllPeriods: 'All Periods' }, + { ProductCategory: 'Accessories', Years: '2021' }, + { ProductCategory: 'Accessories', Months: 'April' }, + { ProductCategory: 'Accessories', Date: '04/07/2021' }, + { ProductCategory: 'Components', AllPeriods: 'All Periods' }, + { ProductCategory: 'Components', Years: '2021' }, + { ProductCategory: 'Components', Months: 'December' }, + { ProductCategory: 'Components', Date: '12/08/2021' } + ]); }); it('should generate correct row data with 3 dimensions with varying depth.', () => { // one dimension with 3 depth, one with 2 and one with 1 const dims = [ - new IgxPivotDateDimension( - { - memberName: 'Date', - enabled: true - }, - { - months: false, - total: true - } - ), + new IgxPivotDateDimension({ + memberName: 'Date', + enabled: true + }, { + months: false, + total: true + }), { memberName: 'AllProduct', memberFunction: () => 'All Products', @@ -646,7 +640,8 @@ describe('Pivot pipes #pivotGrid', () => { { memberName: 'SellerName', enabled: true - }]; + } + ]; pivotConfig.rows = [ dims[0], dims[1], @@ -770,16 +765,13 @@ describe('Pivot pipes #pivotGrid', () => { // 4 dimensions - depths 3, 2, 1, 1 const dims = [ - new IgxPivotDateDimension( - { - memberName: 'Date', - enabled: true - }, - { - months: false, - total: true - } - ), + new IgxPivotDateDimension({ + memberName: 'Date', + enabled: true + }, { + months: false, + total: true + }), { memberName: 'AllProduct', memberFunction: () => 'All Products', @@ -796,7 +788,8 @@ describe('Pivot pipes #pivotGrid', () => { { memberName: 'SellerName', enabled: true - }]; + } + ]; // Date, Product, Country, Seller pivotConfig.rows = [ dims[0], @@ -944,19 +937,17 @@ describe('Pivot pipes #pivotGrid', () => { { ProductCategory: 'Clothing', UnitPrice: 16.05, SellerName: 'Walter', Country: 'Bulgaria', Date: '02/19/2020', UnitsSold: 492, Discontinued: false - }]; + } + ]; // 5 dimensions - depths 3, 2, 2, 1, 1 const dims = [ - new IgxPivotDateDimension( - { - memberName: 'Date', - enabled: true - }, - { - months: false, - total: true - } - ), + new IgxPivotDateDimension({ + memberName: 'Date', + enabled: true + }, { + months: false, + total: true + }), { memberName: 'AllProduct', memberFunction: () => 'All Products', @@ -984,7 +975,8 @@ describe('Pivot pipes #pivotGrid', () => { memberFunction: (rowData) => { return rowData.Discontinued.toString(); } - }]; + } + ]; // Date, Product, Country, Seller, Discontinued pivotConfig.rows = [ dims[0], // Date @@ -1001,24 +993,22 @@ describe('Pivot pipes #pivotGrid', () => { const prod_country_date_seller_discontinued = PivotGridFunctions.getDimensionValues(rowStatePipeResult); const allPeriods_allProducts_records = prod_country_date_seller_discontinued.filter(x => x['AllPeriods'] === 'All Periods' && x['AllProduct'] === 'All Products'); - expect(allPeriods_allProducts_records).toEqual( - [ - { AllPeriods: 'All Periods', AllProduct: 'All Products', AllCountries: 'All Countries', SellerName: 'Stanley', Discontinued: 'false' }, - { AllPeriods: 'All Periods', AllProduct: 'All Products', AllCountries: 'All Countries', SellerName: 'Walter', Discontinued: 'false' }, - { AllPeriods: 'All Periods', AllProduct: 'All Products', AllCountries: 'All Countries', SellerName: 'Elisa', Discontinued: 'true' }, - { AllPeriods: 'All Periods', AllProduct: 'All Products', AllCountries: 'All Countries', SellerName: 'David', Discontinued: 'false' }, - { AllPeriods: 'All Periods', AllProduct: 'All Products', AllCountries: 'All Countries', SellerName: 'John', Discontinued: 'false' }, - { AllPeriods: 'All Periods', AllProduct: 'All Products', AllCountries: 'All Countries', SellerName: 'Larry', Discontinued: 'true' }, - { AllPeriods: 'All Periods', AllProduct: 'All Products', AllCountries: 'All Countries', SellerName: 'Lydia', Discontinued: 'true' }, - { AllPeriods: 'All Periods', AllProduct: 'All Products', Country: 'Bulgaria', SellerName: 'Stanley', Discontinued: 'false' }, - { AllPeriods: 'All Periods', AllProduct: 'All Products', Country: 'Bulgaria', SellerName: 'Walter', Discontinued: 'false' }, - { AllPeriods: 'All Periods', AllProduct: 'All Products', Country: 'USA', SellerName: 'Elisa', Discontinued: 'true' }, - { AllPeriods: 'All Periods', AllProduct: 'All Products', Country: 'USA', SellerName: 'David', Discontinued: 'false' }, - { AllPeriods: 'All Periods', AllProduct: 'All Products', Country: 'USA', SellerName: 'John', Discontinued: 'false' }, - { AllPeriods: 'All Periods', AllProduct: 'All Products', Country: 'Uruguay', SellerName: 'Larry', Discontinued: 'true' }, - { AllPeriods: 'All Periods', AllProduct: 'All Products', Country: 'Uruguay', SellerName: 'Lydia', Discontinued: 'true' } - ] - ); + expect(allPeriods_allProducts_records).toEqual([ + { AllPeriods: 'All Periods', AllProduct: 'All Products', AllCountries: 'All Countries', SellerName: 'Stanley', Discontinued: 'false' }, + { AllPeriods: 'All Periods', AllProduct: 'All Products', AllCountries: 'All Countries', SellerName: 'Walter', Discontinued: 'false' }, + { AllPeriods: 'All Periods', AllProduct: 'All Products', AllCountries: 'All Countries', SellerName: 'Elisa', Discontinued: 'true' }, + { AllPeriods: 'All Periods', AllProduct: 'All Products', AllCountries: 'All Countries', SellerName: 'David', Discontinued: 'false' }, + { AllPeriods: 'All Periods', AllProduct: 'All Products', AllCountries: 'All Countries', SellerName: 'John', Discontinued: 'false' }, + { AllPeriods: 'All Periods', AllProduct: 'All Products', AllCountries: 'All Countries', SellerName: 'Larry', Discontinued: 'true' }, + { AllPeriods: 'All Periods', AllProduct: 'All Products', AllCountries: 'All Countries', SellerName: 'Lydia', Discontinued: 'true' }, + { AllPeriods: 'All Periods', AllProduct: 'All Products', Country: 'Bulgaria', SellerName: 'Stanley', Discontinued: 'false' }, + { AllPeriods: 'All Periods', AllProduct: 'All Products', Country: 'Bulgaria', SellerName: 'Walter', Discontinued: 'false' }, + { AllPeriods: 'All Periods', AllProduct: 'All Products', Country: 'USA', SellerName: 'Elisa', Discontinued: 'true' }, + { AllPeriods: 'All Periods', AllProduct: 'All Products', Country: 'USA', SellerName: 'David', Discontinued: 'false' }, + { AllPeriods: 'All Periods', AllProduct: 'All Products', Country: 'USA', SellerName: 'John', Discontinued: 'false' }, + { AllPeriods: 'All Periods', AllProduct: 'All Products', Country: 'Uruguay', SellerName: 'Larry', Discontinued: 'true' }, + { AllPeriods: 'All Periods', AllProduct: 'All Products', Country: 'Uruguay', SellerName: 'Lydia', Discontinued: 'true' } + ]); const allPeriods_clothing_records = prod_country_date_seller_discontinued.filter(x => x['AllPeriods'] === 'All Periods' && x['ProductCategory'] === 'Clothing'); expect(allPeriods_clothing_records).toEqual([ @@ -1228,21 +1218,19 @@ describe('Pivot pipes #pivotGrid', () => { { ProductCategory: 'Clothing', UnitPrice: 16.05, SellerName: 'Walter', Country: 'Bulgaria', City: 'Plovdiv', Date: '02/19/2020', UnitsSold: 492 - }]; + } + ]; pivotConfig.columns = [{ - memberName: 'Country', - enabled: true - }]; + memberName: 'Country', + enabled: true + }]; pivotConfig.rows = [ - new IgxPivotDateDimension( - { - memberName: 'Date', - enabled: true - }, - { - months: false - } - ), + new IgxPivotDateDimension({ + memberName: 'Date', + enabled: true + }, { + months: false + }), { memberName: 'City', enabled: true @@ -1283,8 +1271,7 @@ describe('Pivot pipes #pivotGrid', () => { memberName: 'AllProduct', memberFunction: () => 'All Products', enabled: true, - childLevel: - { + childLevel: { memberName: 'Product', memberFunction: (recData) => recData.Product.Name, @@ -1295,8 +1282,7 @@ describe('Pivot pipes #pivotGrid', () => { memberName: 'AllSeller', memberFunction: () => 'All Sellers', enabled: true, - childLevel: - { + childLevel: { memberName: 'Seller', memberFunction: (recData) => recData.Seller.Name, enabled: true, @@ -1330,18 +1316,15 @@ describe('Pivot pipes #pivotGrid', () => { ]; pivotConfig.columns = []; pivotConfig.rows = [ - new IgxPivotDateDimension( - { - memberName: 'Date', - enabled: true - }, - { - months: true, - quarters: true, - fullDate: false - } - ) - ] + new IgxPivotDateDimension({ + memberName: 'Date', + enabled: true + }, { + months: true, + quarters: true, + fullDate: false + }) + ]; const rowPipeResult = rowPipe.transform(data, pivotConfig, cloneStrategy, expansionStates); const columnPipeResult = columnPipe.transform(rowPipeResult, pivotConfig, cloneStrategy, new Map()); const rowStatePipeResult = rowStatePipe.transform(columnPipeResult, pivotConfig, expansionStates, true); diff --git a/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.spec.ts b/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.spec.ts index 93ba74b5413..ca79ec065d7 100644 --- a/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.spec.ts +++ b/projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.spec.ts @@ -22,6 +22,7 @@ import { IgxPivotGridComponent } from './pivot-grid.component'; import { IgxGridCell } from 'igniteui-angular/grids/core'; import { IGridCellEventArgs } from 'igniteui-angular/grids/core'; import { getI18nManager } from 'igniteui-i18n-core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const CSS_CLASS_LIST = 'igx-drop-down__list'; const CSS_CLASS_ITEM = 'igx-drop-down__item'; @@ -165,7 +166,7 @@ describe('IgxPivotGrid #pivotGrid', () => { const removeIcon = rowChip.querySelectorAll('igx-icon')[2]; removeIcon.click(); fixture.detectChanges(); - expect(pivotGrid.pivotConfiguration.rows[1].enabled).toBeFalse(); + expect(pivotGrid.pivotConfiguration.rows[1].enabled).toBe(false); expect(pivotGrid.rowDimensions.length).toBe(1); pivotRecord = (pivotGrid.rowList.first as IgxPivotRowComponent).data; expect(pivotRecord.dimensionValues.get('SellerName')).toBeUndefined(); @@ -189,7 +190,7 @@ describe('IgxPivotGrid #pivotGrid', () => { const removeIcon = rowChip.querySelectorAll('igx-icon')[2]; removeIcon.click(); fixture.detectChanges(); - expect(pivotGrid.pivotConfiguration.columns[1].enabled).toBeFalse(); + expect(pivotGrid.pivotConfiguration.columns[1].enabled).toBe(false); expect(pivotGrid.columnDimensions.length).toBe(1); expect(pivotGrid.columns.length).toBe(9); }); @@ -208,7 +209,7 @@ describe('IgxPivotGrid #pivotGrid', () => { let removeIcon = rowChip.querySelectorAll('igx-icon')[2]; removeIcon.click(); fixture.detectChanges(); - expect(pivotGrid.pivotConfiguration.values[0].enabled).toBeFalse(); + expect(pivotGrid.pivotConfiguration.values[0].enabled).toBe(false); expect(pivotGrid.values.length).toBe(1); expect(pivotGrid.columns.length).not.toBe(9); @@ -217,7 +218,7 @@ describe('IgxPivotGrid #pivotGrid', () => { removeIcon = rowChip.querySelectorAll('igx-icon')[2]; removeIcon.click(); fixture.detectChanges(); - expect(pivotGrid.pivotConfiguration.values[1].enabled).toBeFalse(); + expect(pivotGrid.pivotConfiguration.values[1].enabled).toBe(false); expect(pivotGrid.values.length).toBe(0); expect(pivotGrid.columns.length).toBe(3); }); @@ -242,7 +243,7 @@ describe('IgxPivotGrid #pivotGrid', () => { pivotGrid.pivotConfiguration.filters = [filterDimension]; pivotGrid.pipeTrigger++; fixture.detectChanges(); - expect(pivotGrid.pivotConfiguration.filters[0].enabled).toBeTrue(); + expect(pivotGrid.pivotConfiguration.filters[0].enabled).toBe(true); expect(pivotGrid.rowList.length).toBe(2); const headerRow = fixture.nativeElement.querySelector('igx-pivot-header-row'); @@ -250,7 +251,7 @@ describe('IgxPivotGrid #pivotGrid', () => { const removeIcon = rowChip.querySelectorAll('igx-icon')[1]; removeIcon.click(); fixture.detectChanges(); - expect(pivotGrid.pivotConfiguration.filters[0].enabled).toBeFalse(); + expect(pivotGrid.pivotConfiguration.filters[0].enabled).toBe(false); expect(pivotGrid.rowList.length).toBe(5); }); @@ -306,23 +307,20 @@ describe('IgxPivotGrid #pivotGrid', () => { const pivotGrid = fixture.componentInstance.pivotGrid; pivotGrid.pivotConfiguration.values.pop(); pivotGrid.pivotConfiguration.columns = [{ - memberName: 'AllCountries', - memberFunction: () => 'All Countries', - enabled: true, - childLevel: { - memberName: 'Country', - enabled: true - } - }]; - pivotGrid.pivotConfiguration.rows[0] = new IgxPivotDateDimension( - { - memberName: 'Date', - enabled: true - }, - { - total: false - } - ); + memberName: 'AllCountries', + memberFunction: () => 'All Countries', + enabled: true, + childLevel: { + memberName: 'Country', + enabled: true + } + }]; + pivotGrid.pivotConfiguration.rows[0] = new IgxPivotDateDimension({ + memberName: 'Date', + enabled: true + }, { + total: false + }); pivotGrid.notifyDimensionChange(true); expect(pivotGrid.columns.length).toBe(5); expect(pivotGrid.columnGroupStates.size).toBe(0); @@ -334,24 +332,24 @@ describe('IgxPivotGrid #pivotGrid', () => { expect(pivotGrid.columnGroupStates.size).toBe(1); const value = pivotGrid.columnGroupStates.entries().next().value; expect(value[0]).toEqual('All Countries'); - expect(value[1]).toBeTrue(); + expect(value[1]).toBe(true); }); it('should collapse column with 2 value dimension', () => { const pivotGrid = fixture.componentInstance.pivotGrid; pivotGrid.pivotConfiguration.columns = [{ - memberName: 'AllCountries', - memberFunction: () => 'All Countries', - enabled: true, - childLevel: { - memberName: 'Country', + memberName: 'AllCountries', + memberFunction: () => 'All Countries', + enabled: true, + childLevel: { + memberName: 'Country', + enabled: true + } + }, + { + memberName: 'SellerName', enabled: true - } - }, - { - memberName: 'SellerName', - enabled: true - }]; + }]; pivotGrid.notifyDimensionChange(true); fixture.detectChanges(); expect(pivotGrid.columnGroupStates.size).toBe(0); @@ -363,7 +361,7 @@ describe('IgxPivotGrid #pivotGrid', () => { expect(pivotGrid.columnGroupStates.size).toBe(1); let value = pivotGrid.columnGroupStates.entries().next().value; expect(value[0]).toEqual('All Countries'); - expect(value[1]).toBeTrue(); + expect(value[1]).toBe(true); headerRow = fixture.nativeElement.querySelector('igx-pivot-header-row'); header = headerRow.querySelector('igx-grid-header-group'); @@ -372,7 +370,7 @@ describe('IgxPivotGrid #pivotGrid', () => { fixture.detectChanges(); value = pivotGrid.columnGroupStates.entries().next().value; expect(value[0]).toEqual('All Countries'); - expect(value[1]).toBeFalse(); + expect(value[1]).toBe(false); }); it('should collapse row', () => { @@ -387,21 +385,18 @@ describe('IgxPivotGrid #pivotGrid', () => { fixture.detectChanges(); expect(pivotGrid.rowList.length).toEqual(1); expect(pivotGrid.expansionStates.size).toEqual(1); - expect(pivotGrid.expansionStates.get('All')).toBeFalse(); + expect(pivotGrid.expansionStates.get('All')).toBe(false); }); it('should display aggregations when no row dimensions are enabled', () => { const pivotGrid = fixture.componentInstance.pivotGrid; pivotGrid.pivotConfiguration.columns = [ - new IgxPivotDateDimension( - { - memberName: 'Date', - enabled: true - }, - { - months: false - } - ) + new IgxPivotDateDimension({ + memberName: 'Date', + enabled: true + }, { + months: false + }) ]; pivotGrid.pivotConfiguration.rows = []; pivotGrid.notifyDimensionChange(true); @@ -441,15 +436,12 @@ describe('IgxPivotGrid #pivotGrid', () => { pivotGrid.height = '700px'; pivotGrid.width = '1000px'; pivotGrid.pivotConfiguration.columns = [ - new IgxPivotDateDimension( - { - memberName: 'Date', - enabled: true - }, - { - months: false - } - ) + new IgxPivotDateDimension({ + memberName: 'Date', + enabled: true + }, { + months: false + }) ]; pivotGrid.pivotConfiguration.rows = [ { @@ -482,15 +474,12 @@ describe('IgxPivotGrid #pivotGrid', () => { pivotGrid.height = '700px'; pivotGrid.width = '1000px'; pivotGrid.pivotConfiguration.columns = [ - new IgxPivotDateDimension( - { - memberName: 'Date', - enabled: true - }, - { - months: false - } - ) + new IgxPivotDateDimension({ + memberName: 'Date', + enabled: true + }, { + months: false + }) ]; pivotGrid.pivotConfiguration.rows = [ { @@ -541,7 +530,7 @@ describe('IgxPivotGrid #pivotGrid', () => { fixture.detectChanges(); tick(); - setElementSize(pivotGrid.nativeElement, ɵSize.Large) + setElementSize(pivotGrid.nativeElement, ɵSize.Large); fixture.detectChanges(); expect(pivotGrid.gridSize).toBe(ɵSize.Large); @@ -553,9 +542,9 @@ describe('IgxPivotGrid #pivotGrid', () => { it('should render correct auto-widths for dimensions with no width', () => { const pivotGrid = fixture.componentInstance.pivotGrid as IgxPivotGridComponent; pivotGrid.data = [{ - ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley', - Country: 'Bulgaria', Date: '01/01/2021', UnitsSold: 282 - }]; + ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley', + Country: 'Bulgaria', Date: '01/01/2021', UnitsSold: 282 + }]; fixture.detectChanges(); // there should be just 1 dimension column and 2 value columns and they should auto-fill the available space @@ -569,40 +558,40 @@ describe('IgxPivotGrid #pivotGrid', () => { // change data to have many columns so that they no longer fit in the grid pivotGrid.data = [{ - ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley', - Country: 'Bulgaria', Date: '01/01/2021', UnitsSold: 282 - }, { - ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley', - Country: 'USA', Date: '01/01/2021', UnitsSold: 282 - }, - { - ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley', - Country: 'Spain', Date: '01/01/2021', UnitsSold: 282 - }, - { - ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley', - Country: 'Italy', Date: '01/01/2021', UnitsSold: 282 - }, - { - ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley', - Country: 'Greece', Date: '01/01/2021', UnitsSold: 282 - }, - { - ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley', - Country: 'Uruguay', Date: '01/01/2021', UnitsSold: 282 - }, - { - ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley', - Country: 'Mexico', Date: '01/01/2021', UnitsSold: 282 - } + ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley', + Country: 'Bulgaria', Date: '01/01/2021', UnitsSold: 282 + }, { + ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley', + Country: 'USA', Date: '01/01/2021', UnitsSold: 282 + }, + { + ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley', + Country: 'Spain', Date: '01/01/2021', UnitsSold: 282 + }, + { + ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley', + Country: 'Italy', Date: '01/01/2021', UnitsSold: 282 + }, + { + ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley', + Country: 'Greece', Date: '01/01/2021', UnitsSold: 282 + }, + { + ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley', + Country: 'Uruguay', Date: '01/01/2021', UnitsSold: 282 + }, + { + ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley', + Country: 'Mexico', Date: '01/01/2021', UnitsSold: 282 + } ]; fixture.detectChanges(); // all should take grid size default min-width (200 for default grid size) as they exceed the size of the grid const colGroups = pivotGrid.columns.filter(x => x.columnGroup); const childCols = pivotGrid.columns.filter(x => !x.columnGroup); - expect(colGroups.every(x => x.width === '400px')).toBeTrue(); - expect(childCols.every(x => x.width === '200px')).toBeTrue(); + expect(colGroups.every(x => x.width === '400px')).toBe(true); + expect(childCols.every(x => x.width === '200px')).toBe(true); }); it('should render correct grid with noop strategies', () => { @@ -626,8 +615,7 @@ describe('IgxPivotGrid #pivotGrid', () => { memberName: 'Country', enabled: true }, - ] - , + ], rows: [ { memberFunction: () => 'All', @@ -689,7 +677,7 @@ describe('IgxPivotGrid #pivotGrid', () => { } } ] - } + }; fixture.detectChanges(); @@ -731,7 +719,7 @@ describe('IgxPivotGrid #pivotGrid', () => { } } ] - } + }; fixture.detectChanges(); @@ -808,7 +796,7 @@ describe('IgxPivotGrid #pivotGrid', () => { const pivotGrid = fixture.componentInstance.pivotGrid; const colSum = pivotGrid.featureColumnsWidth() + pivotGrid.columns.filter(x => !x.columnGroup).map(x => x.calcPixelWidth).reduce((x, y) => x + y); const expectedSize = Math.min(window.innerWidth, colSum); - expect(pivotGrid.nativeElement.clientWidth - expectedSize).toBeLessThan(50, "should take sum of columns as width."); + expect(pivotGrid.nativeElement.clientWidth - expectedSize, "should take sum of columns as width.").toBeLessThan(50); }); it('should render cell values for dimension columns containing dots - issue #16445', () => { @@ -899,8 +887,7 @@ describe('IgxPivotGrid #pivotGrid', () => { const rows = pivotGrid.rowList.toArray(); expect(rows.length).toBe(3); const expectedHeaders = ['All', 'Clothing', 'Components']; - const rowHeaders = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + const rowHeaders = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); const rowDimensionHeaders = rowHeaders.map(x => x.componentInstance.column.header); expect(rowDimensionHeaders).toEqual(expectedHeaders); }); @@ -951,9 +938,9 @@ describe('IgxPivotGrid #pivotGrid', () => { } ]; pivotGrid.pivotConfiguration.filters = [{ - memberName: 'SellerName', - enabled: true - }]; + memberName: 'SellerName', + enabled: true + }]; pivotGrid.pipeTrigger++; pivotGrid.setupColumns(); fixture.detectChanges(); @@ -1076,8 +1063,7 @@ describe('IgxPivotGrid #pivotGrid', () => { // check rows const expectedHeaders = ['All', 'Clothing', 'Components']; - const rowHeaders = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + const rowHeaders = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); const rowDimensionHeaders = rowHeaders.map(x => x.componentInstance.column.header); expect(rowHeaders.length).toBe(3); expect(rowDimensionHeaders).toEqual(expectedHeaders); @@ -1097,9 +1083,9 @@ describe('IgxPivotGrid #pivotGrid', () => { ]; pivotGrid.pivotConfiguration.rows = [{ - memberName: 'SellerName', - enabled: true - }]; + memberName: 'SellerName', + enabled: true + }]; pivotGrid.pipeTrigger++; pivotGrid.setupColumns(); fixture.detectChanges(); @@ -1116,19 +1102,16 @@ describe('IgxPivotGrid #pivotGrid', () => { (getI18nManager() as any).removeAllListeners(); const pivotGrid = fixture.componentInstance.pivotGrid; - pivotGrid.pivotConfiguration.rows = [new IgxPivotDateDimension( - { + pivotGrid.pivotConfiguration.rows = [new IgxPivotDateDimension({ memberName: 'Date', enabled: true - }, - { + }, { months: true, quarters: true, years: true, fullDate: true, total: true - } - )]; + })]; pivotGrid.pipeTrigger++; pivotGrid.setupColumns(); @@ -1232,8 +1215,7 @@ describe('IgxPivotGrid #pivotGrid', () => { const rows = pivotGrid.rowList.toArray(); expect(rows.length).toBe(5); const expectedHeaders = ['All Periods', '2021', 'Q4', 'December', '12/08/2021']; - const rowHeaders = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + const rowHeaders = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); const rowDimensionHeaders = rowHeaders.map(x => x.componentInstance.column.header); expect(rowDimensionHeaders).toEqual(expectedHeaders); }); @@ -1252,20 +1234,19 @@ describe('IgxPivotGrid #pivotGrid', () => { ]; pivotGrid.pivotConfiguration.rows = [{ - memberName: 'SellerName', - enabled: true - }]; + memberName: 'SellerName', + enabled: true + }]; pivotGrid.pipeTrigger++; pivotGrid.setupColumns(); fixture.detectChanges(); - const headerRow = fixture.debugElement.queryAll( - By.directive(IgxPivotHeaderRowComponent))[0].componentInstance; + const headerRow = fixture.debugElement.queryAll(By.directive(IgxPivotHeaderRowComponent))[0].componentInstance; const filtersChip = headerRow.nativeElement.querySelector('igx-chip[id="Date"]'); expect(filtersChip).not.toBeUndefined(); const filterIcon = filtersChip.querySelectorAll('igx-icon')[0]; - spyOn(headerRow, 'onFilteringIconPointerDown').and.callThrough(); + vi.spyOn(headerRow, 'onFilteringIconPointerDown'); filterIcon.dispatchEvent(new Event('pointerdown')); expect(headerRow.onFilteringIconPointerDown).toHaveBeenCalledTimes(1); }); @@ -1273,13 +1254,12 @@ describe('IgxPivotGrid #pivotGrid', () => { it('should apply sorting for dimension via row chip', () => { fixture.detectChanges(); const pivotGrid = fixture.componentInstance.pivotGrid; - spyOn(pivotGrid.dimensionsSortingExpressionsChange, 'emit'); + vi.spyOn(pivotGrid.dimensionsSortingExpressionsChange, 'emit'); const headerRow = fixture.nativeElement.querySelector('igx-pivot-header-row'); const rowChip = headerRow.querySelector('igx-chip[id="All"]'); rowChip.click(); fixture.detectChanges(); - let rowHeaders = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + let rowHeaders = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); let expectedOrder = ['All', 'Accessories', 'Bikes', 'Clothing', 'Components']; let rowDimensionHeaders = rowHeaders.map(x => x.componentInstance.column.header); expect(rowDimensionHeaders).toEqual(expectedOrder); @@ -1287,8 +1267,7 @@ describe('IgxPivotGrid #pivotGrid', () => { rowChip.click(); fixture.detectChanges(); expectedOrder = ['All', 'Components', 'Clothing', 'Bikes', 'Accessories']; - rowHeaders = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + rowHeaders = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); rowDimensionHeaders = rowHeaders.map(x => x.componentInstance.column.header); expect(rowDimensionHeaders).toEqual(expectedOrder); @@ -1306,7 +1285,7 @@ describe('IgxPivotGrid #pivotGrid', () => { const pivotGrid = fixture.componentInstance.pivotGrid; const headerRow = fixture.nativeElement.querySelector('igx-pivot-header-row'); const colChip = headerRow.querySelector('igx-chip[id="Country"]'); - spyOn(pivotGrid.dimensionsSortingExpressionsChange, 'emit'); + vi.spyOn(pivotGrid.dimensionsSortingExpressionsChange, 'emit'); // sort colChip.click(); fixture.detectChanges(); @@ -1334,18 +1313,18 @@ describe('IgxPivotGrid #pivotGrid', () => { it('should apply sorting for dimension via column chip when dimension has memberFunction', () => { const pivotGrid = fixture.componentInstance.pivotGrid; pivotGrid.pivotConfiguration.columns = [{ - memberName: 'Country', - memberFunction: (data) => { - return data['Country']; - }, - enabled: true - }]; + memberName: 'Country', + memberFunction: (data) => { + return data['Country']; + }, + enabled: true + }]; pivotGrid.notifyDimensionChange(true); fixture.detectChanges(); const headerRow = fixture.nativeElement.querySelector('igx-pivot-header-row'); const colChip = headerRow.querySelector('igx-chip[id="Country"]'); - spyOn(pivotGrid.dimensionsSortingExpressionsChange, 'emit'); + vi.spyOn(pivotGrid.dimensionsSortingExpressionsChange, 'emit'); // sort colChip.click(); fixture.detectChanges(); @@ -1374,23 +1353,20 @@ describe('IgxPivotGrid #pivotGrid', () => { const pivotGrid = fixture.componentInstance.pivotGrid; pivotGrid.pivotConfiguration.columns = [ - new IgxPivotDateDimension( - { - memberName: 'Date', - memberFunction: (data) => { - return data['Date']; - }, - enabled: true, - dataType: GridColumnDataType.Date + new IgxPivotDateDimension({ + memberName: 'Date', + memberFunction: (data) => { + return data['Date']; }, - { - total: false, - years: false, - quarters: false, - months: false, - fullDate: true - } - ) + enabled: true, + dataType: GridColumnDataType.Date + }, { + total: false, + years: false, + quarters: false, + months: false, + fullDate: true + }) ]; pivotGrid.notifyDimensionChange(true); fixture.detectChanges(); @@ -1403,7 +1379,7 @@ describe('IgxPivotGrid #pivotGrid', () => { fixture.detectChanges(); let colHeaders = pivotGrid.columns.filter(x => x.level === 0).map(x => x.header); - let expected = ['01/05/2019', '01/06/2020', '02/19/2020', '05/12/2020', '01/01/2021', '04/07/2021', '12/08/2021'] + let expected = ['01/05/2019', '01/06/2020', '02/19/2020', '05/12/2020', '01/01/2021', '04/07/2021', '12/08/2021']; expect(colHeaders).toEqual(expected); // sort desc @@ -1449,7 +1425,7 @@ describe('IgxPivotGrid #pivotGrid', () => { }); // xit-ing because of https://github.com/IgniteUI/igniteui-angular/issues/10546 - xit('should sort on column for all sibling dimensions.', () => { + it.skip('should sort on column for all sibling dimensions.', () => { const pivotGrid = fixture.componentInstance.pivotGrid; pivotGrid.height = '1500px'; pivotGrid.pivotConfiguration.rows = [ @@ -1554,7 +1530,7 @@ describe('IgxPivotGrid #pivotGrid', () => { fixture.detectChanges(); let colHeaders = pivotGrid.columns.filter(x => x.level === 0).map(x => x.header); - let expected = ['01/05/2019', '01/06/2020', '02/19/2020', '05/12/2020', '01/01/2021', '04/07/2021', '12/08/2021'] + let expected = ['01/05/2019', '01/06/2020', '02/19/2020', '05/12/2020', '01/01/2021', '04/07/2021', '12/08/2021']; expect(colHeaders).toEqual(expected); // sort desc @@ -1570,7 +1546,7 @@ describe('IgxPivotGrid #pivotGrid', () => { fixture.detectChanges(); colHeaders = pivotGrid.columns.filter(x => x.level === 0).map(x => x.header); - expected = ['01/01/2021', '01/05/2019', '01/06/2020', '04/07/2021', '12/08/2021', '05/12/2020', '02/19/2020'] + expected = ['01/01/2021', '01/05/2019', '01/06/2020', '04/07/2021', '12/08/2021', '05/12/2020', '02/19/2020']; expect(colHeaders).toEqual(expected); }); @@ -1613,18 +1589,18 @@ describe('IgxPivotGrid #pivotGrid', () => { label: 'Sum of Sale' }, aggregateList: [{ - key: 'SUM', - aggregator: IgxTotalSaleAggregate.totalSale, - label: 'Sum of Sale' - }, { - key: 'MIN', - aggregator: IgxTotalSaleAggregate.totalMin, - label: 'Minimum of Sale' - }, { - key: 'MAX', - aggregator: IgxTotalSaleAggregate.totalMax, - label: 'Maximum of Sale' - }], + key: 'SUM', + aggregator: IgxTotalSaleAggregate.totalSale, + label: 'Sum of Sale' + }, { + key: 'MIN', + aggregator: IgxTotalSaleAggregate.totalMin, + label: 'Minimum of Sale' + }, { + key: 'MAX', + aggregator: IgxTotalSaleAggregate.totalMax, + label: 'Maximum of Sale' + }], enabled: true }); pivotGrid.pipeTrigger++; @@ -1894,9 +1870,9 @@ describe('IgxPivotGrid #pivotGrid', () => { } ]; pivotGrid.pivotConfiguration.filters = [{ - memberName: 'SellerName', - enabled: true - }]; + memberName: 'SellerName', + enabled: true + }]; pivotGrid.pipeTrigger++; pivotGrid.setupColumns(); fixture.detectChanges(); @@ -1911,8 +1887,8 @@ describe('IgxPivotGrid #pivotGrid', () => { fixture.detectChanges(); // check drop here chips are displayed in other areas - expect(headerRow.notificationChips.toArray()[1].nativeElement.hidden).toBeFalse(); - expect(headerRow.notificationChips.toArray()[2].nativeElement.hidden).toBeFalse(); + expect(headerRow.notificationChips.toArray()[1].nativeElement.hidden).toBe(false); + expect(headerRow.notificationChips.toArray()[2].nativeElement.hidden).toBe(false); const dropHereRowChip = headerRow.notificationChips.toArray()[2]; // move Seller onto the drop here chip @@ -2044,21 +2020,21 @@ describe('IgxPivotGrid #pivotGrid', () => { expect(pivotGrid.rowDimensionWidthToPixels(rowDimension)).toBe(200); fixture.componentInstance.pivotConfigHierarchy = { columns: [{ - memberName: 'Country', - enabled: true - }, + memberName: 'Country', + enabled: true + }, ], rows: [{ - memberName: 'All', - memberFunction: () => 'All', - enabled: true, - width: "auto", - childLevel: { - memberName: 'ProductCategory', - memberFunction: (data) => data.ProductCategory, - enabled: true - } - }], + memberName: 'All', + memberFunction: () => 'All', + enabled: true, + width: "auto", + childLevel: { + memberName: 'ProductCategory', + memberFunction: (data) => data.ProductCategory, + enabled: true + } + }], values: [ { member: 'UnitPrice', @@ -2094,9 +2070,9 @@ describe('IgxPivotGrid #pivotGrid', () => { expect(pivotGrid.pivotConfiguration).toEqual({ rows: null, columns: null, values: null, filters: null }); pivotGrid.data = [{ - ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley', - Country: 'Bulgaria', Date: new Date('01/01/2021'), UnitsSold: 282 - }]; + ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley', + Country: 'Bulgaria', Date: new Date('01/01/2021'), UnitsSold: 282 + }]; fixture.detectChanges(); expect(pivotGrid.allDimensions.length).toEqual(4); @@ -2125,7 +2101,7 @@ describe('IgxPivotGrid #pivotGrid', () => { total: false, years: true, quarters: false - } + }; expect(dateDimension.enabled).toBe(true); @@ -2138,7 +2114,7 @@ describe('IgxPivotGrid #pivotGrid', () => { it('should have the correct IGridCellEventArgs when clicking on a cell', () => { const pivotGrid = fixture.componentInstance.pivotGrid; - spyOn(pivotGrid.cellClick, 'emit').and.callThrough(); + vi.spyOn(pivotGrid.cellClick, 'emit'); fixture.detectChanges(); const cell = pivotGrid.gridAPI.get_cell_by_index(0, 'Bulgaria-UnitsSold'); @@ -2150,7 +2126,8 @@ describe('IgxPivotGrid #pivotGrid', () => { const expectedCell = new IgxGridCell(pivotGrid, 0, cell.column); const cellClickArgs: IGridCellEventArgs = { cell: expectedCell, event }; - expect(pivotGrid.cellClick.emit).toHaveBeenCalledOnceWith(cellClickArgs); + expect(pivotGrid.cellClick.emit).toHaveBeenCalledTimes(1); + expect(pivotGrid.cellClick.emit).toHaveBeenCalledWith(cellClickArgs); }); }); }); @@ -2169,12 +2146,11 @@ describe('IgxPivotGrid #pivotGrid', () => { expect(pivotGrid.selectedRows).toEqual([]); const pivotRows = GridFunctions.getPivotRows(fixture); const row = pivotRows[1].componentInstance; - const rowHeaders = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + const rowHeaders = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); const secondDimCell = rowHeaders.find(x => x.componentInstance.column.header === 'Clothing'); secondDimCell.nativeElement.click(); fixture.detectChanges(); - expect(row.selected).toBeTrue(); + expect(row.selected).toBe(true); expect(pivotGrid.selectedRows).not.toBeNull(); expect(pivotGrid.selectedRows.length).toBe(1); expect((pivotGrid.selectedRows[0] as IPivotGridRecord).dimensionValues.get('All cities')).toBe('All Cities'); @@ -2183,7 +2159,7 @@ describe('IgxPivotGrid #pivotGrid', () => { //deselect secondDimCell.nativeElement.click(); fixture.detectChanges(); - expect(row.selected).toBeFalse(); + expect(row.selected).toBe(false); expect(pivotGrid.selectedRows.length).toBe(0); }); @@ -2191,35 +2167,33 @@ describe('IgxPivotGrid #pivotGrid', () => { fixture.detectChanges(); const pivotGrid = fixture.componentInstance.pivotGrid; const pivotRows = GridFunctions.getPivotRows(fixture); - const rowHeaders = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + const rowHeaders = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); const firstDimCell = rowHeaders.find(x => x.componentInstance.column.header === 'All Cities'); firstDimCell.nativeElement.click(); fixture.detectChanges(); for (let i = 0; i < 5; ++i) { - expect(pivotRows[i].componentInstance.selected).toBeTrue(); + expect(pivotRows[i].componentInstance.selected).toBe(true); } expect(pivotGrid.selectedRows).not.toBeNull(); expect(pivotGrid.selectedRows.length).toBe(5); const dimensionValues = PivotGridFunctions.getDimensionValues(pivotGrid.selectedRows); - const expected = - [ - { - AllProducts: 'AllProducts', 'All cities': 'All Cities' - }, - { - ProductCategory: 'Clothing', 'All cities': 'All Cities' - }, - { - ProductCategory: 'Bikes', 'All cities': 'All Cities' - }, - { - ProductCategory: 'Accessories', 'All cities': 'All Cities' - }, - { - ProductCategory: 'Components', 'All cities': 'All Cities' - } - ]; + const expected = [ + { + AllProducts: 'AllProducts', 'All cities': 'All Cities' + }, + { + ProductCategory: 'Clothing', 'All cities': 'All Cities' + }, + { + ProductCategory: 'Bikes', 'All cities': 'All Cities' + }, + { + ProductCategory: 'Accessories', 'All cities': 'All Cities' + }, + { + ProductCategory: 'Components', 'All cities': 'All Cities' + } + ]; expect(dimensionValues).toEqual(expected); }); @@ -2319,14 +2293,14 @@ describe('IgxPivotGrid #pivotGrid', () => { const dimensionContents = fixture.debugElement.queryAll(By.css('.igx-grid__tbody-pivot-dimension')); let rowHeaders = dimensionContents[0].queryAll(By.directive(IgxPivotRowDimensionHeaderGroupComponent)); - expect(rowHeaders[0].componentInstance.column.resizable).toBeTrue(); - expect(rowHeaders[3].componentInstance.column.resizable).toBeTrue(); + expect(rowHeaders[0].componentInstance.column.resizable).toBe(true); + expect(rowHeaders[3].componentInstance.column.resizable).toBe(true); rowHeaders = dimensionContents[1].queryAll(By.directive(IgxPivotRowDimensionHeaderGroupComponent)); - expect(rowHeaders[0].componentInstance.column.resizable).toBeTrue(); - expect(rowHeaders[1].componentInstance.column.resizable).toBeTrue(); - expect(rowHeaders[5].componentInstance.column.resizable).toBeTrue(); - expect(rowHeaders[7].componentInstance.column.resizable).toBeTrue(); + expect(rowHeaders[0].componentInstance.column.resizable).toBe(true); + expect(rowHeaders[1].componentInstance.column.resizable).toBe(true); + expect(rowHeaders[5].componentInstance.column.resizable).toBe(true); + expect(rowHeaders[7].componentInstance.column.resizable).toBe(true); })); it('should update grid after resizing a top dimension header to be bigger.', fakeAsync(() => { @@ -2529,7 +2503,7 @@ describe('IgxPivotGrid #pivotGrid', () => { it("should position correct the horizontal scrollbar", () => { fixture.detectChanges(); const scrollBarPosition = fixture.nativeElement.querySelector("igx-horizontal-virtual-helper").getBoundingClientRect(); - const displayContainerPosition = fixture.nativeElement.querySelector(".igx-grid__tbody-content").getBoundingClientRect() + const displayContainerPosition = fixture.nativeElement.querySelector(".igx-grid__tbody-content").getBoundingClientRect(); expect(scrollBarPosition.x).toEqual(displayContainerPosition.x); }); }); @@ -2837,7 +2811,8 @@ describe('IgxPivotGrid #pivotGrid', () => { { memberName: 'ProductCategory', enabled: true - }], + } + ], values: [ { member: 'UnitsSold', @@ -2856,8 +2831,7 @@ describe('IgxPivotGrid #pivotGrid', () => { const rows = pivotGrid.rowList.toArray(); expect(rows.length).toBe(4); const expectedHeaders = ['Clothing', 'Bikes', 'Accessories', 'Components']; - const rowHeaders = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + const rowHeaders = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); const rowDimensionHeaders = rowHeaders.map(x => x.componentInstance.column.header); expect(rowDimensionHeaders).toEqual(expectedHeaders); @@ -2884,7 +2858,8 @@ describe('IgxPivotGrid #pivotGrid', () => { { memberName: 'ProductCategory', enabled: true - }], + } + ], values: [ { member: 'UnitsSold', @@ -2918,7 +2893,7 @@ describe('IgxPivotGrid #pivotGrid', () => { rowValues.add('Clothing'); pivotGrid.filterDimension(pivotGrid.pivotConfiguration.rows[1].childLevel, rowValues, IgxStringFilteringOperand.instance().condition('in')); expect(pivotGrid.rowList.length).toBe(4); - const rowDimData = pivotGrid.rowList.map(x => (x as IgxPivotRowComponent).data.dimensionValues.get('ProductCategory')) + const rowDimData = pivotGrid.rowList.map(x => (x as IgxPivotRowComponent).data.dimensionValues.get('ProductCategory')); expect(rowDimData).toEqual([undefined, 'Clothing', undefined, 'Clothing']); expect(pivotGrid.filteringExpressionsTree.filteringOperands.length).toEqual(2); }); @@ -2957,7 +2932,8 @@ describe('IgxPivotGrid #pivotGrid', () => { memberName: 'ProductCategory', enabled: true, filter: filterRowExpTree - }], + } + ], values: [ { member: 'UnitsSold', @@ -3046,10 +3022,8 @@ describe('IgxPivotGrid #pivotGrid', () => { // check rows const rows = pivotGrid.rowList.toArray(); expect(rows.length).toBe(7); - const layoutContainer = fixture.debugElement.query( - By.directive(IgxPivotRowDimensionMrlRowComponent)); - const contentRowHeaders = layoutContainer.queryAll( - By.directive(IgxPivotRowDimensionContentComponent)); + const layoutContainer = fixture.debugElement.query(By.directive(IgxPivotRowDimensionMrlRowComponent)); + const contentRowHeaders = layoutContainer.queryAll(By.directive(IgxPivotRowDimensionContentComponent)); // check each dimension from hierarchy is on another column. const rowDimensionCol1 = contentRowHeaders.filter(y => y.componentInstance.layout.colStart === 1); @@ -3081,10 +3055,8 @@ describe('IgxPivotGrid #pivotGrid', () => { it("should horizontally expand/collapse on a single dimension hierarchy.", () => { fixture.detectChanges(); - let layoutContainer = fixture.debugElement.query( - By.directive(IgxPivotRowDimensionMrlRowComponent)); - let contentRowHeaders = layoutContainer.queryAll( - By.directive(IgxPivotRowDimensionContentComponent)); + let layoutContainer = fixture.debugElement.query(By.directive(IgxPivotRowDimensionMrlRowComponent)); + let contentRowHeaders = layoutContainer.queryAll(By.directive(IgxPivotRowDimensionContentComponent)); // collapse All Products let rowDimensionCol3 = contentRowHeaders.filter(y => y.componentInstance.layout.colStart === 3)[0]; @@ -3096,10 +3068,8 @@ describe('IgxPivotGrid #pivotGrid', () => { fixture.detectChanges(); // check cells are merged - layoutContainer = fixture.debugElement.query( - By.directive(IgxPivotRowDimensionMrlRowComponent)); - contentRowHeaders = layoutContainer.queryAll( - By.directive(IgxPivotRowDimensionContentComponent)); + layoutContainer = fixture.debugElement.query(By.directive(IgxPivotRowDimensionMrlRowComponent)); + contentRowHeaders = layoutContainer.queryAll(By.directive(IgxPivotRowDimensionContentComponent)); rowDimensionCol3 = contentRowHeaders.filter(y => y.componentInstance.layout.colStart === 3)[0]; expect(rowDimensionCol3.componentInstance.layout.colStart).toEqual(3); expect(rowDimensionCol3.componentInstance.layout.colEnd).toEqual(5); @@ -3113,10 +3083,8 @@ describe('IgxPivotGrid #pivotGrid', () => { fixture.detectChanges(); // check cell is no longer merged. - layoutContainer = fixture.debugElement.query( - By.directive(IgxPivotRowDimensionMrlRowComponent)); - contentRowHeaders = layoutContainer.queryAll( - By.directive(IgxPivotRowDimensionContentComponent)); + layoutContainer = fixture.debugElement.query(By.directive(IgxPivotRowDimensionMrlRowComponent)); + contentRowHeaders = layoutContainer.queryAll(By.directive(IgxPivotRowDimensionContentComponent)); rowDimensionCol3 = contentRowHeaders.filter(y => y.componentInstance.layout.colStart === 3)[0]; expect(rowDimensionCol3.componentInstance.layout.colStart).toEqual(3); expect(rowDimensionCol3.componentInstance.layout.colEnd).toEqual(4); @@ -3126,14 +3094,12 @@ describe('IgxPivotGrid #pivotGrid', () => { it("should collapse fully the last dimension if all parent dimensions get collapsed.", () => { pivotGrid.data = [{ - ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley Brooker', - Country: 'Bulgaria', City: 'Plovdiv', Date: '01/01/2012', UnitsSold: 282 - }]; + ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley Brooker', + Country: 'Bulgaria', City: 'Plovdiv', Date: '01/01/2012', UnitsSold: 282 + }]; fixture.detectChanges(); - let layoutContainer = fixture.debugElement.query( - By.directive(IgxPivotRowDimensionMrlRowComponent)); - let contentRowHeaders = layoutContainer.queryAll( - By.directive(IgxPivotRowDimensionContentComponent)); + let layoutContainer = fixture.debugElement.query(By.directive(IgxPivotRowDimensionMrlRowComponent)); + let contentRowHeaders = layoutContainer.queryAll(By.directive(IgxPivotRowDimensionContentComponent)); const rowDimensionsCol3 = contentRowHeaders.filter(y => y.componentInstance.layout.colStart === 3); let rowDimensionsCol4 = contentRowHeaders.filter(y => y.componentInstance.layout.colStart === 4); @@ -3143,10 +3109,8 @@ describe('IgxPivotGrid #pivotGrid', () => { expander.nativeElement.click(); fixture.detectChanges(); - layoutContainer = fixture.debugElement.query( - By.directive(IgxPivotRowDimensionMrlRowComponent)); - contentRowHeaders = layoutContainer.queryAll( - By.directive(IgxPivotRowDimensionContentComponent)); + layoutContainer = fixture.debugElement.query(By.directive(IgxPivotRowDimensionMrlRowComponent)); + contentRowHeaders = layoutContainer.queryAll(By.directive(IgxPivotRowDimensionContentComponent)); rowDimensionsCol4 = contentRowHeaders.filter(y => y.componentInstance.layout.colStart === 4); // nothing is now on column 4 since all are collapsed. expect(rowDimensionsCol4.length).toBe(0); @@ -3171,13 +3135,10 @@ describe('IgxPivotGrid #pivotGrid', () => { // check rows const rows = pivotGrid.rowList.toArray(); expect(rows.length).toBe(7); - let layoutContainers = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionMrlRowComponent)); + let layoutContainers = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionMrlRowComponent)); expect(layoutContainers.length).toBe(2); - const contentRowHeaders = layoutContainers[0].queryAll( - By.directive(IgxPivotRowDimensionContentComponent)); - const summaryRowHeaders = layoutContainers[1].queryAll( - By.directive(IgxPivotRowDimensionContentComponent)); + const contentRowHeaders = layoutContainers[0].queryAll(By.directive(IgxPivotRowDimensionContentComponent)); + const summaryRowHeaders = layoutContainers[1].queryAll(By.directive(IgxPivotRowDimensionContentComponent)); // check first column of data contains summary const summaryRowHeader = summaryRowHeaders.map(x => x.componentInstance.rowDimensionColumn.header); @@ -3189,8 +3150,7 @@ describe('IgxPivotGrid #pivotGrid', () => { expander.nativeElement.click(); fixture.detectChanges(); - layoutContainers = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionMrlRowComponent)); + layoutContainers = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionMrlRowComponent)); expect(layoutContainers.length).toBe(1); expect(pivotGrid.rowList.toArray().length).toBe(1); }); @@ -3236,8 +3196,7 @@ describe('IgxPivotGrid #pivotGrid', () => { expander.nativeElement.click(); fixture.detectChanges(); - layoutContainers = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionMrlRowComponent)); + layoutContainers = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionMrlRowComponent)); expect(layoutContainers.length).toBe(1); expect(pivotGrid.rowList.toArray().length).toBe(1); expect(pivotGrid.navigation.activeNode.row).toEqual(0); @@ -3290,10 +3249,8 @@ describe('IgxPivotGrid #pivotGrid', () => { it("should allow navigation in the row layouts.", fakeAsync(() => { fixture.detectChanges(); - const layoutContainer = fixture.debugElement.query( - By.directive(IgxPivotRowDimensionMrlRowComponent)); - const allGroups = layoutContainer.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + const layoutContainer = fixture.debugElement.query(By.directive(IgxPivotRowDimensionMrlRowComponent)); + const allGroups = layoutContainer.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); const row0Col0 = allGroups[0]; const row0Col1 = allGroups.filter(x => x.componentInstance.column.header === "Plovdiv")[0]; const row1Col1 = allGroups.filter(x => x.componentInstance.column.header === "New York")[0]; @@ -3404,8 +3361,7 @@ describe('IgxPivotGrid #pivotGrid', () => { memberFunction: () => 'AllProducts', memberName: 'AllProducts', enabled: true, - childLevel: - { + childLevel: { memberFunction: (data) => data.ProductCategory, memberName: 'ProductCategory', enabled: true @@ -3414,8 +3370,7 @@ describe('IgxPivotGrid #pivotGrid', () => { ]; pivotGrid.pipeTrigger++; fixture.detectChanges(); - let rowHeaders = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + let rowHeaders = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); const productsHeaderColumn = rowHeaders.filter(x => x.componentInstance.column.header === "ProductCategory")[0].nativeElement; const productRowContents = rowHeaders.filter(x => x.componentInstance.column.field === "ProductCategory"); @@ -3429,8 +3384,7 @@ describe('IgxPivotGrid #pivotGrid', () => { sortIcon.click(); fixture.detectChanges(); - rowHeaders = fixture.debugElement.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + rowHeaders = fixture.debugElement.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); const updatedProductRowContents = rowHeaders.filter(x => x.componentInstance.column.field === "ProductCategory"); const updatedProductRowContentsHeaders = updatedProductRowContents.map(x => x.componentInstance.column.header); expect(updatedProductRowContentsHeaders).toEqual(['ProductCategory', 'Components', 'Clothing', 'Bikes', 'Accessories']); @@ -3438,17 +3392,15 @@ describe('IgxPivotGrid #pivotGrid', () => { it("should allow select/deselect the correct rows on row header click.", () => { fixture.detectChanges(); - const layoutContainer = fixture.debugElement.query( - By.directive(IgxPivotRowDimensionMrlRowComponent)); - const rowHeaders = layoutContainer.queryAll( - By.directive(IgxPivotRowDimensionHeaderComponent)); + const layoutContainer = fixture.debugElement.query(By.directive(IgxPivotRowDimensionMrlRowComponent)); + const rowHeaders = layoutContainer.queryAll(By.directive(IgxPivotRowDimensionHeaderComponent)); expect(pivotGrid.selectedRows).toEqual([]); const pivotRows = GridFunctions.getPivotRows(fixture); const row = pivotRows[4].componentInstance; const secondDimCell = rowHeaders.find(x => x.componentInstance.column.header === 'Accessories'); secondDimCell.nativeElement.click(); fixture.detectChanges(); - expect(row.selected).toBeTrue(); + expect(row.selected).toBe(true); expect(pivotGrid.selectedRows).not.toBeNull(); expect(pivotGrid.selectedRows.length).toBe(1); expect((pivotGrid.selectedRows[0] as IPivotGridRecord).dimensionValues.get('ProductCategory')).toBe('Accessories'); @@ -3476,8 +3428,7 @@ describe('IgxPivotGrid #pivotGrid', () => { memberName: 'Country', enabled: true }, - ] - , + ], rows: [ { memberFunction: () => 'All', diff --git a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-add-row-ui.spec.ts b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-add-row-ui.spec.ts index 17e30376260..bf9e422de7a 100644 --- a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-add-row-ui.spec.ts +++ b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-add-row-ui.spec.ts @@ -9,6 +9,7 @@ import { IgxTreeGridRowComponent } from './tree-grid-row.component'; import { first } from 'rxjs/operators'; import { wait } from '../../../test-utils/ui-interactions.spec'; import { IRowDataCancelableEventArgs } from 'igniteui-angular/grids/core'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('IgxTreeGrid - Add Row UI #tGrid', () => { let fix; @@ -74,7 +75,7 @@ describe('IgxTreeGrid - Add Row UI #tGrid', () => { endTransition(); const addRow = treeGrid.gridAPI.get_row_by_index(2); - expect(addRow.addRowUI).toBeTrue(); + expect(addRow.addRowUI).toBe(true); treeGrid.gridAPI.crudService.endEdit(true); fix.detectChanges(); @@ -90,7 +91,7 @@ describe('IgxTreeGrid - Add Row UI #tGrid', () => { row.beginAddChild(); fix.detectChanges(); const addRow = treeGrid.gridAPI.get_row_by_index(2); - expect(addRow.addRowUI).toBeTrue(); + expect(addRow.addRowUI).toBe(true); }); it('should allow adding sibling to child row via the API.', () => { @@ -138,8 +139,8 @@ describe('IgxTreeGrid - Add Row UI #tGrid', () => { treeGrid.pinRow(1); treeGrid.pinRow(6); - expect(treeGrid.getRowByKey(1).pinned).toBeTrue(); - expect(treeGrid.getRowByKey(6).pinned).toBeTrue(); + expect(treeGrid.getRowByKey(1).pinned).toBe(true); + expect(treeGrid.getRowByKey(6).pinned).toBe(true); actionStrip.show(treeGrid.rowList.toArray()[1]); fix.detectChanges(); @@ -153,8 +154,8 @@ describe('IgxTreeGrid - Add Row UI #tGrid', () => { endTransition(); const addRow = treeGrid.gridAPI.get_row_by_index(2); - expect(addRow.addRowUI).toBeTrue(); - expect(addRow.inEditMode).toBeTrue(); + expect(addRow.addRowUI).toBe(true); + expect(addRow.inEditMode).toBe(true); treeGrid.gridAPI.crudService.endEdit(true); fix.detectChanges(); @@ -172,8 +173,8 @@ describe('IgxTreeGrid - Add Row UI #tGrid', () => { treeGrid.pinRow(1); treeGrid.pinRow(6); - expect(treeGrid.getRowByKey(1).pinned).toBeTrue(); - expect(treeGrid.getRowByKey(6).pinned).toBeTrue(); + expect(treeGrid.getRowByKey(1).pinned).toBe(true); + expect(treeGrid.getRowByKey(6).pinned).toBe(true); actionStrip.show(treeGrid.rowList.last); fix.detectChanges(); @@ -187,8 +188,8 @@ describe('IgxTreeGrid - Add Row UI #tGrid', () => { endTransition(); const addRow = treeGrid.gridAPI.get_row_by_index(10); - expect(addRow.addRowUI).toBeTrue(); - expect(addRow.inEditMode).toBeTrue(); + expect(addRow.addRowUI).toBe(true); + expect(addRow.inEditMode).toBe(true); treeGrid.gridAPI.crudService.endEdit(true); fix.detectChanges(); @@ -206,7 +207,7 @@ describe('IgxTreeGrid - Add Row UI #tGrid', () => { endTransition(); const addRow = treeGrid.gridAPI.get_row_by_index(2); - expect(addRow.addRowUI).toBeTrue(); + expect(addRow.addRowUI).toBe(true); treeGrid.gridAPI.crudService.endEdit(true); fix.detectChanges(); @@ -216,7 +217,7 @@ describe('IgxTreeGrid - Add Row UI #tGrid', () => { expect(addedRow.data[treeGrid.foreignKey]).toBe(2); }); - it('should collapse row when child row adding begins and it added row should go under correct parent.', async() => { + it('should collapse row when child row adding begins and it added row should go under correct parent.', async () => { treeGrid.data = [ { ID: 1, ParentID: -1, Name: 'Casey Houston', JobTitle: 'Vice President', Age: 32 }, { ID: 2, ParentID: 10, Name: 'Gilberto Todd', JobTitle: 'Director', Age: 41 }, @@ -247,7 +248,7 @@ describe('IgxTreeGrid - Add Row UI #tGrid', () => { fix.detectChanges(); // last row should be add row const addRow = treeGrid.gridAPI.get_row_by_index(4); - expect(addRow.addRowUI).toBeTrue(); + expect(addRow.addRowUI).toBe(true); endTransition(); // end edit diff --git a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-crud.spec.ts b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-crud.spec.ts index 5cfae2b3c6f..d1c3ecd342d 100644 --- a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-crud.spec.ts +++ b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-crud.spec.ts @@ -10,6 +10,7 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { GridFunctions } from '../../../test-utils/grid-functions.spec'; import { DebugElement } from '@angular/core'; import { IgxTreeGridComponent } from './tree-grid.component'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const CELL_CSS_CLASS = '.igx-grid__td'; @@ -243,7 +244,7 @@ describe('IgxTreeGrid - CRUD #tGrid', () => { let error = ''; const newRow = { ID: 777, - ParentID: 12345, // there is no row with ID=12345 + ParentID: 12345, // there is no row with ID=12345 Name: 'New Employee 1', JobTitle: 'Senior Web Developer', Age: 33 @@ -562,28 +563,28 @@ describe('IgxTreeGrid - CRUD #tGrid', () => { UIInteractions.simulateDoubleClickAndSelectEvent(treeGrid.gridAPI.get_cell_by_index(0, 'ID')); fix.detectChanges(); - expect(cell.editMode).toBe(true, 'cannot enter edit mode with double click'); + expect(cell.editMode, 'cannot enter edit mode with double click').toBe(true); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); - expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with double click'); + expect(cell.editMode, 'cannot exit edit mode after entering with double click').toBe(false); UIInteractions.triggerEventHandlerKeyDown('enter', gridContent); fix.detectChanges(); - expect(cell.editMode).toBe(true, 'cannot enter edit mode with enter'); + expect(cell.editMode, 'cannot enter edit mode with enter').toBe(true); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); - expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with enter'); + expect(cell.editMode, 'cannot exit edit mode after entering with enter').toBe(false); UIInteractions.triggerEventHandlerKeyDown('f2', gridContent); fix.detectChanges(); - expect(cell.editMode).toBe(true, 'cannot enter edit mode with F2'); + expect(cell.editMode, 'cannot enter edit mode with F2').toBe(true); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); - expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with F2'); + expect(cell.editMode, 'cannot exit edit mode after entering with F2').toBe(false); }); it('should be able to enter edit mode of a non-tree-grid column on dblclick, enter and F2', () => { @@ -591,27 +592,27 @@ describe('IgxTreeGrid - CRUD #tGrid', () => { UIInteractions.simulateDoubleClickAndSelectEvent(treeGrid.gridAPI.get_cell_by_index(0, 'Name')); fix.detectChanges(); - expect(cell.editMode).toBe(true, 'cannot enter edit mode with double click'); + expect(cell.editMode, 'cannot enter edit mode with double click').toBe(true); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); - expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with double click'); + expect(cell.editMode, 'cannot exit edit mode after entering with double click').toBe(false); UIInteractions.triggerEventHandlerKeyDown('enter', gridContent); fix.detectChanges(); - expect(cell.editMode).toBe(true, 'cannot enter edit mode with enter'); + expect(cell.editMode, 'cannot enter edit mode with enter').toBe(true); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); - expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with enter'); + expect(cell.editMode, 'cannot exit edit mode after entering with enter').toBe(false); UIInteractions.triggerEventHandlerKeyDown('f2', gridContent); fix.detectChanges(); - expect(cell.editMode).toBe(true, 'cannot enter edit mode with F2'); + expect(cell.editMode, 'cannot enter edit mode with F2').toBe(true); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); - expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with F2'); + expect(cell.editMode, 'cannot exit edit mode after entering with F2').toBe(false); }); it('should be able to edit a tree-grid cell through UI', () => { @@ -703,27 +704,27 @@ describe('IgxTreeGrid - CRUD #tGrid', () => { UIInteractions.simulateDoubleClickAndSelectEvent(treeGrid.gridAPI.get_cell_by_index(0, 'ID')); fix.detectChanges(); - expect(cell.editMode).toBe(true, 'cannot enter edit mode with double click'); + expect(cell.editMode, 'cannot enter edit mode with double click').toBe(true); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); - expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with double click'); + expect(cell.editMode, 'cannot exit edit mode after entering with double click').toBe(false); UIInteractions.triggerEventHandlerKeyDown('enter', gridContent); fix.detectChanges(); - expect(cell.editMode).toBe(true, 'cannot enter edit mode with enter'); + expect(cell.editMode, 'cannot enter edit mode with enter').toBe(true); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); - expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with enter'); + expect(cell.editMode, 'cannot exit edit mode after entering with enter').toBe(false); UIInteractions.triggerEventHandlerKeyDown('f2', gridContent); fix.detectChanges(); - expect(cell.editMode).toBe(true, 'cannot enter edit mode with F2'); + expect(cell.editMode, 'cannot enter edit mode with F2').toBe(true); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); - expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with F2'); + expect(cell.editMode, 'cannot exit edit mode after entering with F2').toBe(false); }); it('should be able to enter edit mode of a non-tree-grid column on dblclick, enter and F2', () => { @@ -731,27 +732,27 @@ describe('IgxTreeGrid - CRUD #tGrid', () => { UIInteractions.simulateDoubleClickAndSelectEvent(treeGrid.gridAPI.get_cell_by_index(0, 'Name')); fix.detectChanges(); - expect(cell.editMode).toBe(true, 'cannot enter edit mode with double click'); + expect(cell.editMode, 'cannot enter edit mode with double click').toBe(true); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); - expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with double click'); + expect(cell.editMode, 'cannot exit edit mode after entering with double click').toBe(false); UIInteractions.triggerEventHandlerKeyDown('enter', gridContent); fix.detectChanges(); - expect(cell.editMode).toBe(true, 'cannot enter edit mode with enter'); + expect(cell.editMode, 'cannot enter edit mode with enter').toBe(true); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); - expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with enter'); + expect(cell.editMode, 'cannot exit edit mode after entering with enter').toBe(false); UIInteractions.triggerEventHandlerKeyDown('f2', gridContent); fix.detectChanges(); - expect(cell.editMode).toBe(true, 'cannot enter edit mode with F2'); + expect(cell.editMode, 'cannot enter edit mode with F2').toBe(true); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); - expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with F2'); + expect(cell.editMode, 'cannot exit edit mode after entering with F2').toBe(false); }); it('should be able to edit a tree-grid cell through UI', () => { @@ -828,12 +829,12 @@ describe('IgxTreeGrid - CRUD #tGrid', () => { fix.detectChanges(); cell.editMode = true; fix.detectChanges(); - expect(cell.row.inEditMode).toBeTrue(); + expect(cell.row.inEditMode).toBe(true); treeGrid.rowEditable = false; fix.detectChanges(); cell.editValue = true; fix.detectChanges(); - expect(cell.row.inEditMode).toBeFalse(); + expect(cell.row.inEditMode).toBe(false); }); }); @@ -934,8 +935,8 @@ describe('IgxTreeGrid - CRUD #tGrid', () => { }); it('should delete a root level row by ID', () => { - spyOn(treeGrid.rowDelete, 'emit').and.callThrough(); - spyOn(treeGrid.rowDeleted, 'emit').and.callThrough(); + vi.spyOn(treeGrid.rowDelete, 'emit'); + vi.spyOn(treeGrid.rowDeleted, 'emit'); let someRow = treeGrid.getRowByIndex(0); expect(someRow.key).toBe(1); @@ -965,8 +966,11 @@ describe('IgxTreeGrid - CRUD #tGrid', () => { treeGrid.deleteRow(someRow.key); fix.detectChanges(); - expect(treeGrid.rowDelete.emit).toHaveBeenCalledOnceWith(rowDeleteArgs); - expect(treeGrid.rowDeleted.emit).toHaveBeenCalledOnceWith(rowDeletedArgs); + expect(treeGrid.rowDelete.emit).toHaveBeenCalledTimes(1); + + expect(treeGrid.rowDelete.emit).toHaveBeenCalledWith(rowDeleteArgs); + expect(treeGrid.rowDeleted.emit).toHaveBeenCalledTimes(1); + expect(treeGrid.rowDeleted.emit).toHaveBeenCalledWith(rowDeletedArgs); someRow = treeGrid.getRowByIndex(0); expect(someRow.key).toBe(2); @@ -977,8 +981,8 @@ describe('IgxTreeGrid - CRUD #tGrid', () => { }); it('should cancel rowDelete event', () => { - spyOn(treeGrid.rowDelete, 'emit').and.callThrough(); - spyOn(treeGrid.rowDeleted, 'emit').and.callThrough(); + vi.spyOn(treeGrid.rowDelete, 'emit'); + vi.spyOn(treeGrid.rowDeleted, 'emit'); let someRow = treeGrid.getRowByIndex(0); expect(someRow.key).toBe(1); @@ -1004,7 +1008,9 @@ describe('IgxTreeGrid - CRUD #tGrid', () => { treeGrid.deleteRow(someRow.key); fix.detectChanges(); - expect(treeGrid.rowDelete.emit).toHaveBeenCalledOnceWith(rowDeleteArgs); + expect(treeGrid.rowDelete.emit).toHaveBeenCalledTimes(1); + + expect(treeGrid.rowDelete.emit).toHaveBeenCalledWith(rowDeleteArgs); expect(treeGrid.rowDeleted.emit).toHaveBeenCalledTimes(0); someRow = treeGrid.getRowByIndex(0); @@ -1114,9 +1120,9 @@ describe('IgxTreeGrid - CRUD #tGrid', () => { const verifyRowsCount = (fix, expectedRootRowsCount, expectedVisibleRowsCount) => { const treeGrid = fix.componentInstance.treeGrid; - expect(TreeGridFunctions.getAllRows(fix).length).toBe(expectedVisibleRowsCount, 'Incorrect DOM rows length.'); - expect(treeGrid.data.length).toBe(expectedRootRowsCount, 'Incorrect data length.'); - expect(treeGrid.dataRowList.length).toBe(expectedVisibleRowsCount, 'Incorrect dataRowList length.'); + expect(TreeGridFunctions.getAllRows(fix).length, 'Incorrect DOM rows length.').toBe(expectedVisibleRowsCount); + expect(treeGrid.data.length, 'Incorrect data length.').toBe(expectedRootRowsCount); + expect(treeGrid.dataRowList.length, 'Incorrect dataRowList length.').toBe(expectedVisibleRowsCount); }; const verifyTreeGridRecordsCount = (fix, expectedRootRecordsCount, expectedFlatRecordsCount) => { @@ -1135,6 +1141,6 @@ const verifyCellValue = (fix, rowIndex, columnKey, expectedCellValue) => { const treeGrid = fix.componentInstance.treeGrid; const actualValue = TreeGridFunctions.getCellValue(fix, rowIndex, columnKey); const actualAPIValue = treeGrid.gridAPI.get_row_by_index(rowIndex).cells.filter((c) => c.column.field === columnKey)[0].value; - expect(actualValue.toString()).toBe(expectedCellValue, 'incorrect cell value'); - expect(actualAPIValue.toString()).toBe(expectedCellValue, 'incorrect api cell value'); + expect(actualValue.toString(), 'incorrect cell value').toBe(expectedCellValue); + expect(actualAPIValue.toString(), 'incorrect api cell value').toBe(expectedCellValue); }; diff --git a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-expanding.spec.ts b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-expanding.spec.ts index b1ab72d1c22..5e035c3e086 100644 --- a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-expanding.spec.ts +++ b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-expanding.spec.ts @@ -1,14 +1,6 @@ import { TestBed, fakeAsync, tick, waitForAsync } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { - IgxTreeGridExpandingComponent, - IgxTreeGridPrimaryForeignKeyComponent, - IgxTreeGridRowEditingComponent, - IgxTreeGridLoadOnDemandComponent, - IgxTreeGridLoadOnDemandHasChildrenComponent, - IgxTreeGridLoadOnDemandChildDataComponent, - IgxTreeGridCustomExpandersTemplateComponent -} from '../../../test-utils/tree-grid-components.spec'; +import { IgxTreeGridExpandingComponent, IgxTreeGridPrimaryForeignKeyComponent, IgxTreeGridRowEditingComponent, IgxTreeGridLoadOnDemandComponent, IgxTreeGridLoadOnDemandHasChildrenComponent, IgxTreeGridLoadOnDemandChildDataComponent, IgxTreeGridCustomExpandersTemplateComponent } from '../../../test-utils/tree-grid-components.spec'; import { TreeGridFunctions } from '../../../test-utils/tree-grid-functions.spec'; import { first } from 'rxjs/operators'; import { wait } from '../../../test-utils/ui-interactions.spec'; @@ -17,6 +9,7 @@ import { CellType, GridSelectionMode } from 'igniteui-angular/grids/core'; import { IgxTreeGridComponent } from './tree-grid.component'; import { QueryList } from '@angular/core'; import { IgxTreeGridAPIService } from './tree-grid-api.service'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { let fix; @@ -218,44 +211,44 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { // expand a root level row let aRow = treeGrid.gridAPI.get_row_by_index(0); let cells = (aRow.cells as QueryList).toArray(); - expect(cells[0].value).toBe(147, 'wrong root level row'); + expect(cells[0].value, 'wrong root level row').toBe(147); expect(aRow.expanded).toBe(false); aRow.expanded = true; fix.detectChanges(); rows = TreeGridFunctions.getAllRows(fix); - expect(rows.length).toBe(7, 'root level row expanding problem'); + expect(rows.length, 'root level row expanding problem').toBe(7); // expand a second level row aRow = treeGrid.gridAPI.get_row_by_index(3); cells = (aRow.cells as QueryList).toArray(); - expect(cells[0].value).toBe(317, 'wrong second level row'); + expect(cells[0].value, 'wrong second level row').toBe(317); expect(aRow.expanded).toBe(false); aRow.expanded = true; fix.detectChanges(); rows = TreeGridFunctions.getAllRows(fix); - expect(rows.length).toBe(9, 'second level row expanding problem'); + expect(rows.length, 'second level row expanding problem').toBe(9); // check third level rows are having the correct values aRow = treeGrid.gridAPI.get_row_by_index(4); cells = (aRow.cells as QueryList).toArray(); - expect(cells[0].value).toBe(711, 'wrong third level row'); + expect(cells[0].value, 'wrong third level row').toBe(711); aRow = treeGrid.gridAPI.get_row_by_index(5); cells = (aRow.cells as QueryList).toArray(); - expect(cells[0].value).toBe(998, 'wrong third level row'); + expect(cells[0].value, 'wrong third level row').toBe(998); // collapse a second level row aRow = treeGrid.gridAPI.get_row_by_index(3); aRow.expanded = false; fix.detectChanges(); rows = TreeGridFunctions.getAllRows(fix); - expect(rows.length).toBe(7, 'second level row collapsing problem'); + expect(rows.length, 'second level row collapsing problem').toBe(7); // collapse a root level row aRow = treeGrid.gridAPI.get_row_by_index(0); aRow.expanded = false; fix.detectChanges(); rows = TreeGridFunctions.getAllRows(fix); - expect(rows.length).toBe(4, 'root level row collapsing problem'); + expect(rows.length, 'root level row collapsing problem').toBe(4); }); it('should expand/collapse when using \'expandAll\' and \'collapseAll\' methods', () => { @@ -277,19 +270,19 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { expect(rows.length).toBe(4); }); - it('should emit an event when expanding rows (API)', (done) => { + it('should emit an event when expanding rows (API)', async () => { const aRow = treeGrid.gridAPI.get_row_by_index(0); treeGrid.rowToggle.pipe(first()).subscribe((args) => { expect(args.cancel).toBe(false); expect(args.event).toBeUndefined(); expect(args.expanded).toBe(true); expect(args.rowID.ID).toBe(147); - done(); + ; }); aRow.expanded = true; }); - it('should emit an event when collapsing rows (API)', (done) => { + it('should emit an event when collapsing rows (API)', async () => { const aRow = treeGrid.gridAPI.get_row_by_index(0); aRow.expanded = true; fix.detectChanges(); @@ -298,26 +291,26 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { expect(args.event).toBeUndefined(); expect(args.expanded).toBe(false); expect(args.rowID.ID).toBe(147); - done(); + ; }); aRow.expanded = false; fix.detectChanges(); }); - it('should emit an event when expanding rows (UI)', (done) => { + it('should emit an event when expanding rows (UI)', async () => { treeGrid.rowToggle.pipe(first()).subscribe((args) => { expect(args.cancel).toBe(false); expect(args.event).toBeDefined(); expect(args.expanded).toBe(true); expect(args.rowID.ID).toBe(147); - done(); + ; }); const rowsDOM = TreeGridFunctions.getAllRows(fix); const indicatorDivDOM = TreeGridFunctions.getExpansionIndicatorDiv(rowsDOM[0]); indicatorDivDOM.triggerEventHandler('click', new Event('click')); }); - it('should emit an event when collapsing rows (UI)', (done) => { + it('should emit an event when collapsing rows (UI)', async () => { const rowsDOM = TreeGridFunctions.getAllRows(fix); const indicatorDivDOM = TreeGridFunctions.getExpansionIndicatorDiv(rowsDOM[0]); indicatorDivDOM.triggerEventHandler('click', new Event('click')); @@ -327,7 +320,7 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { expect(args.event).toBeDefined(); expect(args.expanded).toBe(false); expect(args.rowID.ID).toBe(147); - done(); + ; }); indicatorDivDOM.triggerEventHandler('click', new Event('click')); fix.detectChanges(); @@ -659,32 +652,32 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { // expand a root level row let aRow = treeGrid.gridAPI.get_row_by_index(0); let cells = (aRow.cells as QueryList).toArray(); - expect(cells[0].value).toBe(1, 'wrong root level row'); + expect(cells[0].value, 'wrong root level row').toBe(1); expect(aRow.expanded).toBe(false); aRow.expanded = true; fix.detectChanges(); rows = TreeGridFunctions.getAllRows(fix); - expect(rows.length).toBe(5, 'root level row expanding problem'); + expect(rows.length, 'root level row expanding problem').toBe(5); // expand a second level row aRow = treeGrid.gridAPI.get_row_by_index(1); cells = (aRow.cells as QueryList).toArray(); - expect(cells[0].value).toBe(2, 'wrong second level row'); + expect(cells[0].value, 'wrong second level row').toBe(2); expect(aRow.expanded).toBe(false); aRow.expanded = true; fix.detectChanges(); rows = TreeGridFunctions.getAllRows(fix); - expect(rows.length).toBe(7, 'second level row expanding problem'); + expect(rows.length, 'second level row expanding problem').toBe(7); // check third level rows are having the correct values aRow = treeGrid.gridAPI.get_row_by_index(2); cells = (aRow.cells as QueryList).toArray(); - expect(cells[0].value).toBe(3, 'wrong third level row'); + expect(cells[0].value, 'wrong third level row').toBe(3); aRow = treeGrid.gridAPI.get_row_by_index(3); cells = (aRow.cells as QueryList).toArray(); - expect(cells[0].value).toBe(7, 'wrong third level row'); + expect(cells[0].value, 'wrong third level row').toBe(7); // collapse a second level row aRow = treeGrid.gridAPI.get_row_by_index(1); @@ -692,7 +685,7 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { fix.detectChanges(); rows = TreeGridFunctions.getAllRows(fix); - expect(rows.length).toBe(5, 'second level row collapsing problem'); + expect(rows.length, 'second level row collapsing problem').toBe(5); // collapse a root level row aRow = treeGrid.gridAPI.get_row_by_index(0); @@ -700,7 +693,7 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { fix.detectChanges(); rows = TreeGridFunctions.getAllRows(fix); - expect(rows.length).toBe(3, 'root level row collapsing problem'); + expect(rows.length, 'root level row collapsing problem').toBe(3); }); it('should expand/collapse when using \'expandAll\' and \'collapseAll\' methods', () => { @@ -719,19 +712,19 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { expect(rows.length).toBe(3); }); - it('should emit an event when expanding rows (API)', (done) => { + it('should emit an event when expanding rows (API)', async () => { const aRow = treeGrid.getRowByIndex(0); treeGrid.rowToggle.pipe(first()).subscribe((args) => { expect(args.cancel).toBe(false); expect(args.event).toBeUndefined(); expect(args.expanded).toBe(true); expect(args.rowID).toBe(1); - done(); + ; }); aRow.expanded = true; }); - it('should emit an event when collapsing rows (API)', (done) => { + it('should emit an event when collapsing rows (API)', async () => { const aRow = treeGrid.getRowByIndex(0); aRow.expanded = true; fix.detectChanges(); @@ -741,25 +734,25 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { expect(args.event).toBeUndefined(); expect(args.expanded).toBe(false); expect(args.rowID).toBe(1); - done(); + ; }); aRow.expanded = false; }); - it('should emit an event when expanding rows (UI)', (done) => { + it('should emit an event when expanding rows (UI)', async () => { treeGrid.rowToggle.pipe(first()).subscribe((args) => { expect(args.cancel).toBe(false); expect(args.event).toBeDefined(); expect(args.expanded).toBe(true); expect(args.rowID).toBe(1); - done(); + ; }); const rowsDOM = TreeGridFunctions.getAllRows(fix); const indicatorDivDOM = TreeGridFunctions.getExpansionIndicatorDiv(rowsDOM[0]); indicatorDivDOM.triggerEventHandler('click', new Event('click')); }); - it('should emit an event when collapsing rows (UI)', (done) => { + it('should emit an event when collapsing rows (UI)', async () => { const rowsDOM = TreeGridFunctions.getAllRows(fix); const indicatorDivDOM = TreeGridFunctions.getExpansionIndicatorDiv(rowsDOM[0]); indicatorDivDOM.triggerEventHandler('click', new Event('click')); @@ -770,7 +763,7 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { expect(args.event).toBeDefined(); expect(args.expanded).toBe(false); expect(args.rowID).toBe(1); - done(); + ; }); indicatorDivDOM.triggerEventHandler('click', new Event('click')); }); @@ -1156,61 +1149,61 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { const cell = treeGrid.getCellByColumn(1, 'Name'); const overlayContent = GridFunctions.getRowEditingBanner(fix); expect(overlayContent.getBoundingClientRect().height).toBe(0); - expect(treeGrid.rowEditingOverlay.collapsed).toBeTruthy('Edit overlay should not be visible'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should not be visible').toBeTruthy(); cell.editMode = true; fix.detectChanges(); - expect(treeGrid.rowEditingOverlay.collapsed).toBeFalsy('Edit overlay should be visible'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should be visible').toBeFalsy(); expect(overlayContent.getBoundingClientRect().height).toBeGreaterThan(0); expect(overlayContent.getBoundingClientRect().top).toBeLessThan(treeGrid.nativeElement.getBoundingClientRect().top + - treeGrid.nativeElement.getBoundingClientRect().height); + treeGrid.nativeElement.getBoundingClientRect().height); const firstRow = rows[0]; const indicatorDiv = TreeGridFunctions.getExpansionIndicatorDiv(firstRow); indicatorDiv.triggerEventHandler('click', new Event('click')); fix.detectChanges(); - expect(treeGrid.rowEditingOverlay.collapsed).toBeFalsy('Edit overlay should not hide'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should not hide').toBeFalsy(); expect(overlayContent.getBoundingClientRect().height).toBeGreaterThan(0); expect(overlayContent.getBoundingClientRect().top).toBeLessThan(treeGrid.nativeElement.getBoundingClientRect().top + - treeGrid.nativeElement.getBoundingClientRect().height); + treeGrid.nativeElement.getBoundingClientRect().height); indicatorDiv.triggerEventHandler('click', new Event('click')); fix.detectChanges(); - expect(treeGrid.rowEditingOverlay.collapsed).toBeFalsy('Edit overlay should still be shown'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should still be shown').toBeFalsy(); expect(overlayContent.getBoundingClientRect().height).toBeGreaterThan(0); expect(overlayContent.getBoundingClientRect().top).toBeLessThan(treeGrid.nativeElement.getBoundingClientRect().top + - treeGrid.nativeElement.getBoundingClientRect().height); + treeGrid.nativeElement.getBoundingClientRect().height); }); it('Do not hide banner with collapsing a node, using API', () => { const cell = treeGrid.getCellByColumn(1, 'Name'); const overlayContent = GridFunctions.getRowEditingBanner(fix); expect(overlayContent.getBoundingClientRect().height).toBe(0); - expect(treeGrid.rowEditingOverlay.collapsed).toBeTruthy('Edit overlay should not be visible'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should not be visible').toBeTruthy(); cell.editMode = true; fix.detectChanges(); - expect(treeGrid.rowEditingOverlay.collapsed).toBeFalsy('Edit overlay should be visible'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should be visible').toBeFalsy(); expect(overlayContent.getBoundingClientRect().height).toBeGreaterThan(0); expect(overlayContent.getBoundingClientRect().top).toBeLessThan(treeGrid.nativeElement.getBoundingClientRect().top + - treeGrid.nativeElement.getBoundingClientRect().height); + treeGrid.nativeElement.getBoundingClientRect().height); treeGrid.toggleRow(treeGrid.getRowByIndex(0).key); fix.detectChanges(); - expect(treeGrid.rowEditingOverlay.collapsed).toBeFalsy('Edit overlay should not hide'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should not hide').toBeFalsy(); expect(overlayContent.getBoundingClientRect().height).toBeGreaterThan(0); expect(overlayContent.getBoundingClientRect().top).toBeLessThan(treeGrid.nativeElement.getBoundingClientRect().top + - treeGrid.nativeElement.getBoundingClientRect().height); + treeGrid.nativeElement.getBoundingClientRect().height); treeGrid.toggleRow(treeGrid.getRowByIndex(0).key); fix.detectChanges(); - expect(treeGrid.rowEditingOverlay.collapsed).toBeFalsy('Edit overlay should still be shown'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should still be shown').toBeFalsy(); expect(overlayContent.getBoundingClientRect().height).toBeGreaterThan(0); expect(overlayContent.getBoundingClientRect().top).toBeLessThan(treeGrid.nativeElement.getBoundingClientRect().top + - treeGrid.nativeElement.getBoundingClientRect().height); + treeGrid.nativeElement.getBoundingClientRect().height); }); // The following tests were written, @@ -1227,7 +1220,7 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { const cell = treeGrid.getCellByColumn(0, 'Name'); const overlayContent = GridFunctions.getRowEditingBanner(fix); expect(overlayContent.getBoundingClientRect().height).toBe(0); - expect(treeGrid.rowEditingOverlay.collapsed).toBeTruthy('Edit overlay should not be visible'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should not be visible').toBeTruthy(); cell.editMode = true; fix.detectChanges(); @@ -1238,17 +1231,17 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { fix.detectChanges(); expect(overlayContent.getBoundingClientRect().height).toBeGreaterThan(0); - expect(treeGrid.rowEditingOverlay.collapsed).toBeFalsy('Edit overlay should be visible'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should be visible').toBeFalsy(); expect(overlayContent.getBoundingClientRect().top).toBeLessThan(treeGrid.nativeElement.getBoundingClientRect().top + - treeGrid.nativeElement.getBoundingClientRect().height); + treeGrid.nativeElement.getBoundingClientRect().height); indicatorDiv.triggerEventHandler('click', new Event('click')); fix.detectChanges(); expect(overlayContent.getBoundingClientRect().height).toBeGreaterThan(0); - expect(treeGrid.rowEditingOverlay.collapsed).toBeFalsy('Edit overlay should be visible'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should be visible').toBeFalsy(); expect(overlayContent.getBoundingClientRect().top).toBeLessThan(treeGrid.nativeElement.getBoundingClientRect().top + - treeGrid.nativeElement.getBoundingClientRect().height); + treeGrid.nativeElement.getBoundingClientRect().height); }); it('Do not hide parent banner while collapsing the parent node, using API', () => { @@ -1257,7 +1250,7 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { const cell = treeGrid.getCellByColumn(1, 'Name'); const overlayContent = GridFunctions.getRowEditingBanner(fix); expect(overlayContent.getBoundingClientRect().height).toBe(0); - expect(treeGrid.rowEditingOverlay.collapsed).toBeTruthy('Edit overlay should not be visible'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should not be visible').toBeTruthy(); cell.editMode = true; fix.detectChanges(); @@ -1266,17 +1259,17 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { fix.detectChanges(); expect(overlayContent.getBoundingClientRect().height).toBeGreaterThan(0); - expect(treeGrid.rowEditingOverlay.collapsed).toBeFalsy('Edit overlay should be visible'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should be visible').toBeFalsy(); expect(overlayContent.getBoundingClientRect().top).toBeLessThan(treeGrid.nativeElement.getBoundingClientRect().top + - treeGrid.nativeElement.getBoundingClientRect().height); + treeGrid.nativeElement.getBoundingClientRect().height); treeGrid.toggleRow(treeGrid.getRowByIndex(0).key); fix.detectChanges(); expect(overlayContent.getBoundingClientRect().height).toBeGreaterThan(0); - expect(treeGrid.rowEditingOverlay.collapsed).toBeFalsy('Edit overlay should be visible'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should be visible').toBeFalsy(); expect(overlayContent.getBoundingClientRect().top).toBeLessThan(treeGrid.nativeElement.getBoundingClientRect().top + - treeGrid.nativeElement.getBoundingClientRect().height); + treeGrid.nativeElement.getBoundingClientRect().height); }); it('Do not hide banner while collapsing node that is NOT a parent one, using UI', () => { @@ -1286,7 +1279,7 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { const cell = treeGrid.getCellByColumn(9, 'Name'); const overlayContent = GridFunctions.getRowEditingBanner(fix); expect(overlayContent.getBoundingClientRect().height).toBe(0); - expect(treeGrid.rowEditingOverlay.collapsed).toBeTruthy('Edit overlay should not be visible'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should not be visible').toBeTruthy(); cell.editMode = true; fix.detectChanges(); @@ -1297,17 +1290,17 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { fix.detectChanges(); expect(overlayContent.getBoundingClientRect().height).toBeGreaterThan(0); - expect(treeGrid.rowEditingOverlay.collapsed).toBeFalsy('Edit overlay should be visible'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should be visible').toBeFalsy(); expect(overlayContent.getBoundingClientRect().top).toBeLessThan(treeGrid.nativeElement.getBoundingClientRect().top + - treeGrid.nativeElement.getBoundingClientRect().height); + treeGrid.nativeElement.getBoundingClientRect().height); indicatorDiv.triggerEventHandler('click', new Event('click')); fix.detectChanges(); expect(overlayContent.getBoundingClientRect().height).toBeGreaterThan(0); - expect(treeGrid.rowEditingOverlay.collapsed).toBeFalsy('Edit overlay should be visible'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should be visible').toBeFalsy(); expect(overlayContent.getBoundingClientRect().top).toBeLessThan(treeGrid.nativeElement.getBoundingClientRect().top + - treeGrid.nativeElement.getBoundingClientRect().height); + treeGrid.nativeElement.getBoundingClientRect().height); }); it('Do not hide banner while collapsing node that is NOT a parent one, using API', () => { @@ -1316,7 +1309,7 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { const cell = treeGrid.getCellByColumn(9, 'Name'); const overlayContent = GridFunctions.getRowEditingBanner(fix); expect(overlayContent.getBoundingClientRect().height).toBe(0); - expect(treeGrid.rowEditingOverlay.collapsed).toBeTruthy('Edit overlay should not be visible'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should not be visible').toBeTruthy(); cell.editMode = true; fix.detectChanges(); @@ -1325,17 +1318,17 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { fix.detectChanges(); expect(overlayContent.getBoundingClientRect().height).toBeGreaterThan(0); - expect(treeGrid.rowEditingOverlay.collapsed).toBeFalsy('Edit overlay should be visible'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should be visible').toBeFalsy(); expect(overlayContent.getBoundingClientRect().top).toBeLessThan(treeGrid.nativeElement.getBoundingClientRect().top + - treeGrid.nativeElement.getBoundingClientRect().height); + treeGrid.nativeElement.getBoundingClientRect().height); treeGrid.toggleRow(treeGrid.getRowByIndex(0).key); fix.detectChanges(); expect(overlayContent.getBoundingClientRect().height).toBeGreaterThan(0); - expect(treeGrid.rowEditingOverlay.collapsed).toBeFalsy('Edit overlay should be visible'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should be visible').toBeFalsy(); expect(overlayContent.getBoundingClientRect().top).toBeLessThan(treeGrid.nativeElement.getBoundingClientRect().top + - treeGrid.nativeElement.getBoundingClientRect().height); + treeGrid.nativeElement.getBoundingClientRect().height); }); it('Hide banner while collapsing node that is NOT a parent one, but goes outside visible area, using UI', () => { @@ -1358,7 +1351,7 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { let overlayContent = GridFunctions.getRowEditingBanner(fix); expect(overlayContent.getBoundingClientRect().height).toBe(0); - expect(treeGrid.rowEditingOverlay.collapsed).toBeTruthy('Edit overlay should not be visible'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should not be visible').toBeTruthy(); const cell = treeGrid.getCellByColumn(2, 'Name'); cell.editMode = true; fix.detectChanges(); @@ -1368,16 +1361,16 @@ describe('IgxTreeGrid - Expanding / Collapsing #tGrid', () => { indicatorDiv.triggerEventHandler('click', new Event('click')); fix.detectChanges(); - expect(treeGrid.rowEditingOverlay.collapsed).toBeFalsy('Edit overlay should be visible'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should be visible').toBeFalsy(); expect(overlayContent.getBoundingClientRect().top).toBeGreaterThan(treeGrid.nativeElement.getBoundingClientRect().top + - treeGrid.nativeElement.getBoundingClientRect().height); + treeGrid.nativeElement.getBoundingClientRect().height); indicatorDiv.triggerEventHandler('click', new Event('click')); fix.detectChanges(); - expect(treeGrid.rowEditingOverlay.collapsed).toBeFalsy('Edit overlay should be visible but outside of bounds'); + expect(treeGrid.rowEditingOverlay.collapsed, 'Edit overlay should be visible but outside of bounds').toBeFalsy(); expect(overlayContent.getBoundingClientRect().top).toBeLessThan(treeGrid.nativeElement.getBoundingClientRect().top + - treeGrid.nativeElement.getBoundingClientRect().height); + treeGrid.nativeElement.getBoundingClientRect().height); }); }); @@ -1407,7 +1400,7 @@ const verifyGridPager = (fix, rowsCount, firstCellValue, pagerText, buttonsVisib const gridElement: HTMLElement = fix.nativeElement.querySelector('.igx-grid'); expect(grid.getCellByColumn(0, 'ID').value).toMatch(firstCellValue); - expect(grid.rowList.length).toEqual(rowsCount, 'Invalid number of rows initialized'); + expect(grid.rowList.length, 'Invalid number of rows initialized').toEqual(rowsCount); if (pagerText != null) { expect(gridElement.querySelector('igx-page-nav')).toBeDefined(); diff --git a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-filtering.spec.ts b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-filtering.spec.ts index 409b315df20..f42077b92a5 100644 --- a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-filtering.spec.ts +++ b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-filtering.spec.ts @@ -10,6 +10,7 @@ import { UIInteractions } from '../../../test-utils/ui-interactions.spec'; import { SampleTestData } from '../../../test-utils/sample-test-data.spec'; import { By } from '@angular/platform-browser'; import { FilteringStrategy, GridColumnDataType, IgxDateFilteringOperand, IgxNumberFilteringOperand, IgxStringFilteringOperand, TreeGridFilteringStrategy, TreeGridFormattedValuesFilteringStrategy, TreeGridMatchingRecordsOnlyFilteringStrategy } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const IGX_CHECKBOX_LABEL = '.igx-checkbox__label'; @@ -288,12 +289,12 @@ describe('IgxTreeGrid - Filtering actions #tGrid', () => { grid.filter('ID', 0, IgxNumberFilteringOperand.instance().condition('equals')); fix.detectChanges(); let rows = TreeGridFunctions.getAllRows(fix); - expect(rows.length).toEqual(5, 'Wrong rows count'); + expect(rows.length, 'Wrong rows count').toEqual(5); grid.filter('ID', 1, IgxNumberFilteringOperand.instance().condition('equals')); fix.detectChanges(); rows = TreeGridFunctions.getAllRows(fix); - expect(rows.length).toEqual(17, 'Wrong rows count'); + expect(rows.length, 'Wrong rows count').toEqual(17); }); it('\'Blanks\' should be always visible', fakeAsync(() => { @@ -367,14 +368,14 @@ describe('IgxTreeGrid - Filtering actions #tGrid', () => { tick(); let treeItems = GridFunctions.getExcelStyleSearchComponentTreeNodes(fix, null); - expect(treeItems.length).toBe(4, 'incorrect rendered tree node count'); + expect(treeItems.length, 'incorrect rendered tree node count').toBe(4); GridFunctions.clickExcelTreeNodeExpandIcon(fix, 0); fix.detectChanges(); tick(); treeItems = GridFunctions.getExcelStyleSearchComponentTreeNodes(fix, null); - expect(treeItems.length).toBe(6, 'incorrect rendered tree node count'); + expect(treeItems.length, 'incorrect rendered tree node count').toBe(6); })); it('Should change arrow icon on expand', fakeAsync(() => { @@ -384,14 +385,14 @@ describe('IgxTreeGrid - Filtering actions #tGrid', () => { const icon = GridFunctions.getExcelFilterTreeNodeIcon(fix, 0); let iconText = icon.children[0].innerText; - expect(iconText).toBe('chevron_right', 'incorrect rendered icon'); + expect(iconText, 'incorrect rendered icon').toBe('chevron_right'); GridFunctions.clickExcelTreeNodeExpandIcon(fix, 0); fix.detectChanges(); tick(); iconText = icon.children[0].innerText; - expect(iconText).toBe('expand_more', 'incorrect rendered icon'); + expect(iconText, 'incorrect rendered icon').toBe('expand_more'); })); it('Should display Select All item', fakeAsync(() => { @@ -472,7 +473,7 @@ describe('IgxTreeGrid - Filtering actions #tGrid', () => { const searchComponent = GridFunctions.getExcelStyleSearchComponent(fix, null, 'igx-tree-grid'); let treeItems = GridFunctions.getExcelStyleSearchComponentTreeNodes(fix, searchComponent); - expect(treeItems.length).toBe(4, 'incorrect rendered items count'); + expect(treeItems.length, 'incorrect rendered items count').toBe(4); const inputNativeElement = GridFunctions.getExcelStyleSearchComponentInput(fix, searchComponent, 'igx-tree-grid'); UIInteractions.clickAndSendInputElementValue(inputNativeElement, '6', fix); @@ -480,7 +481,7 @@ describe('IgxTreeGrid - Filtering actions #tGrid', () => { tick(); treeItems = GridFunctions.getExcelStyleSearchComponentTreeNodes(fix, searchComponent); - expect(treeItems.length).toBe(2, 'incorrect rendered items count'); + expect(treeItems.length, 'incorrect rendered items count').toBe(2); const clearIcon: any = Array.from(searchComponent.querySelectorAll('igx-icon')) .find((icon: any) => icon.innerText === 'clear'); @@ -489,7 +490,7 @@ describe('IgxTreeGrid - Filtering actions #tGrid', () => { fix.detectChanges(); treeItems = GridFunctions.getExcelStyleSearchComponentTreeNodes(fix, searchComponent); - expect(treeItems.length).toBe(4, 'incorrect rendered items count'); + expect(treeItems.length, 'incorrect rendered items count').toBe(4); })); it('Should filter items and clear filters correctly', fakeAsync(() => { @@ -505,7 +506,7 @@ describe('IgxTreeGrid - Filtering actions #tGrid', () => { let searchComponent = GridFunctions.getExcelStyleSearchComponent(fix, null, 'igx-tree-grid'); let treeItems = GridFunctions.getExcelStyleSearchComponentTreeNodes(fix, searchComponent); - expect(treeItems.length).toBe(4, 'incorrect rendered items count'); + expect(treeItems.length, 'incorrect rendered items count').toBe(4); const inputNativeElement = GridFunctions.getExcelStyleSearchComponentInput(fix, searchComponent, 'igx-tree-grid'); UIInteractions.clickAndSendInputElementValue(inputNativeElement, '8', fix); @@ -513,7 +514,7 @@ describe('IgxTreeGrid - Filtering actions #tGrid', () => { tick(); treeItems = GridFunctions.getExcelStyleSearchComponentTreeNodes(fix, searchComponent); - expect(treeItems.length).toBe(4, 'incorrect rendered items count'); + expect(treeItems.length, 'incorrect rendered items count').toBe(4); GridFunctions.clickApplyExcelStyleFiltering(fix, null, 'igx-tree-grid'); fix.detectChanges(); @@ -538,7 +539,7 @@ describe('IgxTreeGrid - Filtering actions #tGrid', () => { searchComponent = GridFunctions.getExcelStyleSearchComponent(fix, null, 'igx-tree-grid'); treeItems = GridFunctions.getExcelStyleSearchComponentTreeNodes(fix, searchComponent); - expect(treeItems.length).toBe(4, 'incorrect rendered tree node items count'); + expect(treeItems.length, 'incorrect rendered tree node items count').toBe(4); GridFunctions.clickApplyExcelStyleFiltering(fix, null, 'igx-tree-grid'); fix.detectChanges(); @@ -548,7 +549,7 @@ describe('IgxTreeGrid - Filtering actions #tGrid', () => { .map(c => c.nativeElement.innerText) .sort(); - expect(gridCellValues.length).toEqual(18, 'incorrect rendered grid items count'); + expect(gridCellValues.length, 'incorrect rendered grid items count').toEqual(18); })); it('Should update checkboxes after clearing column filters correctly', fakeAsync(() => { @@ -579,7 +580,7 @@ describe('IgxTreeGrid - Filtering actions #tGrid', () => { tick(); let checkboxes: any[] = Array.from(GridFunctions.getExcelStyleFilteringCheckboxes(fix, excelMenu, 'igx-tree-grid')); - checkboxes.forEach(ch => expect(ch.checked).toBe(true, 'incorrect checkbox state')); + checkboxes.forEach(ch => expect(ch.checked, 'incorrect checkbox state').toBe(true)); searchComponent = GridFunctions.getExcelStyleSearchComponent(fix, null, 'igx-tree-grid'); inputNativeElement = GridFunctions.getExcelStyleSearchComponentInput(fix, searchComponent, 'igx-tree-grid'); @@ -588,10 +589,10 @@ describe('IgxTreeGrid - Filtering actions #tGrid', () => { tick(); checkboxes = Array.from(GridFunctions.getExcelStyleFilteringCheckboxes(fix, excelMenu, 'igx-tree-grid')); - const addToFilterCheckbox = checkboxes.splice(1,1)[0]; + const addToFilterCheckbox = checkboxes.splice(1, 1)[0]; - expect(addToFilterCheckbox.checked).toBe(false, 'incorrect checkbox state') - checkboxes.forEach(ch => expect(ch.checked).toBe(true, 'incorrect checkbox state')); + expect(addToFilterCheckbox.checked, 'incorrect checkbox state').toBe(false); + checkboxes.forEach(ch => expect(ch.checked, 'incorrect checkbox state').toBe(true)); })); it('Should filter tree grid correctly', fakeAsync(() => { @@ -607,7 +608,7 @@ describe('IgxTreeGrid - Filtering actions #tGrid', () => { tick(); const treeItems = GridFunctions.getExcelStyleSearchComponentTreeNodes(fix, searchComponent); - expect(treeItems.length).toEqual(2, 'incorrect rendered items count'); + expect(treeItems.length, 'incorrect rendered items count').toEqual(2); GridFunctions.clickApplyExcelStyleFiltering(fix, null, 'igx-tree-grid'); fix.detectChanges(); @@ -751,7 +752,7 @@ describe('IgxTreeGrid - Filtering actions #tGrid', () => { it('Should not throw console error when number column with dataType string is filtered.', fakeAsync(() => { tGrid.columns[0].dataType = GridColumnDataType.String; fix.detectChanges(); - spyOn(console, 'error'); + vi.spyOn(console, 'error'); GridFunctions.clickExcelFilterIcon(fix, 'ID'); fix.detectChanges(); @@ -820,7 +821,7 @@ describe('IgxTreeGrid - Filtering actions #tGrid', () => { tick(); const treeItems = GridFunctions.getExcelStyleSearchComponentTreeNodes(fix, searchComponent); - expect(treeItems.length).toEqual(2, 'incorrect rendered items count'); + expect(treeItems.length, 'incorrect rendered items count').toEqual(2); GridFunctions.clickApplyExcelStyleFiltering(fix, null, 'igx-tree-grid'); fix.detectChanges(); @@ -881,144 +882,142 @@ describe('IgxTreeGrid - Filtering actions #tGrid', () => { expect(treeGrid.data.filter(c => c.Name === newCellValue).length).toBeGreaterThan(0); })); - it('should not remove an edited parent node from the filtered list if it has a child node that meets the criteria', - fakeAsync(() => { - const newCellValue = 'John McJohn'; - treeGrid.filter('Name', 'on', IgxStringFilteringOperand.instance().condition('contains'), true); - tick(); + it('should not remove an edited parent node from the filtered list if it has a child node that meets the criteria', fakeAsync(() => { + const newCellValue = 'John McJohn'; + treeGrid.filter('Name', 'on', IgxStringFilteringOperand.instance().condition('contains'), true); + tick(); - // modify a parent node which has a child that matches the filtering condition - const targetCell = treeGrid.getCellByColumn(0, 'Name'); - targetCell.update(newCellValue); - tick(); - fix.detectChanges(); + // modify a parent node which has a child that matches the filtering condition + const targetCell = treeGrid.getCellByColumn(0, 'Name'); + targetCell.update(newCellValue); + tick(); + fix.detectChanges(); - // verify that the parent node is still in the filtered list - expect(treeGrid.filteredData.filter(p => p.Name === targetCell.value).length).toBeGreaterThan(0); + // verify that the parent node is still in the filtered list + expect(treeGrid.filteredData.filter(p => p.Name === targetCell.value).length).toBeGreaterThan(0); - treeGrid.clearFilter(); - tick(); - fix.detectChanges(); + treeGrid.clearFilter(); + tick(); + fix.detectChanges(); - // verify the changes were preserved after the filtering is removed - expect(treeGrid.data.filter(p => p.Name === targetCell.value).length).toBeGreaterThan(0); - })); + // verify the changes were preserved after the filtering is removed + expect(treeGrid.data.filter(p => p.Name === targetCell.value).length).toBeGreaterThan(0); + })); it(`should remove the parent node from the filtered list if - its only matching child is modified and does not match the filtering condition anymore`, - fakeAsync(() => { - const newCellValue = 'John McJohn'; - const filterValue = 'Langdon'; - treeGrid.filter('Name', filterValue, IgxStringFilteringOperand.instance().condition('contains'), true); - tick(); - - // modify the first child node that meets the filtering condition - const targetCell = treeGrid.getCellByColumn(1, 'Name'); - targetCell.update(newCellValue); - tick(); - fix.detectChanges(); - - // verify that the parent node is no longer in the filtered list - expect(grid.filteredData).toBeFalsy(); - - treeGrid.clearFilter(); - tick(); - fix.detectChanges(); - - // verify that there is a parent which contains the updated child node - const filteredParentNodes = treeGrid.data.filter(n => n.Employees.filter(e => e.Name === newCellValue).length !== 0); - - // if there are any parent nodes in this collection then the changes were preserved - expect(filteredParentNodes.length).toBeGreaterThan(0); - })); - - it('should not remove a parent node from the filtered list if it has at least one child node which matches the filtering condition', - fakeAsync(() => { - const newCellValue = 'Peter Peterson'; - treeGrid.filter('Name', 'h', IgxStringFilteringOperand.instance().condition('contains'), true); - tick(); - - // modify the first child node which meets the filtering condition - const targetCell = treeGrid.getCellByColumn(1, 'Name'); - targetCell.update(newCellValue); - tick(); - fix.detectChanges(); - - // check if the edited child row is removed - expect(treeGrid.filteredData.filter(c => c.Name === newCellValue).length).toBe(0); - - // check if the parent which contains the edited row is not removed - expect(treeGrid.filteredData.filter(p => p.Name === targetCell.row.parent.data.Name).length).toBeGreaterThan(0); - - treeGrid.clearFilter(); - tick(); - fix.detectChanges(); - - // verify that there is a parent which contains the updated child node - const filteredParentNodes = treeGrid.data.filter(n => n.Employees.filter(e => e.Name === newCellValue).length !== 0); - - // if there are any parent nodes in this collection then the changes were preserved - expect(filteredParentNodes.length).toBeGreaterThan(0); - })); - - it('should be able to apply custom filter strategy', fakeAsync(() => { - expect(treeGrid.filterStrategy).toBeDefined(); - treeGrid.filter('Name', 'd', IgxStringFilteringOperand.instance().condition('contains'), true); - tick(); - fix.detectChanges(); - - expect(treeGrid.rowList.length).toBe(9); - - treeGrid.clearFilter(); - fix.detectChanges(); - - const customFilter = new CustomTreeGridFilterStrategy(); - // apply the same filter condition but with custu - treeGrid.filterStrategy = customFilter; - fix.detectChanges(); - - treeGrid.filter('Name', 'd', IgxStringFilteringOperand.instance().condition('contains'), true); - tick(); - fix.detectChanges(); - - expect(treeGrid.rowList.length).toBe(4); - expect(treeGrid.filteredData.map(rec => rec.ID)).toEqual([ 847, 225, 663, 141]); - })); - - it('should display only the filtered records when using TreeGridMatchingRecordsOnlyFilteringStrategy', fakeAsync(() => { - expect(treeGrid.filterStrategy).toBeDefined(); - treeGrid.filter('Name', 'Trevor', IgxStringFilteringOperand.instance().condition('contains'), true); - tick(); - fix.detectChanges(); - - expect(treeGrid.rowList.length).toBe(3); - - const matchingRecordsOnlyStrategy = new TreeGridMatchingRecordsOnlyFilteringStrategy(); - treeGrid.filterStrategy = matchingRecordsOnlyStrategy; - fix.detectChanges(); - - treeGrid.filter('Name', 'Trevor', IgxStringFilteringOperand.instance().condition('contains'), true); - tick(); - fix.detectChanges(); - - expect(treeGrid.rowList.length).toBe(1); - expect(treeGrid.filteredData.map(rec => rec.ID)).toEqual([141]); - })); - }); - class CustomTreeGridFilterStrategy extends FilteringStrategy { + its only matching child is modified and does not match the filtering condition anymore`, fakeAsync(() => { + const newCellValue = 'John McJohn'; + const filterValue = 'Langdon'; + treeGrid.filter('Name', filterValue, IgxStringFilteringOperand.instance().condition('contains'), true); + tick(); - public override filter(data: [], expressionsTree): any[] { - const result = []; - if (!expressionsTree || !expressionsTree.filteringOperands || - expressionsTree.filteringOperands.length === 0 || !data.length) { - return data; - } - data.forEach((rec: any) => { - if (this.matchRecord(rec.data, expressionsTree)) { - result.push(rec); - } - }); - return result; + // modify the first child node that meets the filtering condition + const targetCell = treeGrid.getCellByColumn(1, 'Name'); + targetCell.update(newCellValue); + tick(); + fix.detectChanges(); + + // verify that the parent node is no longer in the filtered list + expect(grid.filteredData).toBeFalsy(); + + treeGrid.clearFilter(); + tick(); + fix.detectChanges(); + + // verify that there is a parent which contains the updated child node + const filteredParentNodes = treeGrid.data.filter(n => n.Employees.filter(e => e.Name === newCellValue).length !== 0); + + // if there are any parent nodes in this collection then the changes were preserved + expect(filteredParentNodes.length).toBeGreaterThan(0); + })); + + it('should not remove a parent node from the filtered list if it has at least one child node which matches the filtering condition', fakeAsync(() => { + const newCellValue = 'Peter Peterson'; + treeGrid.filter('Name', 'h', IgxStringFilteringOperand.instance().condition('contains'), true); + tick(); + + // modify the first child node which meets the filtering condition + const targetCell = treeGrid.getCellByColumn(1, 'Name'); + targetCell.update(newCellValue); + tick(); + fix.detectChanges(); + + // check if the edited child row is removed + expect(treeGrid.filteredData.filter(c => c.Name === newCellValue).length).toBe(0); + + // check if the parent which contains the edited row is not removed + expect(treeGrid.filteredData.filter(p => p.Name === targetCell.row.parent.data.Name).length).toBeGreaterThan(0); + + treeGrid.clearFilter(); + tick(); + fix.detectChanges(); + + // verify that there is a parent which contains the updated child node + const filteredParentNodes = treeGrid.data.filter(n => n.Employees.filter(e => e.Name === newCellValue).length !== 0); + + // if there are any parent nodes in this collection then the changes were preserved + expect(filteredParentNodes.length).toBeGreaterThan(0); + })); + + it('should be able to apply custom filter strategy', fakeAsync(() => { + expect(treeGrid.filterStrategy).toBeDefined(); + treeGrid.filter('Name', 'd', IgxStringFilteringOperand.instance().condition('contains'), true); + tick(); + fix.detectChanges(); + + expect(treeGrid.rowList.length).toBe(9); + + treeGrid.clearFilter(); + fix.detectChanges(); + + const customFilter = new CustomTreeGridFilterStrategy(); + // apply the same filter condition but with custu + treeGrid.filterStrategy = customFilter; + fix.detectChanges(); + + treeGrid.filter('Name', 'd', IgxStringFilteringOperand.instance().condition('contains'), true); + tick(); + fix.detectChanges(); + + expect(treeGrid.rowList.length).toBe(4); + expect(treeGrid.filteredData.map(rec => rec.ID)).toEqual([847, 225, 663, 141]); + })); + + it('should display only the filtered records when using TreeGridMatchingRecordsOnlyFilteringStrategy', fakeAsync(() => { + expect(treeGrid.filterStrategy).toBeDefined(); + treeGrid.filter('Name', 'Trevor', IgxStringFilteringOperand.instance().condition('contains'), true); + tick(); + fix.detectChanges(); + + expect(treeGrid.rowList.length).toBe(3); + + const matchingRecordsOnlyStrategy = new TreeGridMatchingRecordsOnlyFilteringStrategy(); + treeGrid.filterStrategy = matchingRecordsOnlyStrategy; + fix.detectChanges(); + + treeGrid.filter('Name', 'Trevor', IgxStringFilteringOperand.instance().condition('contains'), true); + tick(); + fix.detectChanges(); + + expect(treeGrid.rowList.length).toBe(1); + expect(treeGrid.filteredData.map(rec => rec.ID)).toEqual([141]); + })); + }); + class CustomTreeGridFilterStrategy extends FilteringStrategy { + + public override filter(data: [ + ], expressionsTree): any[] { + const result = []; + if (!expressionsTree || !expressionsTree.filteringOperands || + expressionsTree.filteringOperands.length === 0 || !data.length) { + return data; } + data.forEach((rec: any) => { + if (this.matchRecord(rec.data, expressionsTree)) { + result.push(rec); + } + }); + return result; + } } }); diff --git a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-grouping.pipe.spec.ts b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-grouping.pipe.spec.ts index b000d5af946..4ad6ed2e3a9 100644 --- a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-grouping.pipe.spec.ts +++ b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-grouping.pipe.spec.ts @@ -4,6 +4,7 @@ import { DefaultSortingStrategy, IGroupingExpression } from 'igniteui-angular/co import { SampleTestData } from '../../../test-utils/sample-test-data.spec'; import { IgxTreeGridSimpleComponent, IgxTreeGridPrimaryForeignKeyComponent } from '../../../test-utils/tree-grid-components.spec'; import { IgxTreeGridGroupingPipe } from './tree-grid.grouping.pipe'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('TreeGrid Grouping Pipe', () => { @@ -49,39 +50,35 @@ describe('TreeGrid Grouping Pipe', () => { }); it('groups the data properly by a single number field', () => { - const groupingExpressions = - [groupingExpression('ParentID')]; + const groupingExpressions = [groupingExpression('ParentID')]; transformAndVerify(data, groupedByParentID, groupingExpressions, 'Employees', 'CK'); }); it('groups the data properly by a single string field', () => { - const groupingExpressions = - [groupingExpression('JobTitle')]; + const groupingExpressions = [groupingExpression('JobTitle')]; transformAndVerify(data, groupedByJobTitle, groupingExpressions, 'Employees', 'CK'); }); it('groups the data properly by two fields.', () => { - const groupingExpressions = - [ - groupingExpression('OnPTO', 2), - groupingExpression('JobTitle'), - ]; + const groupingExpressions = [ + groupingExpression('OnPTO', 2), + groupingExpression('JobTitle'), + ]; transformAndVerify(data, groupedByPTODescJobTitle, groupingExpressions, 'Employees', 'CK'); }); it('groups the data properly by three fields.', () => { - const groupingExpressions = - [ - groupingExpression('OnPTO'), - groupingExpression('JobTitle', 2), - groupingExpression('ParentID', 1) - ]; + const groupingExpressions = [ + groupingExpression('OnPTO'), + groupingExpression('JobTitle', 2), + groupingExpression('ParentID', 1) + ]; transformAndVerify(data, groupedByPTOJobDescPID, groupingExpressions, 'Employees', 'CK'); }); it('check result based on \'groupKey\' parameter.', () => { const groupingExpressions = [groupingExpression('OnPTO')]; - const groupKeys = [ null, undefined, 'OOF']; + const groupKeys = [null, undefined, 'OOF']; groupKeys.forEach((groupKey) => { const result = groupPipe.transform(data, groupingExpressions, groupKey, 'CK', null); @@ -93,7 +90,7 @@ describe('TreeGrid Grouping Pipe', () => { it('check result based on \'childDataKey\' parameter.', () => { const groupingExpressions = [groupingExpression('OnPTO')]; - const childDataKeys = [ null, undefined, 'CK']; + const childDataKeys = [null, undefined, 'CK']; const groupKey = 'Group'; childDataKeys.forEach((childDataKey) => { @@ -109,9 +106,9 @@ describe('TreeGrid Grouping Pipe', () => { it('check result with aggregations.', () => { const groupingExpressions = [groupingExpression('OnPTO')]; const aggregations = [{ - field: 'Age', - aggregate: (parent: any, children: any[]) => children.map((c) => c.Age).reduce((min, c) => min < c ? min : c, new Date()) - }]; + field: 'Age', + aggregate: (parent: any, children: any[]) => children.map((c) => c.Age).reduce((min, c) => min < c ? min : c, new Date()) + }]; const result = groupPipe.transform(data, groupingExpressions, 'Group', 'CK', grid, aggregations); expect(result[0]['Age']).toEqual(25); @@ -126,15 +123,14 @@ describe('TreeGrid Grouping Pipe', () => { groupPipe = new IgxTreeGridGroupingPipe(); data = SampleTestData.employeeTreeDataPrimaryForeignKeyExt(); data.forEach(element => { - element['HireDate'].toJSON = function(){ + element['HireDate'].toJSON = function () { return this.toDateString(); }; }); }); it('groups the data properly by a single date field', () => { - const groupingExpressions = - [groupingExpression('HireDate')]; + const groupingExpressions = [groupingExpression('HireDate')]; transformAndVerify(data, groupedByHireDate, groupingExpressions, 'Employees', 'CK', grid); }); }); @@ -152,23 +148,14 @@ describe('TreeGrid Grouping Pipe', () => { }); it('groups the data properly by a single string field with lower case value', () => { - const groupingExpressions = - [groupingExpression('JobTitle')]; + const groupingExpressions = [groupingExpression('JobTitle')]; transformAndVerify(data, groupedByJobTitleCaseSensitive, groupingExpressions, 'Employees', 'CK', grid); }); }); - const groupingExpression = (fieldName: string, dir = 1, ignoreCase = true, strategy = DefaultSortingStrategy.instance()) => ( - {fieldName, dir, ignoreCase, strategy }); - - const transformAndVerify = ( - inputData: any[], - expectedResult: string, - groupingExpressions = [], - groupKey: string, - childDataKey: string, - treeGrid = null, - aggregations = []) => { + const groupingExpression = (fieldName: string, dir = 1, ignoreCase = true, strategy = DefaultSortingStrategy.instance()) => ({ fieldName, dir, ignoreCase, strategy }); + + const transformAndVerify = (inputData: any[], expectedResult: string, groupingExpressions = [], groupKey: string, childDataKey: string, treeGrid = null, aggregations = []) => { const result = groupPipe.transform(inputData, groupingExpressions, groupKey, childDataKey, treeGrid, aggregations); diff --git a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-grouping.spec.ts b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-grouping.spec.ts index 1c76b5d6bc9..ea9bda9bf36 100644 --- a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-grouping.spec.ts +++ b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-grouping.spec.ts @@ -6,6 +6,7 @@ import { IgxTreeGridGroupByAreaComponent } from 'igniteui-angular/grids/tree-gri import { TreeGridFunctions } from '../../../test-utils/tree-grid-functions.spec'; import { IgxTreeGridComponent } from './tree-grid.component'; import { DefaultSortingStrategy } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; describe('IgxTreeGrid', () => { @@ -24,7 +25,7 @@ describe('IgxTreeGrid', () => { let groupByArea: IgxTreeGridGroupByAreaComponent; const DROP_AREA_MSG = 'Drag a column header and drop it here to group by that column.'; - describe(' GroupByArea Standalone', ()=> { + describe(' GroupByArea Standalone', () => { beforeEach(() => { fix = TestBed.createComponent(IgxTreeGridGroupByAreaTestComponent); @@ -53,14 +54,14 @@ describe('IgxTreeGrid', () => { expect(spanElement.innerText).toEqual(DROP_AREA_MSG); })); - it ('has the expected default properties\' values', fakeAsync(() => { + it('has the expected default properties\' values', fakeAsync(() => { expect(groupByArea).toBeDefined(); expect(groupByArea.grid).toEqual(treeGrid); expect(groupByArea.expressions).toEqual([]); - expect(groupByArea.hideGroupedColumns).toBeFalse(); + expect(groupByArea.hideGroupedColumns).toBe(false); expect(groupByArea.dropAreaMessage).toMatch(DROP_AREA_MSG); expect(groupByArea.dropAreaTemplate).toBeUndefined(); - expect(groupByArea.dropAreaVisible).toBeTrue(); + expect(groupByArea.dropAreaVisible).toBe(true); })); it('allows changing the drop area message', fakeAsync(() => { @@ -78,7 +79,7 @@ describe('IgxTreeGrid', () => { fix.detectChanges(); tick(); - expect(groupByArea.hideGroupedColumns).toBeTrue(); + expect(groupByArea.hideGroupedColumns).toBe(true); })); }); @@ -97,14 +98,14 @@ describe('IgxTreeGrid', () => { clearGridSubs(); }); - it ('GroupByArea has the expected properties\' values set', fakeAsync(() => { + it('GroupByArea has the expected properties\' values set', fakeAsync(() => { expect(groupByArea).toBeDefined(); expect(groupByArea.expressions.length).toEqual(2); expect(groupByArea.grid).toEqual(treeGrid); - expect(groupByArea.hideGroupedColumns).toBeFalse(); + expect(groupByArea.hideGroupedColumns).toBe(false); expect(groupByArea.dropAreaMessage).toMatch(DROP_AREA_MSG); expect(groupByArea.dropAreaTemplate).toBeUndefined(); - expect(groupByArea.dropAreaVisible).toBeFalse(); + expect(groupByArea.dropAreaVisible).toBe(false); })); it('is loaded grouped by two fields.', fakeAsync(() => { @@ -132,7 +133,7 @@ describe('IgxTreeGrid', () => { expect(chips[0].id).toEqual('OnPTO'); expect(chips[1].id).toEqual('HireDate'); - groupingExpressions.push({ fieldName: 'JobTitle', dir: 2, ignoreCase: true, strategy: DefaultSortingStrategy.instance()}); + groupingExpressions.push({ fieldName: 'JobTitle', dir: 2, ignoreCase: true, strategy: DefaultSortingStrategy.instance() }); fix.detectChanges(); tick(); @@ -151,41 +152,41 @@ describe('IgxTreeGrid', () => { })); it('group columns stay visible by default', fakeAsync(() => { - expect(treeGrid.getColumnByName('OnPTO').hidden).toBeFalse(); - expect(treeGrid.getColumnByName('HireDate').hidden).toBeFalse(); + expect(treeGrid.getColumnByName('OnPTO').hidden).toBe(false); + expect(treeGrid.getColumnByName('HireDate').hidden).toBe(false); })); it('keeps the group columns visible by default', fakeAsync(() => { - expect(treeGrid.getColumnByName('HireDate').hidden).toBeFalse(); + expect(treeGrid.getColumnByName('HireDate').hidden).toBe(false); groupingExpressions.pop(); groupByArea.expressions = [...groupingExpressions]; fix.detectChanges(); tick(); - expect(treeGrid.getColumnByName('HireDate').hidden).toBeFalse(); + expect(treeGrid.getColumnByName('HireDate').hidden).toBe(false); })); it('hides/shows the grouped by column when hideGroupedColumns=true', fakeAsync(() => { groupByArea.hideGroupedColumns = true; fix.detectChanges(); - expect(treeGrid.getColumnByName('HireDate').hidden).toBeTrue(); + expect(treeGrid.getColumnByName('HireDate').hidden).toBe(true); groupingExpressions.pop(); groupByArea.expressions = [...groupingExpressions]; fix.detectChanges(); tick(); - expect(treeGrid.getColumnByName('HireDate').hidden).toBeFalse(); + expect(treeGrid.getColumnByName('HireDate').hidden).toBe(false); - groupingExpressions.push({ fieldName: 'JobTitle', dir: 2, ignoreCase: true, strategy: DefaultSortingStrategy.instance()}); + groupingExpressions.push({ fieldName: 'JobTitle', dir: 2, ignoreCase: true, strategy: DefaultSortingStrategy.instance() }); groupByArea.expressions = [...groupingExpressions]; fix.detectChanges(); tick(); - expect(treeGrid.getColumnByName('JobTitle').hidden).toBeTrue(); + expect(treeGrid.getColumnByName('JobTitle').hidden).toBe(true); })); it('shows aggregated values in parent records properly', fakeAsync(() => { @@ -193,10 +194,10 @@ describe('IgxTreeGrid', () => { expect(treeGrid.getCellByColumn(1, 'HireDate').value).toBeUndefined(); const aggregations = [{ - field: 'HireDate', - aggregate: (parent: any, children: any[]) => children.map((c) => c.HireDate) - .reduce((min, c) => min < c ? min : c, new Date()) - }]; + field: 'HireDate', + aggregate: (parent: any, children: any[]) => children.map((c) => c.HireDate) + .reduce((min, c) => min < c ? min : c, new Date()) + }]; fix.componentInstance.aggregations = aggregations; fix.detectChanges(); diff --git a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-indentation.spec.ts b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-indentation.spec.ts index a26d7e2490b..2a2e24139e0 100644 --- a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-indentation.spec.ts +++ b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-indentation.spec.ts @@ -7,6 +7,7 @@ import { UIInteractions } from '../../../test-utils/ui-interactions.spec'; import { DropPosition } from 'igniteui-angular/grids/core'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxNumberFilteringOperand, SortingDirection } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach } from 'vitest'; const GRID_RESIZE_CLASS = '.igx-grid-th__resize-handle'; @@ -84,7 +85,7 @@ describe('IgxTreeGrid - Indentation #tGrid', () => { TreeGridFunctions.verifyRowIndentationLevel(treeGrid.getRowByIndex(4), rows[4], 0); })); - it('should persist the indentation on all pages when using paging', fakeAsync(() => { + it('should persist the indentation on all pages when using paging', fakeAsync(() => { fix.componentInstance.paging = true; fix.detectChanges(); @@ -94,7 +95,7 @@ describe('IgxTreeGrid - Indentation #tGrid', () => { // Verify page 1 let rows = TreeGridFunctions.sortElementsVertically(TreeGridFunctions.getAllRows(fix)); - expect(rows.length).toBe(4, 'Incorrect number of rows on page 1.'); + expect(rows.length, 'Incorrect number of rows on page 1.').toBe(4); TreeGridFunctions.verifyRowIndentationLevel(treeGrid.getRowByIndex(0), rows[0], 0); TreeGridFunctions.verifyRowIndentationLevel(treeGrid.getRowByIndex(1), rows[1], 1); TreeGridFunctions.verifyRowIndentationLevel(treeGrid.getRowByIndex(2), rows[2], 1); @@ -106,7 +107,7 @@ describe('IgxTreeGrid - Indentation #tGrid', () => { // Verify page 2 rows = TreeGridFunctions.sortElementsVertically(TreeGridFunctions.getAllRows(fix)); - expect(rows.length).toBe(4, 'Incorrect number of rows on page 2.'); + expect(rows.length, 'Incorrect number of rows on page 2.').toBe(4); TreeGridFunctions.verifyRowIndentationLevel(treeGrid.getRowByIndex(0), rows[0], 2); TreeGridFunctions.verifyRowIndentationLevel(treeGrid.getRowByIndex(1), rows[1], 2); TreeGridFunctions.verifyRowIndentationLevel(treeGrid.getRowByIndex(2), rows[2], 2); @@ -118,7 +119,7 @@ describe('IgxTreeGrid - Indentation #tGrid', () => { // Verify page 3 rows = TreeGridFunctions.sortElementsVertically(TreeGridFunctions.getAllRows(fix)); - expect(rows.length).toBe(2, 'Incorrect number of rows on page 3.'); + expect(rows.length, 'Incorrect number of rows on page 3.').toBe(2); TreeGridFunctions.verifyRowIndentationLevel(treeGrid.getRowByIndex(0), rows[0], 0); TreeGridFunctions.verifyRowIndentationLevel(treeGrid.getRowByIndex(1), rows[1], 1); })); @@ -255,7 +256,7 @@ describe('IgxTreeGrid - Indentation #tGrid', () => { // Verify page 1 let rows = TreeGridFunctions.sortElementsVertically(TreeGridFunctions.getAllRows(fix)); - expect(rows.length).toBe(3, 'Incorrect number of rows on page 1.'); + expect(rows.length, 'Incorrect number of rows on page 1.').toBe(3); TreeGridFunctions.verifyRowIndentationLevel(treeGrid.getRowByIndex(0), rows[0], 0); TreeGridFunctions.verifyRowIndentationLevel(treeGrid.getRowByIndex(1), rows[1], 1); TreeGridFunctions.verifyRowIndentationLevel(treeGrid.getRowByIndex(2), rows[2], 2); @@ -266,7 +267,7 @@ describe('IgxTreeGrid - Indentation #tGrid', () => { // Verify page 2 rows = TreeGridFunctions.sortElementsVertically(TreeGridFunctions.getAllRows(fix)); - expect(rows.length).toBe(3, 'Incorrect number of rows on page 2.'); + expect(rows.length, 'Incorrect number of rows on page 2.').toBe(3); TreeGridFunctions.verifyRowIndentationLevel(treeGrid.getRowByIndex(0), rows[0], 2); TreeGridFunctions.verifyRowIndentationLevel(treeGrid.getRowByIndex(1), rows[1], 1); TreeGridFunctions.verifyRowIndentationLevel(treeGrid.getRowByIndex(2), rows[2], 0); @@ -277,7 +278,7 @@ describe('IgxTreeGrid - Indentation #tGrid', () => { // Verify page 3 rows = TreeGridFunctions.sortElementsVertically(TreeGridFunctions.getAllRows(fix)); - expect(rows.length).toBe(2, 'Incorrect number of rows on page 3.'); + expect(rows.length, 'Incorrect number of rows on page 3.').toBe(2); TreeGridFunctions.verifyRowIndentationLevel(treeGrid.getRowByIndex(0), rows[0], 0); TreeGridFunctions.verifyRowIndentationLevel(treeGrid.getRowByIndex(1), rows[1], 1); })); @@ -345,8 +346,7 @@ const verifyCellsContentAlignment = (fix, columnKey, shouldBeLeftAligned: boolea const cells = TreeGridFunctions.getColumnCells(fix, columnKey); if (shouldBeLeftAligned) { cells.forEach((cell) => { - expect(cell.nativeElement.classList.contains(NUMBER_CELL_CSS_CLASS)) - .toBe(false, 'cell has number css class'); + expect(cell.nativeElement.classList.contains(NUMBER_CELL_CSS_CLASS), 'cell has number css class').toBe(false); // TreeCells have either 2 or 3 div children (2 for root rows and 3 for child rows). const cellDivChildren = cell.queryAll(By.css('div')); @@ -354,8 +354,7 @@ const verifyCellsContentAlignment = (fix, columnKey, shouldBeLeftAligned: boolea }); } else { // Should be right-aligned cells.forEach((cell) => { - expect(cell.nativeElement.classList.contains(NUMBER_CELL_CSS_CLASS)) - .toBe(true, 'cell does not have number css class'); + expect(cell.nativeElement.classList.contains(NUMBER_CELL_CSS_CLASS), 'cell does not have number css class').toBe(true); // NormalCells have 1 div child (no div for indentation and no div for expander). const cellDivChildren = cell.queryAll(By.css('div')); diff --git a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-integration.spec.ts b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-integration.spec.ts index 592925bec61..04b689fdcb1 100644 --- a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-integration.spec.ts +++ b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-integration.spec.ts @@ -1,14 +1,7 @@ import { TestBed, ComponentFixture, waitForAsync, fakeAsync, tick } from '@angular/core/testing'; import { DebugElement } from '@angular/core'; import { IgxTreeGridComponent } from './tree-grid.component'; -import { - IgxTreeGridSimpleComponent, IgxTreeGridPrimaryForeignKeyComponent, - IgxTreeGridStringTreeColumnComponent, IgxTreeGridDateTreeColumnComponent, IgxTreeGridBooleanTreeColumnComponent, - IgxTreeGridRowEditingComponent, IgxTreeGridMultiColHeadersComponent, - IgxTreeGridRowEditingTransactionComponent, - IgxTreeGridRowEditingHierarchicalDSTransactionComponent, - IgxTreeGridRowPinningComponent -} from '../../../test-utils/tree-grid-components.spec'; +import { IgxTreeGridSimpleComponent, IgxTreeGridPrimaryForeignKeyComponent, IgxTreeGridStringTreeColumnComponent, IgxTreeGridDateTreeColumnComponent, IgxTreeGridBooleanTreeColumnComponent, IgxTreeGridRowEditingComponent, IgxTreeGridMultiColHeadersComponent, IgxTreeGridRowEditingTransactionComponent, IgxTreeGridRowEditingHierarchicalDSTransactionComponent, IgxTreeGridRowPinningComponent } from '../../../test-utils/tree-grid-components.spec'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { TreeGridFunctions } from '../../../test-utils/tree-grid-functions.spec'; import { UIInteractions, wait } from '../../../test-utils/ui-interactions.spec'; @@ -17,6 +10,7 @@ import { CellType, DropPosition, IgxTreeGridRow } from 'igniteui-angular/grids/c import { IgxTreeGridRowComponent } from './tree-grid-row.component'; import { IgxGridTransaction } from 'igniteui-angular/grids/core'; import { HierarchicalTransaction, IgxHierarchicalTransactionService, IgxNumberFilteringOperand, IgxStringFilteringOperand, SortingDirection, TransactionType } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const CSS_CLASS_BANNER = 'igx-banner'; const CSS_CLASS_ROW_EDITED = 'igx-grid__tr--edited'; @@ -160,14 +154,14 @@ describe('IgxTreeGrid - Integration #tGrid', () => { const headerCell = TreeGridFunctions.getHeaderCell(fix, 'ID'); const column = treeGrid.columnList.filter(c => c.field === 'ID')[0]; - expect(headerCell.nativeElement.getBoundingClientRect().width).toBe(225, 'incorrect column width'); + expect(headerCell.nativeElement.getBoundingClientRect().width, 'incorrect column width').toBe(225); expect(parseInt(column.width, 10)).toBe(225); // API autosizing column.autosize(); fix.detectChanges(); - expect(headerCell.nativeElement.getBoundingClientRect().width).toBe(148, 'incorrect headerCell width'); + expect(headerCell.nativeElement.getBoundingClientRect().width, 'incorrect headerCell width').toBe(148); expect(parseInt(column.width, 10)).toBe(148); }); @@ -177,7 +171,7 @@ describe('IgxTreeGrid - Integration #tGrid', () => { column.resizable = true; treeGrid.cdr.detectChanges(); - expect(headerCell.nativeElement.getBoundingClientRect().width).toBe(225, 'incorrect column width'); + expect(headerCell.nativeElement.getBoundingClientRect().width, 'incorrect column width').toBe(225); expect(parseInt(column.width, 10)).toBe(225); // UI autosizing @@ -185,7 +179,7 @@ describe('IgxTreeGrid - Integration #tGrid', () => { UIInteractions.simulateMouseEvent('dblclick', resizer, 225, 5); fix.detectChanges(); - expect(headerCell.nativeElement.getBoundingClientRect().width).toBe(148, 'incorrect headerCell width'); + expect(headerCell.nativeElement.getBoundingClientRect().width, 'incorrect headerCell width').toBe(148); expect(parseInt(column.width, 10)).toBe(148); }); }); @@ -261,7 +255,7 @@ describe('IgxTreeGrid - Integration #tGrid', () => { "JobTitle": "CEO", "Age": 52 }, - ] + ]; expect(treeGrid.flatData).toEqual(expectedFlatData); }); @@ -344,14 +338,14 @@ describe('IgxTreeGrid - Integration #tGrid', () => { const headerCell = TreeGridFunctions.getHeaderCell(fix, 'ID'); const column = treeGrid.columnList.filter(c => c.field === 'ID')[0]; - expect(headerCell.nativeElement.getBoundingClientRect().width).toBe(180, 'incorrect column width'); + expect(headerCell.nativeElement.getBoundingClientRect().width, 'incorrect column width').toBe(180); expect(parseInt(column.width, 10)).toBe(180); // API autosizing column.autosize(); fix.detectChanges(); - expect(headerCell.nativeElement.getBoundingClientRect().width).toBe(135, 'incorrect headerCell width'); + expect(headerCell.nativeElement.getBoundingClientRect().width, 'incorrect headerCell width').toBe(135); expect(parseInt(column.width, 10)).toBe(135); }); @@ -361,7 +355,7 @@ describe('IgxTreeGrid - Integration #tGrid', () => { column.resizable = true; treeGrid.cdr.detectChanges(); - expect(headerCell.nativeElement.getBoundingClientRect().width).toBe(180, 'incorrect column width'); + expect(headerCell.nativeElement.getBoundingClientRect().width, 'incorrect column width').toBe(180); expect(parseInt(column.width, 10)).toBe(180); // UI autosizing @@ -369,7 +363,7 @@ describe('IgxTreeGrid - Integration #tGrid', () => { UIInteractions.simulateMouseEvent('dblclick', resizer, 225, 5); fix.detectChanges(); - expect(headerCell.nativeElement.getBoundingClientRect().width).toBe(135, 'incorrect headerCell width'); + expect(headerCell.nativeElement.getBoundingClientRect().width, 'incorrect headerCell width').toBe(135); expect(parseInt(column.width, 10)).toBe(135); }); }); @@ -423,7 +417,7 @@ describe('IgxTreeGrid - Integration #tGrid', () => { fix.detectChanges(); // const editRow = cell.row.nativeElement; - const editRow = grid.gridAPI.get_row_by_index(1).nativeElement; + const editRow = grid.gridAPI.get_row_by_index(1).nativeElement; const banner = fix.debugElement.query(By.css('.' + CSS_CLASS_BANNER)).nativeElement; const bannerTop = banner.getBoundingClientRect().top; @@ -448,7 +442,7 @@ describe('IgxTreeGrid - Integration #tGrid', () => { fix.detectChanges(); // const editRow = cell.row.nativeElement; - const editRow = grid.gridAPI.get_row_by_index(2).nativeElement; + const editRow = grid.gridAPI.get_row_by_index(2).nativeElement; const banner = fix.debugElement.query(By.css('.' + CSS_CLASS_BANNER)).nativeElement; const bannerBottom = banner.getBoundingClientRect().bottom; @@ -470,7 +464,7 @@ describe('IgxTreeGrid - Integration #tGrid', () => { fix.detectChanges(); // const editRow = cell.row.nativeElement; - const editRow = grid.gridAPI.get_row_by_index(grid.rowList.length - 1).nativeElement; + const editRow = grid.gridAPI.get_row_by_index(grid.rowList.length - 1).nativeElement; const banner = fix.debugElement.query(By.css('.' + CSS_CLASS_BANNER)).nativeElement; const bannerBottom = banner.getBoundingClientRect().bottom; @@ -584,14 +578,17 @@ describe('IgxTreeGrid - Integration #tGrid', () => { const cancelBtn = fix.debugElement.queryAll(By.css('.igx-button--flat'))[0] as DebugElement; const doneBtn = fix.debugElement.queryAll(By.css('.igx-button--flat'))[1]; - spyOn(cancelBtn.nativeElement, 'focus').and.callThrough(); - spyOn(grid.rowEditTabs.first, 'move').and.callThrough(); - spyOn(grid.rowEditTabs.last, 'move').and.callThrough(); + vi.spyOn(cancelBtn.nativeElement, 'focus'); + vi.spyOn(grid.rowEditTabs.first, 'move'); + vi.spyOn(grid.rowEditTabs.last, 'move'); await TreeGridFunctions.moveGridCellWithTab(fix, grid.gridAPI.get_cell_by_index(2, 'Age')); expect(cancelBtn.nativeElement.focus).toHaveBeenCalled(); - const mockObj = jasmine.createSpyObj('mockObj', ['stopPropagation', 'preventDefault']); + const mockObj = { + stopPropagation: vi.fn().mockName("mockObj.stopPropagation"), + preventDefault: vi.fn().mockName("mockObj.preventDefault") + }; cancelBtn.triggerEventHandler('keydown.tab', mockObj); await wait(30); fix.detectChanges(); @@ -678,7 +675,7 @@ describe('IgxTreeGrid - Integration #tGrid', () => { tick(100); expect(cell.editMode).toBe(true); - expect(document.activeElement.nodeName).toEqual('INPUT') + expect(document.activeElement.nodeName).toEqual('INPUT'); expect((document.activeElement as HTMLInputElement).value).toBe('John Winchester'); expect((document.activeElement as HTMLInputElement).selectionStart).toEqual(0); expect((document.activeElement as HTMLInputElement).selectionEnd).toEqual(15); @@ -895,7 +892,7 @@ describe('IgxTreeGrid - Integration #tGrid', () => { treeGrid = fix.componentInstance.treeGrid; const initialDataLength = treeGrid.data.length; const trans = treeGrid.transactions; - spyOn(trans, 'add').and.callThrough(); + vi.spyOn(trans, 'add'); const addedRowId_1 = treeGrid.rowList.length; const newRow = { @@ -1030,7 +1027,7 @@ describe('IgxTreeGrid - Integration #tGrid', () => { treeGrid.batchEditing = true; fix.detectChanges(); const trans = treeGrid.transactions; - spyOn(trans, 'add').and.callThrough(); + vi.spyOn(trans, 'add'); treeGrid.foreignKey = 'ParentID'; const addedRowId = treeGrid.data.length; @@ -1079,7 +1076,7 @@ describe('IgxTreeGrid - Integration #tGrid', () => { fix.detectChanges(); treeGrid = fix.componentInstance.treeGrid; const trans = treeGrid.transactions; - spyOn(trans, 'add').and.callThrough(); + vi.spyOn(trans, 'add'); const parentRow = treeGrid.getRowByIndex(0); const addedRowId = treeGrid.rowList.length; @@ -1133,7 +1130,7 @@ describe('IgxTreeGrid - Integration #tGrid', () => { treeGrid.batchEditing = true; fix.detectChanges(); const trans = treeGrid.transactions; - spyOn(trans, 'add').and.callThrough(); + vi.spyOn(trans, 'add'); treeGrid.foreignKey = 'ParentID'; const addedRowId = treeGrid.data.length; @@ -1178,7 +1175,7 @@ describe('IgxTreeGrid - Integration #tGrid', () => { fix.detectChanges(); treeGrid = fix.componentInstance.treeGrid; const trans = treeGrid.transactions; - spyOn(trans, 'add').and.callThrough(); + vi.spyOn(trans, 'add'); const parentRow = treeGrid.getRowByIndex(1); const addedRowId = treeGrid.rowList.length; @@ -1256,7 +1253,7 @@ describe('IgxTreeGrid - Integration #tGrid', () => { grid.cascadeOnDelete = false; fixture.detectChanges(); - const row = {ID: 2, ParentID: 1, Name: 'Gilberto Todd', JobTitle: 'Director', Age: 41}; + const row = { ID: 2, ParentID: 1, Name: 'Gilberto Todd', JobTitle: 'Director', Age: 41 }; expect(grid.getRowData(2)).toEqual(row); grid.sort({ fieldName: 'Age', dir: SortingDirection.Desc, ignoreCase: true }); @@ -1271,7 +1268,7 @@ describe('IgxTreeGrid - Integration #tGrid', () => { expect(grid.getRowData(2)).toEqual(row); expect(grid.getRowData(11)).toEqual({}); - const newRow = {ID: 11, ParentID: 1, Name: 'Joe Peterson', JobTitle: 'Manager', Age: 37}; + const newRow = { ID: 11, ParentID: 1, Name: 'Joe Peterson', JobTitle: 'Manager', Age: 37 }; grid.addRow(newRow); fixture.detectChanges(); @@ -1363,7 +1360,7 @@ describe('IgxTreeGrid - Integration #tGrid', () => { await wait(); UIInteractions.simulatePointerEvent('pointermove', header, 420, 90); UIInteractions.simulatePointerEvent('pointerup', header, 420, 90); - await wait() + await wait(); fix.detectChanges(); TreeGridFunctions.verifyTreeColumnInMultiColHeaders(fix, 'Name', 4); @@ -1761,9 +1758,9 @@ describe('IgxTreeGrid - Integration #tGrid', () => { const selectedRange = treeGrid.getSelectedData(); expect(selectedRange).toEqual([ - {ID: 147, Name: 'John Winchester'}, - {ID: 147, Name: 'John Winchester'}, - {ID: 475, Name: 'Michael Langdon'}, + { ID: 147, Name: 'John Winchester' }, + { ID: 147, Name: 'John Winchester' }, + { ID: 475, Name: 'Michael Langdon' }, ]); }); @@ -1796,20 +1793,20 @@ describe('IgxTreeGrid - Integration #tGrid', () => { // Check getRowByIndex expanded, children and parent members expect(firstRow.expanded).toBe(true); expect(firstRow.hasChildren).toBe(true); - expect(firstRow.children[0].hasChildren).toBeFalse(); + expect(firstRow.children[0].hasChildren).toBe(false); // children.length equals the filtered our chidlren! expect(firstRow.children.length).toEqual(1); - expect(firstRow.children[0] instanceof IgxTreeGridRow).toBeTrue(); - expect(firstRow.children[0].parent instanceof IgxTreeGridRow).toBeTrue(); + expect(firstRow.children[0] instanceof IgxTreeGridRow).toBe(true); + expect(firstRow.children[0].parent instanceof IgxTreeGridRow).toBe(true); expect(firstRow.children[0].parent.key).toBe(firstRow.key); expect(treeGrid.getRowByIndex(1).parent.key).toEqual(147); firstRow.expanded = false; expect(firstRow.expanded).toBe(false); - expect(firstRow.pinned).toBeFalse(); + expect(firstRow.pinned).toBe(false); firstRow.pinned = true; - expect(firstRow.pinned).toBeTrue(); + expect(firstRow.pinned).toBe(true); }); it('should delete pinned row without errors', () => { @@ -1818,7 +1815,7 @@ describe('IgxTreeGrid - Integration #tGrid', () => { const firstRow = treeGrid.pinnedRows[0]; expect(firstRow.isRoot).toBe(true); - expect(firstRow.pinned).toBeTrue(); + expect(firstRow.pinned).toBe(true); expect(firstRow.data.ID).toEqual(147); treeGrid.deleteRowById(147); diff --git a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-keyBoardNav.spec.ts b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-keyBoardNav.spec.ts index 26a57acba1e..6334d891f30 100644 --- a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-keyBoardNav.spec.ts +++ b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-keyBoardNav.spec.ts @@ -9,6 +9,7 @@ import { GridFunctions } from '../../../test-utils/grid-functions.spec'; import { DebugElement } from '@angular/core'; import { firstValueFrom } from 'rxjs'; import { CellType } from 'igniteui-angular/grids/core'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; const DEBOUNCETIME = 30; @@ -36,7 +37,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { }); it('should navigate with arrow keys', () => { - spyOn(treeGrid.selected, 'emit').and.callThrough(); + vi.spyOn(treeGrid.selected, 'emit'); let cell = treeGrid.gridAPI.get_cell_by_index(0, 'ID'); UIInteractions.simulateClickAndSelectEvent(cell); @@ -71,7 +72,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { }); it('should move to the top/bottom cell when navigate with Ctrl + arrow Up/Down keys', () => { - spyOn(treeGrid.selected, 'emit').and.callThrough(); + vi.spyOn(treeGrid.selected, 'emit'); let cell = treeGrid.gridAPI.get_cell_by_index(5, 'ID'); UIInteractions.simulateClickAndSelectEvent(cell); fix.detectChanges(); @@ -105,7 +106,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { }); it('should move to the leftmost/rightmost cell when navigate with Ctrl + arrow Left/Right keys', () => { - spyOn(treeGrid.selected, 'emit').and.callThrough(); + vi.spyOn(treeGrid.selected, 'emit'); let cell = treeGrid.gridAPI.get_cell_by_index(0, 'HireDate'); UIInteractions.simulateClickAndSelectEvent(cell); fix.detectChanges(); @@ -139,7 +140,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { }); it('should move to the top left/bottom right cell when navigate with Ctrl + Home/End keys', () => { - spyOn(treeGrid.selected, 'emit').and.callThrough(); + vi.spyOn(treeGrid.selected, 'emit'); let cell = treeGrid.gridAPI.get_cell_by_index(4, 'Name'); UIInteractions.simulateClickAndSelectEvent(cell); fix.detectChanges(); @@ -173,7 +174,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { }); it('should expand/collapse row when Alt + arrow Left/Right keys are pressed', () => { - spyOn(treeGrid.rowToggle, 'emit').and.callThrough(); + vi.spyOn(treeGrid.rowToggle, 'emit'); const cell = treeGrid.gridAPI.get_cell_by_index(0, 'ID'); let rows = TreeGridFunctions.getAllRows(fix); expect(rows.length).toBe(10); @@ -221,7 +222,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { }); it('should expand/collapse row when Alt + arrow Up/Down keys are pressed', () => { - spyOn(treeGrid.rowToggle, 'emit').and.callThrough(); + vi.spyOn(treeGrid.rowToggle, 'emit'); const cell = treeGrid.gridAPI.get_cell_by_index(3, 'HireDate'); let rows = TreeGridFunctions.getAllRows(fix); expect(rows.length).toBe(10); @@ -269,7 +270,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { }); it('should not change selection when press Alt + arrow Left/Right keys on a cell in a row without children', () => { - spyOn(treeGrid.rowToggle, 'emit').and.callThrough(); + vi.spyOn(treeGrid.rowToggle, 'emit'); const cell = treeGrid.gridAPI.get_cell_by_index(1, 'Name'); let rows = TreeGridFunctions.getAllRows(fix); expect(rows.length).toBe(10); @@ -408,7 +409,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { }); it('should navigate with arrow Up and Down keys', async () => { - spyOn(treeGrid.selected, 'emit').and.callThrough(); + vi.spyOn(treeGrid.selected, 'emit'); const firstCell: CellType = treeGrid.gridAPI.get_cell_by_index(5, 'ID'); UIInteractions.simulateClickAndSelectEvent(firstCell); fix.detectChanges(); @@ -443,7 +444,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { it('should navigate with arrow Left and Right', async () => { const firstCell = treeGrid.gridAPI.get_cell_by_index(3, treeColumns[0]); - spyOn(treeGrid.selected, 'emit').and.callThrough(); + vi.spyOn(treeGrid.selected, 'emit'); UIInteractions.simulateClickAndSelectEvent(firstCell); fix.detectChanges(); @@ -491,7 +492,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { }); it('should move to the top/bottom cell when navigate with Ctrl + arrow Up/Down', async () => { - spyOn(treeGrid.selected, 'emit').and.callThrough(); + vi.spyOn(treeGrid.selected, 'emit'); let cell = treeGrid.gridAPI.get_cell_by_index(1, 'Name'); UIInteractions.simulateClickAndSelectEvent(cell); @@ -518,7 +519,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { }); it('should move to the leftmost/rightmost cell when navigate with Ctrl + arrow Left/Right keys', async () => { - spyOn(treeGrid.selected, 'emit').and.callThrough(); + vi.spyOn(treeGrid.selected, 'emit'); let cell = treeGrid.gridAPI.get_cell_by_index(4, treeColumns[1]); UIInteractions.simulateClickAndSelectEvent(cell); @@ -552,7 +553,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { }); it('should move to the top left/bottom right cell when navigate with Ctrl + Home/End keys', async () => { - spyOn(treeGrid.selected, 'emit').and.callThrough(); + vi.spyOn(treeGrid.selected, 'emit'); let cell = treeGrid.gridAPI.get_cell_by_index(2, treeColumns[2]); UIInteractions.simulateClickAndSelectEvent(cell); @@ -669,7 +670,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { newCell = treeGrid.gridAPI.get_cell_by_index(6, treeColumns[0]); TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, newCell); expect(newCell.editMode).toBe(true); - expect( treeGrid.verticalScrollContainer.getScroll().scrollTop).toBeGreaterThan(0); + expect(treeGrid.verticalScrollContainer.getScroll().scrollTop).toBeGreaterThan(0); UIInteractions.triggerEventHandlerKeyDown('Tab', gridContent, false, true); await wait(DEBOUNCETIME * 2); @@ -709,7 +710,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, lastCell); expect(treeGrid.headerContainer.getScroll().scrollLeft).toBeGreaterThan(0); - for (let i = 4; i > 0 ; i--) { + for (let i = 4; i > 0; i--) { let cell = treeGrid.gridAPI.get_cell_by_index(3, columns[i]); UIInteractions.triggerEventHandlerKeyDown('ArrowLeft', gridContent); await wait(DEBOUNCETIME); diff --git a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-multi-cell-selection.spec.ts b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-multi-cell-selection.spec.ts index ea22664eb2c..d946435c792 100644 --- a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-multi-cell-selection.spec.ts +++ b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-multi-cell-selection.spec.ts @@ -1,16 +1,12 @@ import { TestBed, waitForAsync } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { - IgxTreeGridSelectionKeyComponent, - IgxTreeGridSelectionComponent, - IgxTreeGridSelectionWithTransactionComponent, - IgxTreeGridFKeySelectionWithTransactionComponent -} from '../../../test-utils/tree-grid-components.spec'; +import { IgxTreeGridSelectionKeyComponent, IgxTreeGridSelectionComponent, IgxTreeGridSelectionWithTransactionComponent, IgxTreeGridFKeySelectionWithTransactionComponent } from '../../../test-utils/tree-grid-components.spec'; import { clearGridSubs, setupGridScrollDetection } from '../../../test-utils/helper-utils.spec'; import { UIInteractions, wait } from '../../../test-utils/ui-interactions.spec'; import { GridSelectionFunctions, GridSummaryFunctions, GridFunctions } from '../../../test-utils/grid-functions.spec'; import { GridSelectionMode } from 'igniteui-angular/grids/core'; import { IgxStringFilteringOperand } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; describe('IgxTreeGrid - Multi Cell selection #tGrid', () => { @@ -56,7 +52,7 @@ describe('IgxTreeGrid - Multi Cell selection #tGrid', () => { }); it('Should not be possible to select a range when change cellSelection to none', () => { - const rangeChangeSpy = spyOn(treeGrid.rangeSelected, 'emit').and.callThrough(); + const rangeChangeSpy = vi.spyOn(treeGrid.rangeSelected, 'emit'); const startCell = treeGrid.gridAPI.get_cell_by_index(0, 'ID'); const endCell = treeGrid.gridAPI.get_cell_by_index(2, 'ID'); @@ -86,7 +82,7 @@ describe('IgxTreeGrid - Multi Cell selection #tGrid', () => { }); it('Should not be possible to select a range when change cellSelection to single', () => { - const rangeChangeSpy = spyOn(treeGrid.rangeSelected, 'emit').and.callThrough(); + const rangeChangeSpy = vi.spyOn(treeGrid.rangeSelected, 'emit'); const startCell = treeGrid.gridAPI.get_cell_by_index(0, 'ID'); const middleCell = treeGrid.gridAPI.get_cell_by_index(1, 'ID'); const endCell = treeGrid.gridAPI.get_cell_by_index(2, 'ID'); @@ -167,7 +163,7 @@ describe('IgxTreeGrid - Multi Cell selection #tGrid', () => { })); it('Should be able to select a range with holding Shift key', (async () => { - const selectionChangeSpy = spyOn(treeGrid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(treeGrid.rangeSelected, 'emit'); const firstCell = treeGrid.gridAPI.get_cell_by_index(6, 'Age'); UIInteractions.simulateClickAndSelectEvent(firstCell); fix.detectChanges(); @@ -212,7 +208,7 @@ describe('IgxTreeGrid - Multi Cell selection #tGrid', () => { })); it('Should be able to select a range with keyboard', (async () => { - const selectionChangeSpy = spyOn(treeGrid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(treeGrid.rangeSelected, 'emit'); let cell = treeGrid.gridAPI.get_cell_by_index(9, 'Age'); UIInteractions.simulateClickAndSelectEvent(cell); @@ -269,7 +265,7 @@ describe('IgxTreeGrid - Multi Cell selection #tGrid', () => { })); it('Summaries: should select correct data when summaries are enabled', () => { - const selectionChangeSpy = spyOn(treeGrid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(treeGrid.rangeSelected, 'emit'); const range = { rowStart: 0, rowEnd: 10, columnStart: 0, columnEnd: 2 }; const expectedData = [ { ID: 147, Name: 'John Winchester', Age: 55 }, @@ -323,7 +319,7 @@ describe('IgxTreeGrid - Multi Cell selection #tGrid', () => { }); it('Summaries: verify selected data when change summaries position', () => { - const selectionChangeSpy = spyOn(treeGrid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(treeGrid.rangeSelected, 'emit'); const range = { rowStart: 0, rowEnd: 10, columnStart: 0, columnEnd: 2 }; const expectedData1 = [ { ID: 147, Name: 'John Winchester', Age: 55 }, @@ -367,7 +363,7 @@ describe('IgxTreeGrid - Multi Cell selection #tGrid', () => { }); it('Summaries: should select range with keyboard', (async () => { - const selectionChangeSpy = spyOn(treeGrid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(treeGrid.rangeSelected, 'emit'); treeGrid.getColumnByName('Name').hasSummary = true; treeGrid.summaryCalculationMode = 'childLevelsOnly'; fix.detectChanges(); @@ -412,7 +408,7 @@ describe('IgxTreeGrid - Multi Cell selection #tGrid', () => { })); it('Summaries: should clear selected range when navigate from summary cell without pressed shift', (async () => { - const selectionChangeSpy = spyOn(treeGrid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(treeGrid.rangeSelected, 'emit'); treeGrid.getColumnByName('Name').hasSummary = true; treeGrid.summaryCalculationMode = 'childLevelsOnly'; fix.detectChanges(); @@ -928,7 +924,7 @@ describe('IgxTreeGrid - Multi Cell selection #tGrid', () => { }); const verifySelectingRegion = (fix, treeGrid) => { - const selectionChangeSpy = spyOn(treeGrid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(treeGrid.rangeSelected, 'emit'); const range1 = { rowStart: 0, rowEnd: 6, columnStart: 'ID', columnEnd: 'Age' }; const range2 = { rowStart: 11, rowEnd: 16, columnStart: 'ID', columnEnd: 'OnPTO' }; const expectedData1 = [ @@ -1042,7 +1038,7 @@ describe('IgxTreeGrid - Multi Cell selection #tGrid', () => { }; const verifySelectingRangeWithMouseDrag = (fix, treeGrid, detect) => { - const selectionChangeSpy = spyOn(treeGrid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(treeGrid.rangeSelected, 'emit'); const startCell = treeGrid.gridAPI.get_cell_by_index(4, 'Name'); const endCell = treeGrid.gridAPI.get_cell_by_index(7, 'Age'); const range = { rowStart: 4, rowEnd: 7, columnStart: 1, columnEnd: 2 }; diff --git a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-search.spec.ts b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-search.spec.ts index a9cfd4007e9..aabcb3bfbad 100644 --- a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-search.spec.ts +++ b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-search.spec.ts @@ -1,13 +1,11 @@ import { TestBed, waitForAsync } from '@angular/core/testing'; import { IgxTreeGridComponent } from './tree-grid.component'; import { TreeGridFunctions, CELL_VALUE_DIV_CSS_CLASS } from '../../../test-utils/tree-grid-functions.spec'; -import { - IgxTreeGridSearchComponent, - IgxTreeGridPrimaryForeignKeyComponent, - IgxTreeGridSummariesScrollingComponent } from '../../../test-utils/tree-grid-components.spec'; +import { IgxTreeGridSearchComponent, IgxTreeGridPrimaryForeignKeyComponent, IgxTreeGridSummariesScrollingComponent } from '../../../test-utils/tree-grid-components.spec'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { wait } from '../../../test-utils/ui-interactions.spec'; import { IgxStringFilteringOperand, SortingDirection } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach } from 'vitest'; const HIGHLIGHT_CLASS = 'igx-highlight'; const ACTIVE_CLASS = 'igx-highlight__active'; @@ -181,13 +179,13 @@ describe('IgxTreeGrid - search API #tGrid', () => { // Apply asc sorting treeGrid.columnList.filter(c => c.field === 'JobTitle')[0].sortable = true; fix.detectChanges(); - treeGrid.sort({fieldName: 'JobTitle', dir: SortingDirection.Asc, ignoreCase: true }); + treeGrid.sort({ fieldName: 'JobTitle', dir: SortingDirection.Asc, ignoreCase: true }); fix.detectChanges(); verifySearchResult(fixNativeElement, 6, 3); // Apply desc sorting - treeGrid.sort({fieldName: 'JobTitle', dir: SortingDirection.Desc, ignoreCase: true }); + treeGrid.sort({ fieldName: 'JobTitle', dir: SortingDirection.Desc, ignoreCase: true }); fix.detectChanges(); verifySearchResult(fixNativeElement, 6, 1); @@ -197,7 +195,7 @@ describe('IgxTreeGrid - search API #tGrid', () => { // Apply asc sorting treeGrid.columnList.filter(c => c.field === 'JobTitle')[0].sortable = true; fix.detectChanges(); - treeGrid.sort({fieldName: 'JobTitle', dir: SortingDirection.Asc, ignoreCase: true }); + treeGrid.sort({ fieldName: 'JobTitle', dir: SortingDirection.Asc, ignoreCase: true }); fix.detectChanges(); treeGrid.findNext('er'); @@ -408,17 +406,17 @@ const verifySearchResult = (nativeParent, expectedHighlightSpansCount, expectedA const activeSpan = getActiveSpan(nativeParent); if (actualAPISearchCount) { - expect(actualAPISearchCount).toBe(expectedHighlightSpansCount, 'incorrect highlight elements count returned from api'); + expect(actualAPISearchCount, 'incorrect highlight elements count returned from api').toBe(expectedHighlightSpansCount); } - expect(spans.length).toBe(expectedHighlightSpansCount, 'incorrect highlight elements count'); + expect(spans.length, 'incorrect highlight elements count').toBe(expectedHighlightSpansCount); if (expectedActiveSpanIndex !== -1) { // If active element should exist. - expect(activeSpan).toBe(spans[expectedActiveSpanIndex], 'incorrect active element'); + expect(activeSpan, 'incorrect active element').toBe(spans[expectedActiveSpanIndex]); } else { // If active element should not exist. (used when spans.length is expected to be 0 as well) - expect(activeSpan).toBeNull('active element was found'); + expect(activeSpan, 'active element was found').toBeNull(); } }; @@ -436,7 +434,7 @@ const verifyVisibleCellValueDivsCount = (fix) => { allCells.forEach(cell => { const valueDivs: HTMLElement[] = Array.from(cell.nativeElement.querySelectorAll(CELL_VALUE_DIV_CSS_CLASS)); // only one visible 'value div' should be present - expect(valueDivs.filter(div => !div.hidden).length).toBe(1, 'incorrect visible value divs count'); + expect(valueDivs.filter(div => !div.hidden).length, 'incorrect visible value divs count').toBe(1); }); }; diff --git a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-selection.spec.ts b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-selection.spec.ts index ecb5458ddbe..3e791e3cec7 100644 --- a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-selection.spec.ts +++ b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-selection.spec.ts @@ -1,23 +1,8 @@ import { TestBed, fakeAsync, tick, waitForAsync } from '@angular/core/testing'; import { IgxTreeGridComponent } from './tree-grid.component'; -import { - IgxTreeGridSimpleComponent, - IgxTreeGridCellSelectionComponent, - IgxTreeGridSelectionRowEditingComponent, - IgxTreeGridSelectionWithTransactionComponent, - IgxTreeGridRowEditingTransactionComponent, - IgxTreeGridCustomRowSelectorsComponent, - IgxTreeGridCascadingSelectionComponent, - IgxTreeGridCascadingSelectionTransactionComponent, - IgxTreeGridPrimaryForeignKeyCascadeSelectionComponent -} from '../../../test-utils/tree-grid-components.spec'; +import { IgxTreeGridSimpleComponent, IgxTreeGridCellSelectionComponent, IgxTreeGridSelectionRowEditingComponent, IgxTreeGridSelectionWithTransactionComponent, IgxTreeGridRowEditingTransactionComponent, IgxTreeGridCustomRowSelectorsComponent, IgxTreeGridCascadingSelectionComponent, IgxTreeGridCascadingSelectionTransactionComponent, IgxTreeGridPrimaryForeignKeyCascadeSelectionComponent } from '../../../test-utils/tree-grid-components.spec'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { - TreeGridFunctions, - TREE_ROW_SELECTION_CSS_CLASS, - ROW_EDITING_BANNER_OVERLAY_CLASS, - TREE_ROW_DIV_SELECTION_CHECKBOX_CSS_CLASS -} from '../../../test-utils/tree-grid-functions.spec'; +import { TreeGridFunctions, TREE_ROW_SELECTION_CSS_CLASS, ROW_EDITING_BANNER_OVERLAY_CLASS, TREE_ROW_DIV_SELECTION_CHECKBOX_CSS_CLASS } from '../../../test-utils/tree-grid-functions.spec'; import { wait, UIInteractions } from '../../../test-utils/ui-interactions.spec'; import { IgxActionStripComponent } from 'igniteui-angular/action-strip'; import { GridFunctions } from '../../../test-utils/grid-functions.spec'; @@ -25,6 +10,7 @@ import { GridSelectionMode, IgxGridCell } from 'igniteui-angular/grids/core'; import { By } from '@angular/platform-browser'; import { IRowSelectionEventArgs } from 'igniteui-angular/grids/core'; import { FilteringExpressionsTree, FilteringLogic, IgxNumberFilteringOperand, IgxStringFilteringOperand, SortingDirection } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxTreeGrid - Selection #tGrid', () => { let fix; @@ -132,7 +118,7 @@ describe('IgxTreeGrid - Selection #tGrid', () => { TreeGridFunctions.verifyDataRowsSelection(fix, [0, 2], true); treeGrid.selectRows([treeGrid.gridAPI.get_row_by_index(1).key, treeGrid.gridAPI.get_row_by_index(3).key, - treeGrid.gridAPI.get_row_by_index(6).key, treeGrid.gridAPI.get_row_by_index(8).key], true); + treeGrid.gridAPI.get_row_by_index(6).key, treeGrid.gridAPI.get_row_by_index(8).key], true); fix.detectChanges(); // Verify new selection by NOT keeping the old one. @@ -143,8 +129,8 @@ describe('IgxTreeGrid - Selection #tGrid', () => { it('should be able to deselect row of any level', () => { treeGrid.selectRows([treeGrid.gridAPI.get_row_by_index(1).key, treeGrid.gridAPI.get_row_by_index(3).key, - treeGrid.gridAPI.get_row_by_index(6).key, treeGrid.gridAPI.get_row_by_index(8).key, - treeGrid.gridAPI.get_row_by_index(9).key], true); + treeGrid.gridAPI.get_row_by_index(6).key, treeGrid.gridAPI.get_row_by_index(8).key, + treeGrid.gridAPI.get_row_by_index(9).key], true); fix.detectChanges(); treeGrid.deselectRows([treeGrid.gridAPI.get_row_by_index(1).key, treeGrid.gridAPI.get_row_by_index(3).key]); @@ -174,7 +160,7 @@ describe('IgxTreeGrid - Selection #tGrid', () => { it('should persist the selection after filtering', fakeAsync(() => { treeGrid.selectRows([treeGrid.gridAPI.get_row_by_index(0).key, treeGrid.gridAPI.get_row_by_index(5).key, - treeGrid.gridAPI.get_row_by_index(8).key], true); + treeGrid.gridAPI.get_row_by_index(8).key], true); fix.detectChanges(); treeGrid.filter('Age', 40, IgxNumberFilteringOperand.instance().condition('greaterThan')); @@ -224,7 +210,7 @@ describe('IgxTreeGrid - Selection #tGrid', () => { it('should persist the selection after expand/collapse', () => { treeGrid.selectRows([treeGrid.gridAPI.get_row_by_index(0).key, treeGrid.gridAPI.get_row_by_index(3).key, - treeGrid.gridAPI.get_row_by_index(5).key], true); + treeGrid.gridAPI.get_row_by_index(5).key], true); fix.detectChanges(); expect(getVisibleSelectedRows(fix).length).toBe(3); @@ -245,7 +231,7 @@ describe('IgxTreeGrid - Selection #tGrid', () => { it('should persist selection after paging', fakeAsync(() => { treeGrid.selectRows([treeGrid.gridAPI.get_row_by_index(0).key, treeGrid.gridAPI.get_row_by_index(3).key, - treeGrid.gridAPI.get_row_by_index(5).key], true); + treeGrid.gridAPI.get_row_by_index(5).key], true); fix.detectChanges(); tick(16); @@ -281,16 +267,16 @@ describe('IgxTreeGrid - Selection #tGrid', () => { fix.componentInstance.selectedRows = [147, 19, 957]; fix.detectChanges(); - expect(treeGrid.gridAPI.get_row_by_index(0).selected).toBeTrue(); - expect(treeGrid.gridAPI.get_row_by_index(7).selected).toBeTrue(); - expect(treeGrid.gridAPI.get_row_by_index(4).selected).toBeFalse(); + expect(treeGrid.gridAPI.get_row_by_index(0).selected).toBe(true); + expect(treeGrid.gridAPI.get_row_by_index(7).selected).toBe(true); + expect(treeGrid.gridAPI.get_row_by_index(4).selected).toBe(false); fix.componentInstance.selectedRows = [847, 711]; fix.detectChanges(); - expect(treeGrid.gridAPI.get_row_by_index(0).selected).toBeFalse(); - expect(treeGrid.gridAPI.get_row_by_index(4).selected).toBeTrue(); - expect(treeGrid.gridAPI.get_row_by_index(8).selected).toBeTrue(); + expect(treeGrid.gridAPI.get_row_by_index(0).selected).toBe(false); + expect(treeGrid.gridAPI.get_row_by_index(4).selected).toBe(true); + expect(treeGrid.gridAPI.get_row_by_index(8).selected).toBe(true); }); }); @@ -320,7 +306,7 @@ describe('IgxTreeGrid - Selection #tGrid', () => { }); it('Header checkbox should NOT select/deselect all rows when selectionMode is single', () => { - spyOn(treeGrid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(treeGrid.rowSelectionChanging, 'emit'); treeGrid.rowSelection = GridSelectionMode.single; fix.detectChanges(); @@ -970,7 +956,7 @@ describe('IgxTreeGrid - Selection #tGrid', () => { column.bodyTemplate = component.customCell; fix.detectChanges(); - const selectionChangeSpy = spyOn(treeGrid.rangeSelected, 'emit').and.callThrough(); + const selectionChangeSpy = vi.spyOn(treeGrid.rangeSelected, 'emit'); const cell = treeGrid.gridAPI.get_cell_by_index(0, 'ID'); const cellElement = cell.nativeElement; const span = cellElement.querySelector('span'); @@ -1266,7 +1252,7 @@ describe('IgxTreeGrid - Selection #tGrid', () => { endTransition(); const addRow = treeGrid.gridAPI.get_row_by_index(9); - expect(addRow.addRowUI).toBeTrue(); + expect(addRow.addRowUI).toBe(true); treeGrid.gridAPI.crudService.endEdit(true); await wait(100); @@ -1690,7 +1676,7 @@ describe('IgxTreeGrid - Selection #tGrid', () => { e.cancel = true; }); - spyOn(treeGrid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(treeGrid.rowSelectionChanging, 'emit'); treeGrid.selectionService.selectRowsWithNoEvent([317]); fix.detectChanges(); @@ -1699,7 +1685,7 @@ describe('IgxTreeGrid - Selection #tGrid', () => { fix.detectChanges(); const args: IRowSelectionEventArgs = { - oldSelection: [ treeGrid.getRowData(317), treeGrid.getRowData(711), treeGrid.getRowData(998), treeGrid.getRowData(299)], + oldSelection: [treeGrid.getRowData(317), treeGrid.getRowData(711), treeGrid.getRowData(998), treeGrid.getRowData(299)], newSelection: [treeGrid.getRowData(711), treeGrid.getRowData(998)], added: [], removed: [treeGrid.getRowData(317), treeGrid.getRowData(299)], @@ -1768,7 +1754,7 @@ describe('IgxTreeGrid - Selection #tGrid', () => { }); it('selectRowById event SHOULD be emitted correctly with valid arguments.', () => { - spyOn(treeGrid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(treeGrid.rowSelectionChanging, 'emit'); treeGrid.selectionService.selectRowsWithNoEvent([317]); fix.detectChanges(); @@ -1784,10 +1770,10 @@ describe('IgxTreeGrid - Selection #tGrid', () => { treeGrid.selectionService.selectRowById(847, true); const args: IRowSelectionEventArgs = { - oldSelection: [ treeGrid.getRowData(317), treeGrid.getRowData(711), treeGrid.getRowData(998), treeGrid.getRowData(299)], + oldSelection: [treeGrid.getRowData(317), treeGrid.getRowData(711), treeGrid.getRowData(998), treeGrid.getRowData(299)], newSelection: [treeGrid.getRowData(847), treeGrid.getRowData(663)], added: [treeGrid.getRowData(847), treeGrid.getRowData(663)], - removed: [ treeGrid.getRowData(317), treeGrid.getRowData(711), treeGrid.getRowData(998), treeGrid.getRowData(299)], + removed: [treeGrid.getRowData(317), treeGrid.getRowData(711), treeGrid.getRowData(998), treeGrid.getRowData(299)], event: undefined, cancel: false, owner: treeGrid @@ -1812,7 +1798,7 @@ describe('IgxTreeGrid - Selection #tGrid', () => { treeGrid.rowSelectionChanging.subscribe((e: IRowSelectionEventArgs) => { e.newSelection = [treeGrid.getRowData(847), treeGrid.getRowData(663)]; }); - spyOn(treeGrid.rowSelectionChanging, 'emit').and.callThrough(); + vi.spyOn(treeGrid.rowSelectionChanging, 'emit'); treeGrid.selectionService.selectRowsWithNoEvent([317], true); fix.detectChanges(); @@ -1820,10 +1806,10 @@ describe('IgxTreeGrid - Selection #tGrid', () => { treeGrid.selectionService.selectRowById(19, true); const selectionArgs: IRowSelectionEventArgs = { - oldSelection: [ treeGrid.getRowData(317), treeGrid.getRowData(711), treeGrid.getRowData(998), treeGrid.getRowData(299)], + oldSelection: [treeGrid.getRowData(317), treeGrid.getRowData(711), treeGrid.getRowData(998), treeGrid.getRowData(299)], newSelection: [treeGrid.getRowData(847), treeGrid.getRowData(663)], added: [treeGrid.getRowData(19)], - removed: [treeGrid.getRowData(317), treeGrid.getRowData(711), treeGrid.getRowData(998), treeGrid.getRowData(299)], + removed: [treeGrid.getRowData(317), treeGrid.getRowData(711), treeGrid.getRowData(998), treeGrid.getRowData(299)], event: undefined, cancel: false, owner: treeGrid @@ -1936,7 +1922,7 @@ describe('IgxTreeGrid - Selection #tGrid', () => { endTransition(); const addRow = treeGrid.gridAPI.get_row_by_index(9); - expect(addRow.addRowUI).toBeTrue(); + expect(addRow.addRowUI).toBe(true); treeGrid.gridAPI.crudService.endEdit(true); await wait(100); @@ -2198,7 +2184,7 @@ describe('IgxTreeGrid - Selection #tGrid', () => { const firstCheckbox = firstRow.nativeElement.querySelector('.igx-checkbox__composite'); const context = { index: 0, rowID: 1, key: 1, selected: false }; const contextUnselect = { index: 0, rowID: 1, key: 1, selected: true }; - spyOn(fix.componentInstance, 'onRowCheckboxClick').and.callThrough(); + vi.spyOn(fix.componentInstance, 'onRowCheckboxClick'); (firstCheckbox as HTMLElement).click(); fix.detectChanges(); @@ -2217,7 +2203,7 @@ describe('IgxTreeGrid - Selection #tGrid', () => { const context = { selectedCount: 0, totalCount: 8 }; const contextUnselect = { selectedCount: 8, totalCount: 8 }; const headerCheckbox = treeGrid.theadRow.nativeElement.querySelector('.igx-checkbox__composite') as HTMLElement; - spyOn(fix.componentInstance, 'onHeaderCheckboxClick').and.callThrough(); + vi.spyOn(fix.componentInstance, 'onHeaderCheckboxClick'); headerCheckbox.click(); fix.detectChanges(); @@ -2243,5 +2229,4 @@ describe('IgxTreeGrid - Selection #tGrid', () => { }); -const getVisibleSelectedRows = (fix) => TreeGridFunctions.getAllRows(fix).filter( - (row) => row.nativeElement.classList.contains(TREE_ROW_SELECTION_CSS_CLASS)); +const getVisibleSelectedRows = (fix) => TreeGridFunctions.getAllRows(fix).filter((row) => row.nativeElement.classList.contains(TREE_ROW_SELECTION_CSS_CLASS)); diff --git a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-sorting.spec.ts b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-sorting.spec.ts index e2e93d4b71d..b99fde57abf 100644 --- a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-sorting.spec.ts +++ b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-sorting.spec.ts @@ -5,6 +5,7 @@ import { TreeGridFunctions } from '../../../test-utils/tree-grid-functions.spec' import { DefaultSortingStrategy, SortingDirection } from '../../../core/src/data-operations/sorting-strategy'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { GridFunctions } from '../../../test-utils/grid-functions.spec'; +import { describe, it, test, expect, beforeEach, vi } from 'vitest'; describe('IgxTreeGrid - Sorting #tGrid', () => { let fix; @@ -111,8 +112,10 @@ describe('IgxTreeGrid - Sorting #tGrid', () => { expect(treeGrid.getCellByColumn(4, 'Age').value).toEqual(35); }); - it('should sort treeGrid by multiple expressions through API', () => { - pending('figure out how was this passing before'); + it.skip('should sort treeGrid by multiple expressions through API', () => { + // TODO: vitest-migration: The pending() function was converted to a skipped test (`it.skip`). See: https://vitest.dev/api/vi.html#it-skip + // pending('figure out how was this passing before'); + ; // Test prerequisites (need to have multiple records with the same name on every level) treeGrid.data[0].Name = 'Ana Sanders'; treeGrid.data[0].Employees[1].Name = 'Michael Langdon'; @@ -199,7 +202,7 @@ describe('IgxTreeGrid - Sorting #tGrid', () => { describe('UI sorting', () => { it('should sort descending all treeGrid levels by column name through UI', () => { - const header = TreeGridFunctions.getHeaderCell(fix, 'Name'); + const header = TreeGridFunctions.getHeaderCell(fix, 'Name'); GridFunctions.clickHeaderSortIcon(header); GridFunctions.clickHeaderSortIcon(header); fix.detectChanges(); @@ -222,7 +225,7 @@ describe('IgxTreeGrid - Sorting #tGrid', () => { }); it('should sort ascending all treeGrid levels by column name through UI', () => { - const header = TreeGridFunctions.getHeaderCell(fix, 'Age'); + const header = TreeGridFunctions.getHeaderCell(fix, 'Age'); GridFunctions.clickHeaderSortIcon(header); fix.detectChanges(); @@ -250,7 +253,7 @@ describe('IgxTreeGrid - Sorting #tGrid', () => { expect(treeGrid.getCellByColumn(4, 'Age').value).toEqual(35); // Click header once - const header = TreeGridFunctions.getHeaderCell(fix, 'Age'); + const header = TreeGridFunctions.getHeaderCell(fix, 'Age'); GridFunctions.clickHeaderSortIcon(header); fix.detectChanges(); @@ -279,8 +282,8 @@ describe('IgxTreeGrid - Sorting #tGrid', () => { fix.detectChanges(); // Sort by 'Name' in asc order and by 'Age' in desc order - const headerName = TreeGridFunctions.getHeaderCell(fix, 'Name'); - const headerAge = TreeGridFunctions.getHeaderCell(fix, 'Age'); + const headerName = TreeGridFunctions.getHeaderCell(fix, 'Name'); + const headerAge = TreeGridFunctions.getHeaderCell(fix, 'Age'); GridFunctions.clickHeaderSortIcon(headerName); fix.detectChanges(); GridFunctions.clickHeaderSortIcon(headerAge); @@ -329,8 +332,8 @@ describe('IgxTreeGrid - Sorting #tGrid', () => { fix.detectChanges(); // Sort by 'Name' in asc order and by 'Age' in desc order - const headerName = TreeGridFunctions.getHeaderCell(fix, 'Name'); - const headerAge = TreeGridFunctions.getHeaderCell(fix, 'Age'); + const headerName = TreeGridFunctions.getHeaderCell(fix, 'Name'); + const headerAge = TreeGridFunctions.getHeaderCell(fix, 'Age'); GridFunctions.clickHeaderSortIcon(headerName); fix.detectChanges(); GridFunctions.clickHeaderSortIcon(headerAge); diff --git a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-summaries.spec.ts b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-summaries.spec.ts index bd5777ceb4e..2c42158ce85 100644 --- a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-summaries.spec.ts +++ b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-summaries.spec.ts @@ -1,13 +1,6 @@ import { TestBed, waitForAsync } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { - IgxTreeGridSummariesComponent, - IgxTreeGridSummariesKeyComponent, - IgxTreeGridCustomSummariesComponent, - IgxTreeGridSummariesTransactionsComponent, - IgxTreeGridSummariesScrollingComponent, - IgxTreeGridSummariesKeyScroliingComponent -} from '../../../test-utils/tree-grid-components.spec'; +import { IgxTreeGridSummariesComponent, IgxTreeGridSummariesKeyComponent, IgxTreeGridCustomSummariesComponent, IgxTreeGridSummariesTransactionsComponent, IgxTreeGridSummariesScrollingComponent, IgxTreeGridSummariesKeyScroliingComponent } from '../../../test-utils/tree-grid-components.spec'; import { clearGridSubs, setupGridScrollDetection } from '../../../test-utils/helper-utils.spec'; import { wait, UIInteractions } from '../../../test-utils/ui-interactions.spec'; import { GridSummaryFunctions, GridFunctions } from '../../../test-utils/grid-functions.spec'; @@ -15,6 +8,7 @@ import { DebugElement } from '@angular/core'; import { IgxTreeGridComponent } from './tree-grid.component'; import { IgxSummaryRow, IgxTreeGridRow } from 'igniteui-angular/grids/core'; import { IgxNumberFilteringOperand } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; describe('IgxTreeGrid - Summaries #tGrid', () => { const DEBOUNCETIME = 30; @@ -237,21 +231,19 @@ describe('IgxTreeGrid - Summaries #tGrid', () => { treeGrid.toggleRow(treeGrid.getRowByIndex(3).key); fix.detectChanges(); - const gridSummaryRow = treeGrid.getRowByIndex(4); - expect(gridSummaryRow.index).toEqual(4); - expect(gridSummaryRow.viewIndex).toEqual(4); - expect(gridSummaryRow instanceof IgxSummaryRow).toBe(true); + const gridSummaryRow = treeGrid.getRowByIndex(4); + expect(gridSummaryRow.index).toEqual(4); + expect(gridSummaryRow.viewIndex).toEqual(4); + expect(gridSummaryRow instanceof IgxSummaryRow).toBe(true); summaries = GridSummaryFunctions.getAllVisibleSummaries(fix); expect(summaries.length).toBe(4); let summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 4); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, - ['Count', 'Earliest', 'Latest'], ['2', 'Nov 11, 2009', 'Oct 17, 2015']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Earliest', 'Latest'], ['2', 'Nov 11, 2009', 'Oct 17, 2015']); summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 5); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, - ['Count', 'Earliest', 'Latest'], ['3', 'Jul 19, 2009', 'Sep 18, 2014']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Earliest', 'Latest'], ['3', 'Jul 19, 2009', 'Sep 18, 2014']); treeGrid.summaryPosition = 'top'; fix.detectChanges(); @@ -260,12 +252,10 @@ describe('IgxTreeGrid - Summaries #tGrid', () => { expect(summaries.length).toBe(4); summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 1); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, - ['Count', 'Earliest', 'Latest'], ['3', 'Jul 19, 2009', 'Sep 18, 2014']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Earliest', 'Latest'], ['3', 'Jul 19, 2009', 'Sep 18, 2014']); summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 5); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, - ['Count', 'Earliest', 'Latest'], ['2', 'Nov 11, 2009', 'Oct 17, 2015']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Earliest', 'Latest'], ['2', 'Nov 11, 2009', 'Oct 17, 2015']); }); it('should position correctly summary row for collapsed rows -- top position', async () => { @@ -293,12 +283,10 @@ describe('IgxTreeGrid - Summaries #tGrid', () => { expect(summaries.length).toBe(4); let summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 1); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, - ['Count', 'Earliest', 'Latest'], ['3', 'Jul 19, 2009', 'Sep 18, 2014']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Earliest', 'Latest'], ['3', 'Jul 19, 2009', 'Sep 18, 2014']); summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 5); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, - ['Count', 'Earliest', 'Latest'], ['2', 'Nov 11, 2009', 'Oct 17, 2015']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Earliest', 'Latest'], ['2', 'Nov 11, 2009', 'Oct 17, 2015']); }); it('should be able to enable/disable summaries at runtime', () => { @@ -390,8 +378,7 @@ describe('IgxTreeGrid - Summaries #tGrid', () => { }); let summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 4); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, - ['Count', 'Earliest', 'Latest'], ['3', 'Jul 19, 2009', 'Sep 18, 2014']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Earliest', 'Latest'], ['3', 'Jul 19, 2009', 'Sep 18, 2014']); treeGrid.enableSummaries([{ fieldName: 'Age' }, { fieldName: 'ID' }]); fix.detectChanges(); @@ -408,12 +395,10 @@ describe('IgxTreeGrid - Summaries #tGrid', () => { }); summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 4); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['3', '29', '43', '103', '34.333']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['3', '29', '43', '103', '34.333']); summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['4', '42', '61', '207', '51.75']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['4', '42', '61', '207', '51.75']); }); it('should be able to change summary operant at runtime', () => { @@ -428,16 +413,13 @@ describe('IgxTreeGrid - Summaries #tGrid', () => { GridSummaryFunctions.verifyVisibleSummariesHeight(fix, 6); let summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 7); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg', 'Test'], ['3', '29', '43', '103', '34.333', '2']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg', 'Test'], ['3', '29', '43', '103', '34.333', '2']); summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 6); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg', 'Test'], ['2', '35', '44', '79', '39.5', '1']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg', 'Test'], ['2', '35', '44', '79', '39.5', '1']); summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg', 'Test'], ['4', '42', '61', '207', '51.75', '0']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg', 'Test'], ['4', '42', '61', '207', '51.75', '0']); }); it('should be able to change summary operant with API', () => { @@ -514,8 +496,7 @@ describe('IgxTreeGrid - Summaries #tGrid', () => { expect(GridSummaryFunctions.getAllVisibleSummariesLength(fix)).toEqual(2); let summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 2); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['1']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, - ['Count', 'Earliest', 'Latest'], ['1', 'Dec 18, 2007', 'Dec 18, 2007']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Earliest', 'Latest'], ['1', 'Dec 18, 2007', 'Dec 18, 2007']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['1', '50', '50', '50', '50']); summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); @@ -539,8 +520,7 @@ describe('IgxTreeGrid - Summaries #tGrid', () => { let summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 5); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['1']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, - ['Count', 'Earliest', 'Latest'], ['1', 'Dec 18, 2007', 'Dec 18, 2007']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Earliest', 'Latest'], ['1', 'Dec 18, 2007', 'Dec 18, 2007']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['1', '50', '50', '50', '50']); summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 2); @@ -660,10 +640,8 @@ describe('IgxTreeGrid - Summaries #tGrid', () => { const summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['5']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, - ['Count', 'Earliest', 'Latest'], ['5', 'Apr 20, 2008', 'Apr 3, 2019']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['5', '19', '61', '226', '45.2']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Earliest', 'Latest'], ['5', 'Apr 20, 2008', 'Apr 3, 2019']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['5', '19', '61', '226', '45.2']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count'], ['5']); verifySummaryForRow147(fix, 7); @@ -685,8 +663,7 @@ describe('IgxTreeGrid - Summaries #tGrid', () => { const summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 8); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['4']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, - ['Count', 'Earliest', 'Latest'], ['4', 'Jul 19, 2009', 'Apr 3, 2019']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Earliest', 'Latest'], ['4', 'Jul 19, 2009', 'Apr 3, 2019']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count'], ['4']); verifyTreeBaseSummaries(fix); @@ -725,10 +702,8 @@ describe('IgxTreeGrid - Summaries #tGrid', () => { const summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['3']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, - ['Count', 'Earliest', 'Latest'], ['3', 'Feb 1, 2010', 'Feb 22, 2014']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['3', '42', '61', '152', '50.667']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Earliest', 'Latest'], ['3', 'Feb 1, 2010', 'Feb 22, 2014']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['3', '42', '61', '152', '50.667']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count'], ['3']); verifySummaryForRow847(fix, 5); @@ -787,8 +762,7 @@ describe('IgxTreeGrid - Summaries #tGrid', () => { const summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 3); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['2']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, - ['Count', 'Earliest', 'Latest'], ['2', 'Jul 19, 2009', 'Jul 3, 2011']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Earliest', 'Latest'], ['2', 'Jul 19, 2009', 'Jul 3, 2011']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '29', '43', '72', '36']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count'], ['2']); @@ -817,8 +791,7 @@ describe('IgxTreeGrid - Summaries #tGrid', () => { GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['4']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Earliest', 'Latest'], ['4', 'Feb 1, 2010', 'Apr 3, 2019']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['4', '19', '61', '171', '42.75']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['4', '19', '61', '171', '42.75']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count'], ['4']); }); @@ -845,15 +818,13 @@ describe('IgxTreeGrid - Summaries #tGrid', () => { GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['2']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Earliest', 'Latest'], ['2', 'May 4, 2014', 'Apr 3, 2019']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '19', '44', '63', '31.5']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '19', '44', '63', '31.5']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count'], ['2']); summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 5); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['1']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, - ['Count', 'Earliest', 'Latest'], ['1', 'Apr 22, 2010', 'Apr 22, 2010']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Earliest', 'Latest'], ['1', 'Apr 22, 2010', 'Apr 22, 2010']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['1', '39', '39', '39', '39']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count'], ['1']); }); @@ -1417,8 +1388,7 @@ describe('IgxTreeGrid - Summaries #tGrid', () => { GridSummaryFunctions.verifySummaryCellActive(fix, summaryRow, 5); summaryRow = GridSummaryFunctions.getRootSummaryRow(fix); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['4', '42', '61', '207', '51.75']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['4', '42', '61', '207', '51.75']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 5, ['Count'], ['4']); for (let i = 5; i > 0; i--) { @@ -1457,8 +1427,7 @@ describe('IgxTreeGrid - Summaries #tGrid', () => { fix.detectChanges(); GridSummaryFunctions.verifySummaryCellActive(fix, summaryRow, 5); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['4', '42', '61', '207', '51.75']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['4', '42', '61', '207', '51.75']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 5, ['Count'], ['4']); UIInteractions.triggerEventHandlerKeyDown('ArrowLeft', gridFooter, false, false, true); @@ -1486,8 +1455,7 @@ describe('IgxTreeGrid - Summaries #tGrid', () => { fix.detectChanges(); } - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['3', '29', '43', '103', '34.333']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['3', '29', '43', '103', '34.333']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 5, ['Count'], ['3']); for (let i = 5; i > 0; i--) { @@ -1498,8 +1466,7 @@ describe('IgxTreeGrid - Summaries #tGrid', () => { } GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['3', '147', '147', '441', '147']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['3', '147', '147', '441', '147']); }); it('Should not change active summary cell when press Ctrl+ArrowUp/Down', async () => { @@ -1563,8 +1530,7 @@ describe('IgxTreeGrid - Summaries #tGrid', () => { summaryRow = GridSummaryFunctions.getSummaryRowByDataRowIndex(fix, 6); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '317', '317', '634', '317']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['2', '317', '317', '634', '317']); }); it('Should navigate with arrow keys from treeGrid cell to summary row ', () => { @@ -1730,8 +1696,7 @@ describe('IgxTreeGrid - Summaries #tGrid', () => { GridSummaryFunctions.verifyColumnSummaries(summaryRow, 0, [], []); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 1, ['Count'], ['3']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 2, ['Count', 'Earliest', 'Latest'], ['3', 'Jul 19, 2009', 'Sep 18, 2014']); - GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, - ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['3', '29', '43', '103', '34.333']); + GridSummaryFunctions.verifyColumnSummaries(summaryRow, 3, ['Count', 'Min', 'Max', 'Sum', 'Avg'], ['3', '29', '43', '103', '34.333']); GridSummaryFunctions.verifyColumnSummaries(summaryRow, 4, ['Count'], ['3']); }; diff --git a/projects/igniteui-angular/grids/tree-grid/src/tree-grid.component.spec.ts b/projects/igniteui-angular/grids/tree-grid/src/tree-grid.component.spec.ts index c661e8897ee..5f0459e3f8a 100644 --- a/projects/igniteui-angular/grids/tree-grid/src/tree-grid.component.spec.ts +++ b/projects/igniteui-angular/grids/tree-grid/src/tree-grid.component.spec.ts @@ -2,20 +2,14 @@ import { TestBed, fakeAsync, tick, waitForAsync } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxTreeGridComponent } from './tree-grid.component'; import { By } from '@angular/platform-browser'; -import { - IgxTreeGridWrappedInContComponent, - IgxTreeGridDefaultLoadingComponent, - IgxTreeGridCellSelectionComponent, - IgxTreeGridSummariesTransactionsComponent, - IgxTreeGridNoDataComponent, - IgxTreeGridWithNoForeignKeyComponent -} from '../../../test-utils/tree-grid-components.spec'; +import { IgxTreeGridWrappedInContComponent, IgxTreeGridDefaultLoadingComponent, IgxTreeGridCellSelectionComponent, IgxTreeGridSummariesTransactionsComponent, IgxTreeGridNoDataComponent, IgxTreeGridWithNoForeignKeyComponent } from '../../../test-utils/tree-grid-components.spec'; import { wait } from '../../../test-utils/ui-interactions.spec'; import { GridSelectionMode } from 'igniteui-angular/grids/core'; import { SampleTestData } from '../../../test-utils/sample-test-data.spec'; import { SAFE_DISPOSE_COMP_ID } from '../../../test-utils/grid-functions.spec'; import { setElementSize } from '../../../test-utils/helper-utils.spec'; import { IgxStringFilteringOperand, ɵSize } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; describe('IgxTreeGrid Component Tests #tGrid', () => { @@ -82,15 +76,15 @@ describe('IgxTreeGrid Component Tests #tGrid', () => { it(`should render all records exactly if height is 100% and parent container\'s height is unset and there are fewer than 10 records in the data view`, () => { - grid.height = '100%'; - fix.componentInstance.data = fix.componentInstance.data.slice(0, 1); - fix.detectChanges(); - // fakeAsync is not needed. Need a second change detection cycle for height changes to be applied. - fix.detectChanges(); - const defaultHeight = fix.debugElement.query(By.css(TBODY_CLASS)).styles.height; - expect(defaultHeight).toBeFalsy(); - expect(fix.componentInstance.isVerticalScrollbarVisible()).toBeFalsy(); - expect(grid.rowList.length).toEqual(6); + grid.height = '100%'; + fix.componentInstance.data = fix.componentInstance.data.slice(0, 1); + fix.detectChanges(); + // fakeAsync is not needed. Need a second change detection cycle for height changes to be applied. + fix.detectChanges(); + const defaultHeight = fix.debugElement.query(By.css(TBODY_CLASS)).styles.height; + expect(defaultHeight).toBeFalsy(); + expect(fix.componentInstance.isVerticalScrollbarVisible()).toBeFalsy(); + expect(grid.rowList.length).toEqual(6); }); it(`should render 11 records if height is 100% and parent container\'s height is unset and grid size is changed`, async () => { @@ -152,16 +146,13 @@ describe('IgxTreeGrid Component Tests #tGrid', () => { }); it('should throw a warning when primaryKey is set to a non-existing data field', () => { - jasmine.getEnv().allowRespy(true); - const warnSpy = spyOn(console, 'warn'); + const warnSpy = vi.spyOn(console, 'warn'); grid.primaryKey = 'testField'; fix.detectChanges(); expect(console.warn).toHaveBeenCalledTimes(1); - expect(console.warn).toHaveBeenCalledWith( - `Field "${grid.primaryKey}" is not defined in the data. Set \`primaryKey\` to a valid field.` - ); - warnSpy.calls.reset(); + expect(console.warn).toHaveBeenCalledWith(`Field "${grid.primaryKey}" is not defined in the data. Set \`primaryKey\` to a valid field.`); + warnSpy.mockClear(); const oldData = fix.componentInstance.data; const newData = fix.componentInstance.data.map(rec => Object.assign({}, rec, { testField: 0 })); @@ -174,10 +165,7 @@ describe('IgxTreeGrid Component Tests #tGrid', () => { fix.detectChanges(); expect(console.warn).toHaveBeenCalledTimes(1); - expect(console.warn).toHaveBeenCalledWith( - `Field "${grid.primaryKey}" is not defined in the data. Set \`primaryKey\` to a valid field.` - ); - jasmine.getEnv().allowRespy(false); + expect(console.warn).toHaveBeenCalledWith(`Field "${grid.primaryKey}" is not defined in the data. Set \`primaryKey\` to a valid field.`); }); }); @@ -310,7 +298,8 @@ describe('IgxTreeGrid Component Tests #tGrid', () => { tick(); fix.detectChanges(); - let fixEl = fix.nativeElement; let gridEl = grid.nativeElement; + let fixEl = fix.nativeElement; + let gridEl = grid.nativeElement; let tHeadItems = fixEl.querySelector('igx-grid-header-group'); let gridRows = fixEl.querySelector('igx-tree-grid-row'); let paging = fixEl.querySelector('.igx-paginator'); diff --git a/projects/igniteui-angular/icon/src/icon/icon.component.spec.ts b/projects/igniteui-angular/icon/src/icon/icon.component.spec.ts index e44b1ec8666..1ac5b785711 100644 --- a/projects/igniteui-angular/icon/src/icon/icon.component.spec.ts +++ b/projects/igniteui-angular/icon/src/icon/icon.component.spec.ts @@ -6,6 +6,7 @@ import { IconFamily } from './types'; import type { IconType } from './types'; import { By } from "@angular/platform-browser"; +import { describe, it, expect, beforeEach } from 'vitest'; describe("Icon", () => { @@ -22,9 +23,7 @@ describe("Icon", () => { fixture = TestBed.createComponent(IconTestComponent); - const debugElement = fixture.debugElement.query( - By.directive(IgxIconComponent), - ); + const debugElement = fixture.debugElement.query(By.directive(IgxIconComponent)); instance = debugElement.componentInstance; el = debugElement.nativeElement; @@ -148,9 +147,7 @@ describe("Icon", () => { iconService.defaultFamily = fa; const fixture = TestBed.createComponent(IconTestComponent); - const debugElement = fixture.debugElement.query( - By.directive(IgxIconComponent), - ); + const debugElement = fixture.debugElement.query(By.directive(IgxIconComponent)); const instance = debugElement.componentInstance; const el = debugElement.nativeElement; @@ -178,9 +175,7 @@ describe("Icon", () => { }); const fixture = TestBed.createComponent(MetaIconComponent); - const debugElement = fixture.debugElement.query( - By.directive(IgxIconComponent), - ); + const debugElement = fixture.debugElement.query(By.directive(IgxIconComponent)); const instance = debugElement.componentInstance; const el = debugElement.nativeElement; @@ -233,7 +228,8 @@ function assertRenderedIcon(el: HTMLElement, icon: ProtoIgxIcon) { template: ``, imports: [IgxIconComponent] }) -class IconTestComponent {} +class IconTestComponent { +} @Component({ template: ``, imports: [IgxIconComponent] }) -class MetaIconComponent {} +class MetaIconComponent { +} diff --git a/projects/igniteui-angular/icon/src/icon/icon.service.spec.ts b/projects/igniteui-angular/icon/src/icon/icon.service.spec.ts index 08ee0e27266..ccf760a9f34 100644 --- a/projects/igniteui-angular/icon/src/icon/icon.service.spec.ts +++ b/projects/igniteui-angular/icon/src/icon/icon.service.spec.ts @@ -7,7 +7,9 @@ import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http' import { Component, inject } from "@angular/core"; import { IgxIconComponent } from "./icon.component"; import { By } from "@angular/platform-browser"; -import { IgxTheme, THEME_TOKEN, ThemeToken } from 'igniteui-angular/core';; +import { IgxTheme, THEME_TOKEN, ThemeToken } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; +; describe("Icon Service", () => { const FAMILY: IconFamily = { @@ -20,7 +22,11 @@ describe("Icon Service", () => { `; - let iconRef: { name: string; family: string; icon: IconMeta }; + let iconRef: { + name: string; + family: string; + icon: IconMeta; + }; let iconService: IgxIconService; beforeEach(() => { @@ -119,19 +125,15 @@ describe("Icon Service", () => { it("should get the className by family name", () => { iconService.setFamily(FAMILY.name, FAMILY.meta); - expect(iconService.familyClassName(FAMILY.name)).toBe( - FAMILY.meta.className, - ); + expect(iconService.familyClassName(FAMILY.name)).toBe(FAMILY.meta.className); }); - it("should add custom svg icon from url", fakeAsync(( - done: () => object, - ) => { + it("should add custom svg icon from url", fakeAsync((done: () => object) => { const iconName = "test"; const familyName = "svg-icons"; - spyOn(XMLHttpRequest.prototype, "open").and.callThrough(); - spyOn(XMLHttpRequest.prototype, "send"); + vi.spyOn(XMLHttpRequest.prototype, "open"); + vi.spyOn(XMLHttpRequest.prototype, "send"); iconService.addSvgIcon(iconName, "test.svg", familyName); @@ -139,9 +141,7 @@ describe("Icon Service", () => { expect(XMLHttpRequest.prototype.send).toHaveBeenCalledTimes(1); iconService.iconLoaded.pipe().subscribe(() => { - expect( - iconService.isSvgIconCached(iconName, familyName), - ).toBeTruthy(); + expect(iconService.isSvgIconCached(iconName, familyName)).toBeTruthy(); done(); }); })); @@ -193,18 +193,18 @@ describe("Icon Service", () => { expect(svgText).toContain(svg.innerHTML); }); - it("should emit loading event for a custom svg icon from url", (done) => { + it("should emit loading event for a custom svg icon from url", async () => { iconService.iconLoaded.pipe(first()).subscribe((event) => { expect(event.name).toMatch("test"); expect(event.family).toMatch("svg-icons"); - done(); + ; }); const iconName = "test"; const familyName = "svg-icons"; - spyOn(XMLHttpRequest.prototype, "open").and.callThrough(); - spyOn(XMLHttpRequest.prototype, "send").and.callFake(() => { + vi.spyOn(XMLHttpRequest.prototype, "open"); + vi.spyOn(XMLHttpRequest.prototype, "send").mockImplementation(() => { (iconService as any)._iconLoaded.next({ name: iconName, value: svgText, @@ -224,9 +224,9 @@ describe("Icon Service", () => { expect(fixture.componentInstance.themeToken.theme).toBe('material'); expect(arrow_prev).toBeTruthy(); - expect(arrow_prev.classes['material-icons']).toBeTrue(); + expect(arrow_prev.classes['material-icons']).toBe(true); expect(expand_more).toBeTruthy(); - expect(expand_more.classes['material-icons']).toBeTrue(); + expect(expand_more.classes['material-icons']).toBe(true); fixture.componentInstance.setTheme('indigo'); fixture.detectChanges(); @@ -238,11 +238,11 @@ describe("Icon Service", () => { // The class change should be reflected as the family changes expect(arrow_prev).toBeTruthy(); - expect(arrow_prev.classes['internal_indigo']).toBeTrue(); + expect(arrow_prev.classes['internal_indigo']).toBe(true); // The expand_more shouldn't change as its reference is set explicitly expect(expand_more).toBeTruthy(); - expect(expand_more.classes['material-icons']).toBeTrue(); + expect(expand_more.classes['material-icons']).toBe(true); }); }); @@ -253,13 +253,15 @@ describe("Icon Service", () => { `, imports: [IgxIconComponent] }) -class IconTestComponent { } +class IconTestComponent { +} @Component({ template: ``, imports: [IgxIconComponent] }) -class IconRefComponent { } +class IconRefComponent { +} @Component({ template: ` diff --git a/projects/igniteui-angular/input-group/src/input-group/directives-hint/hint.directive.spec.ts b/projects/igniteui-angular/input-group/src/input-group/directives-hint/hint.directive.spec.ts index b7561ac161c..ccb48209830 100644 --- a/projects/igniteui-angular/input-group/src/input-group/directives-hint/hint.directive.spec.ts +++ b/projects/igniteui-angular/input-group/src/input-group/directives-hint/hint.directive.spec.ts @@ -3,6 +3,7 @@ import { TestBed, waitForAsync } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { IgxHintDirective } from './hint.directive'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('IgxHint', () => { const HINT_START_CSS_CLASS = 'igx-input-group__hint-item--start'; @@ -16,7 +17,7 @@ describe('IgxHint', () => { EndHintComponent ] }) - .compileComponents(); + .compileComponents(); })); it('Initializes a hint.', () => { diff --git a/projects/igniteui-angular/input-group/src/input-group/directives-input/input.directive.spec.ts b/projects/igniteui-angular/input-group/src/input-group/directives-input/input.directive.spec.ts index 7d82af8c502..a367d8c6bc8 100644 --- a/projects/igniteui-angular/input-group/src/input-group/directives-input/input.directive.spec.ts +++ b/projects/igniteui-angular/input-group/src/input-group/directives-input/input.directive.spec.ts @@ -10,6 +10,7 @@ import { IgxIconComponent } from '../../../../icon/src/icon/icon.component'; import { IgxLabelDirective } from '../directives-label/label.directive'; import { IgxMaskDirective } from 'igniteui-angular/directives'; import { IgxSuffixDirective } from '../directives-suffix/suffix.directive'; +import { describe, it, expect, beforeEach } from 'vitest'; const INPUT_CSS_CLASS = 'igx-input-group__input'; const CSS_CLASS_INPUT_GROUP_LABEL = 'igx-input-group__label'; @@ -777,7 +778,7 @@ describe('IgxInput', () => { fixture.detectChanges(); expect(igxInput.value).toEqual('C:\\fakepath\\filename.jpg'); - expect(form.controls['fileInput'].value).toEqual('C:\\fakepath\\filename.jpg') + expect(form.controls['fileInput'].value).toEqual('C:\\fakepath\\filename.jpg'); const clearButton = igxInputGroup.element.nativeElement.querySelector('.igx-input-group__clear-icon'); expect(clearButton).toBeDefined(); @@ -942,8 +943,10 @@ describe('IgxInput', () => { imports: [IgxInputGroupComponent, IgxLabelDirective, IgxInputDirective, FormsModule] }) class InputsWithSameNameAttributesComponent { - @ViewChildren('igxInputGroup') public igxInputGroup: QueryList; - @ViewChild(IgxInputDirective, { static: true }) public igxInput: IgxInputDirective; + @ViewChildren('igxInputGroup') + public igxInputGroup: QueryList; + @ViewChild(IgxInputDirective, { static: true }) + public igxInput: IgxInputDirective; public model = { firstName: null @@ -961,8 +964,10 @@ class InputsWithSameNameAttributesComponent { imports: [IgxInputGroupComponent, IgxLabelDirective, IgxInputDirective] }) class InputComponent { - @ViewChild('igxInputGroup', { static: true }) public igxInputGroup: IgxInputGroupComponent; - @ViewChild(IgxInputDirective, { static: true }) public igxInput: IgxInputDirective; + @ViewChild('igxInputGroup', { static: true }) + public igxInputGroup: IgxInputGroupComponent; + @ViewChild(IgxInputDirective, { static: true }) + public igxInput: IgxInputDirective; } @Component({ @@ -987,7 +992,8 @@ class TextareaComponent { imports: [IgxInputGroupComponent, IgxLabelDirective, IgxInputDirective] }) class InputWithPlaceholderComponent { - @ViewChild(IgxInputDirective, { static: true }) public igxInput: IgxInputDirective; + @ViewChild(IgxInputDirective, { static: true }) + public igxInput: IgxInputDirective; } @Component({ @@ -1000,8 +1006,10 @@ class InputWithPlaceholderComponent { imports: [IgxInputGroupComponent, IgxLabelDirective, IgxInputDirective] }) class FilledInputComponent { - @ViewChild('igxInputGroup', { static: true }) public igxInputGroup: IgxInputGroupComponent; - @ViewChild(IgxInputDirective, { static: true }) public igxInput: IgxInputDirective; + @ViewChild('igxInputGroup', { static: true }) + public igxInputGroup: IgxInputGroupComponent; + @ViewChild(IgxInputDirective, { static: true }) + public igxInput: IgxInputDirective; } @Component({ @@ -1014,8 +1022,10 @@ class FilledInputComponent { imports: [IgxInputGroupComponent, IgxLabelDirective, IgxInputDirective] }) class DisabledInputComponent { - @ViewChild('igxInputGroup', { static: true }) public igxInputGroup: IgxInputGroupComponent; - @ViewChild(IgxInputDirective, { static: true }) public igxInput: IgxInputDirective; + @ViewChild('igxInputGroup', { static: true }) + public igxInputGroup: IgxInputGroupComponent; + @ViewChild(IgxInputDirective, { static: true }) + public igxInput: IgxInputDirective; } @Component({ @@ -1028,8 +1038,10 @@ class DisabledInputComponent { imports: [IgxInputGroupComponent, IgxLabelDirective, IgxInputDirective] }) class RequiredInputComponent { - @ViewChild('igxInputGroup', { static: true }) public igxInputGroup: IgxInputGroupComponent; - @ViewChild(IgxInputDirective, { static: true }) public igxInput: IgxInputDirective; + @ViewChild('igxInputGroup', { static: true }) + public igxInputGroup: IgxInputGroupComponent; + @ViewChild(IgxInputDirective, { static: true }) + public igxInput: IgxInputDirective; } @Component({ @@ -1040,8 +1052,10 @@ class RequiredInputComponent { imports: [IgxInputGroupComponent, IgxLabelDirective, IgxInputDirective, FormsModule] }) class RequiredTwoWayDataBoundInputComponent { - @ViewChild('igxInputGroup', { static: true }) public igxInputGroup: IgxInputGroupComponent; - @ViewChild(IgxInputDirective, { static: true }) public igxInput: IgxInputDirective; + @ViewChild('igxInputGroup', { static: true }) + public igxInputGroup: IgxInputGroupComponent; + @ViewChild(IgxInputDirective, { static: true }) + public igxInput: IgxInputDirective; public user = { firstName: '' @@ -1093,15 +1107,23 @@ class RequiredTwoWayDataBoundInputComponent { imports: [IgxInputGroupComponent, IgxLabelDirective, IgxInputDirective, FormsModule] }) class InitiallyFilledInputComponent { - @ViewChild('igxInputGroupNotFilledUndefined', { static: true }) public igxInputGroupNotFilledUndefined: IgxInputGroupComponent; - @ViewChild('igxInputGroupNotFilledNull', { static: true }) public igxInputGroupNotFilledNull: IgxInputGroupComponent; - @ViewChild('igxInputGroupNotFilledEmpty', { static: true }) public igxInputGroupNotFilledEmpty: IgxInputGroupComponent; - - @ViewChild('igxInputGroupFilledString', { static: true }) public igxInputGroupFilledString: IgxInputGroupComponent; - @ViewChild('igxInputGroupFilledNumber', { static: true }) public igxInputGroupFilledNumber: IgxInputGroupComponent; - @ViewChild('igxInputGroupFilledBoolFalse', { static: true }) public igxInputGroupFilledBoolFalse: IgxInputGroupComponent; - @ViewChild('igxInputGroupFilledBoolTrue', { static: true }) public igxInputGroupFilledBoolTrue: IgxInputGroupComponent; - @ViewChild('igxInputGroupFilledDate', { static: true }) public igxInputGroupFilledDate: IgxInputGroupComponent; + @ViewChild('igxInputGroupNotFilledUndefined', { static: true }) + public igxInputGroupNotFilledUndefined: IgxInputGroupComponent; + @ViewChild('igxInputGroupNotFilledNull', { static: true }) + public igxInputGroupNotFilledNull: IgxInputGroupComponent; + @ViewChild('igxInputGroupNotFilledEmpty', { static: true }) + public igxInputGroupNotFilledEmpty: IgxInputGroupComponent; + + @ViewChild('igxInputGroupFilledString', { static: true }) + public igxInputGroupFilledString: IgxInputGroupComponent; + @ViewChild('igxInputGroupFilledNumber', { static: true }) + public igxInputGroupFilledNumber: IgxInputGroupComponent; + @ViewChild('igxInputGroupFilledBoolFalse', { static: true }) + public igxInputGroupFilledBoolFalse: IgxInputGroupComponent; + @ViewChild('igxInputGroupFilledBoolTrue', { static: true }) + public igxInputGroupFilledBoolTrue: IgxInputGroupComponent; + @ViewChild('igxInputGroupFilledDate', { static: true }) + public igxInputGroupFilledDate: IgxInputGroupComponent; public notFilledUndefined = undefined; public notFilledNull = null; @@ -1125,8 +1147,10 @@ class InitiallyFilledInputComponent { imports: [IgxInputGroupComponent, IgxLabelDirective, IgxInputDirective] }) class DataBoundDisabledInputComponent { - @ViewChild('igxInputGroup', { static: true }) public igxInputGroup: IgxInputGroupComponent; - @ViewChild(IgxInputDirective, { static: true }) public igxInput: IgxInputDirective; + @ViewChild('igxInputGroup', { static: true }) + public igxInputGroup: IgxInputGroupComponent; + @ViewChild(IgxInputDirective, { static: true }) + public igxInput: IgxInputDirective; public disabled = false; } @@ -1190,7 +1214,8 @@ class DataBoundDisabledInputWithoutValueComponent extends DataBoundDisabledInput class ReactiveFormComponent { private fb = inject(UntypedFormBuilder); - @ViewChild('strinput', { static: true, read: IgxInputDirective }) public strIgxInput: IgxInputDirective; + @ViewChild('strinput', { static: true, read: IgxInputDirective }) + public strIgxInput: IgxInputDirective; public form = this.fb.group({ str: ['', Validators.required], @@ -1266,8 +1291,10 @@ class ToggleRequiredWithNgModelInputComponent { }) class InputReactiveFormComponent { - @ViewChild('igxInputGroup', { static: true }) public igxInputGroup: IgxInputGroupComponent; - @ViewChild('inputReactive', { read: IgxInputDirective }) public input: IgxInputDirective; + @ViewChild('igxInputGroup', { static: true }) + public igxInputGroup: IgxInputGroupComponent; + @ViewChild('inputReactive', { read: IgxInputDirective }) + public input: IgxInputDirective; public reactiveForm: UntypedFormGroup; public validationType = { @@ -1332,10 +1359,14 @@ class InputReactiveFormComponent { }) class FileInputFormComponent { - @ViewChild('igxInputGroup', { static: true }) public igxInputGroup: IgxInputGroupComponent; - @ViewChild('fileInput', { read: IgxInputDirective }) public input: IgxInputDirective; - @ViewChild('igxInputGroupNgModel', { static: true }) public igxInputGroupNgModel: IgxInputGroupComponent; - @ViewChild('inputNgModel', { read: IgxInputDirective }) public inputWithNgModel: IgxInputDirective; + @ViewChild('igxInputGroup', { static: true }) + public igxInputGroup: IgxInputGroupComponent; + @ViewChild('fileInput', { read: IgxInputDirective }) + public input: IgxInputDirective; + @ViewChild('igxInputGroupNgModel', { static: true }) + public igxInputGroupNgModel: IgxInputGroupComponent; + @ViewChild('inputNgModel', { read: IgxInputDirective }) + public inputWithNgModel: IgxInputDirective; public formWithFileInput: UntypedFormGroup; public model = { inputValue: null diff --git a/projects/igniteui-angular/input-group/src/input-group/directives-input/read-only-input.directive.spec.ts b/projects/igniteui-angular/input-group/src/input-group/directives-input/read-only-input.directive.spec.ts index 0cf117e4b4d..05c83948a64 100644 --- a/projects/igniteui-angular/input-group/src/input-group/directives-input/read-only-input.directive.spec.ts +++ b/projects/igniteui-angular/input-group/src/input-group/directives-input/read-only-input.directive.spec.ts @@ -3,8 +3,10 @@ import { TestBed, waitForAsync } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxReadOnlyInputDirective } from './read-only-input.directive'; import { IgxDatePickerComponent } from 'igniteui-angular/date-picker'; -import { IgxInputGroupComponent } from 'igniteui-angular/input-group';; +import { IgxInputGroupComponent } from 'igniteui-angular/input-group'; +; import { By } from '@angular/platform-browser'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('IgxReadOnlyInputDirective', () => { beforeEach(waitForAsync(() => { @@ -14,7 +16,7 @@ describe('IgxReadOnlyInputDirective', () => { TestComponent ] }) - .compileComponents(); + .compileComponents(); })); it('should update readOnly property and `igx-input-group--readonly` class correctly', () => { @@ -23,32 +25,32 @@ describe('IgxReadOnlyInputDirective', () => { const inputGroupDebug = fixture.debugElement.query(By.directive(IgxInputGroupComponent)); const inputGroupEl = inputGroupDebug.nativeElement as HTMLElement; - expect(inputGroupEl.classList.contains('igx-input-group--readonly')).toBeFalse(); + expect(inputGroupEl.classList.contains('igx-input-group--readonly')).toBe(false); const inputDebug = fixture.debugElement.query(By.css('input')); const inputEl = inputDebug.nativeElement as HTMLInputElement; - expect(inputEl.readOnly).toBeFalse(); + expect(inputEl.readOnly).toBe(false); fixture.componentInstance.datePicker.readOnly = true; fixture.detectChanges(); - expect(inputGroupEl.classList.contains('igx-input-group--readonly')).toBeTrue(); - expect(inputEl.readOnly).toBeTrue(); + expect(inputGroupEl.classList.contains('igx-input-group--readonly')).toBe(true); + expect(inputEl.readOnly).toBe(true); fixture.componentInstance.datePicker.readOnly = false; fixture.detectChanges(); - expect(inputGroupEl.classList.contains('igx-input-group--readonly')).toBeFalse(); - expect(inputEl.readOnly).toBeFalse(); + expect(inputGroupEl.classList.contains('igx-input-group--readonly')).toBe(false); + expect(inputEl.readOnly).toBe(false); // When the date-picker component is in dialog mode, the native input is always readonly fixture.componentInstance.datePicker.mode = 'dialog'; fixture.detectChanges(); - expect(inputGroupEl.classList.contains('igx-input-group--readonly')).toBeFalse(); - expect(inputEl.readOnly).toBeTrue(); + expect(inputGroupEl.classList.contains('igx-input-group--readonly')).toBe(false); + expect(inputEl.readOnly).toBe(true); fixture.componentInstance.datePicker.readOnly = true; fixture.detectChanges(); - expect(inputGroupEl.classList.contains('igx-input-group--readonly')).toBeTrue(); - expect(inputEl.readOnly).toBeTrue(); + expect(inputGroupEl.classList.contains('igx-input-group--readonly')).toBe(true); + expect(inputEl.readOnly).toBe(true); }); }); diff --git a/projects/igniteui-angular/input-group/src/input-group/input-group.component.spec.ts b/projects/igniteui-angular/input-group/src/input-group/input-group.component.spec.ts index a190d14c8f5..6fd0958a3e7 100644 --- a/projects/igniteui-angular/input-group/src/input-group/input-group.component.spec.ts +++ b/projects/igniteui-angular/input-group/src/input-group/input-group.component.spec.ts @@ -5,6 +5,7 @@ import { IgxInputGroupComponent } from './input-group.component'; import { UIInteractions } from '../../../test-utils/ui-interactions.spec'; import { IgxInputDirective, IgxPrefixDirective, IgxSuffixDirective } from '../public_api'; import { IGX_INPUT_GROUP_TYPE, IgxInputGroupType } from './inputGroupType'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const INPUT_GROUP_CSS_CLASS = 'igx-input-group'; const INPUT_GROUP_BOX_CSS_CLASS = 'igx-input-group--box'; @@ -182,7 +183,7 @@ describe('IgxInputGroup', () => { const pointOnPrefix = UIInteractions.getPointFromElement(prefix.nativeElement); const pointerEvent = UIInteractions.createPointerEvent('pointerdown', pointOnPrefix); - const preventDefaultSpy = spyOn(pointerEvent, 'preventDefault'); + const preventDefaultSpy = vi.spyOn(pointerEvent, 'preventDefault'); Object.defineProperty(pointerEvent, 'target', { value: input.nativeElement, configurable: true }); const inputGroupDebugElement = fixture.debugElement.query(By.directive(IgxInputGroupComponent)); @@ -253,10 +254,14 @@ describe('IgxInputGroup', () => { class InputGroupComponent { public IGTOKEN = inject(IGX_INPUT_GROUP_TYPE); - @ViewChild('igxInputGroup', { static: true }) public igxInputGroup: IgxInputGroupComponent; - @ViewChild('igxInput', { read: IgxInputDirective, static: true }) public igxInput: IgxInputDirective; - @ViewChild(IgxPrefixDirective, { read: ElementRef }) public prefix: ElementRef; - @ViewChild(IgxSuffixDirective, { read: ElementRef }) public suffix: ElementRef; + @ViewChild('igxInputGroup', { static: true }) + public igxInputGroup: IgxInputGroupComponent; + @ViewChild('igxInput', { read: IgxInputDirective, static: true }) + public igxInput: IgxInputDirective; + @ViewChild(IgxPrefixDirective, { read: ElementRef }) + public prefix: ElementRef; + @ViewChild(IgxSuffixDirective, { read: ElementRef }) + public suffix: ElementRef; public suppressInputAutofocus = false; } @@ -267,7 +272,8 @@ class InputGroupComponent { imports: [IgxInputGroupComponent, IgxInputDirective] }) class InputGroupBoxComponent { - @ViewChild('igxInputGroup', { static: true }) public igxInputGroup: IgxInputGroupComponent; + @ViewChild('igxInputGroup', { static: true }) + public igxInputGroup: IgxInputGroupComponent; } @Component({ @@ -277,7 +283,8 @@ class InputGroupBoxComponent { imports: [IgxInputGroupComponent, IgxInputDirective] }) class InputGroupBorderComponent { - @ViewChild('igxInputGroup', { static: true }) public igxInputGroup: IgxInputGroupComponent; + @ViewChild('igxInputGroup', { static: true }) + public igxInputGroup: IgxInputGroupComponent; } @Component({ @@ -287,7 +294,8 @@ class InputGroupBorderComponent { imports: [IgxInputDirective, IgxInputGroupComponent] }) class InputGroupSearchComponent { - @ViewChild('igxInputGroup', { static: true }) public igxInputGroup: IgxInputGroupComponent; + @ViewChild('igxInputGroup', { static: true }) + public igxInputGroup: IgxInputGroupComponent; } @Component({ @@ -296,7 +304,8 @@ class InputGroupSearchComponent { `, imports: [IgxInputGroupComponent, IgxInputDirective] }) -class InputGroupFileComponent { } +class InputGroupFileComponent { +} const testInputGroupType = (type: IgxInputGroupType, component: IgxInputGroupComponent, nativeElement: HTMLInputElement) => { let isLine = false; @@ -337,7 +346,8 @@ const testInputGroupType = (type: IgxInputGroupType, component: IgxInputGroupCom imports: [IgxInputGroupComponent, IgxInputDirective] }) class InputGroupDisabledComponent { - @ViewChild('igxInputGroup', { static: true }) public igxInputGroup: IgxInputGroupComponent; + @ViewChild('igxInputGroup', { static: true }) + public igxInputGroup: IgxInputGroupComponent; public disabled = false; @@ -371,7 +381,8 @@ class InputGroupDisabledWithoutValueComponent { imports: [IgxInputGroupComponent, IgxInputDirective] }) class InputGroupDisabledByDefaultComponent { - @ViewChild('igxInputGroup', { static: true }) public igxInputGroup: IgxInputGroupComponent; + @ViewChild('igxInputGroup', { static: true }) + public igxInputGroup: IgxInputGroupComponent; public disabled = true; } diff --git a/projects/igniteui-angular/karma.conf.js b/projects/igniteui-angular/karma.conf.js deleted file mode 100644 index c90fc344637..00000000000 --- a/projects/igniteui-angular/karma.conf.js +++ /dev/null @@ -1,58 +0,0 @@ -// Karma configuration file, see link for more information -// https://karma-runner.github.io/1.0/config/configuration-file.html - -process.env.CHROME_BIN = require('puppeteer').executablePath(); - -module.exports = function (config) { - config.set({ - basePath: '', - frameworks: ['parallel', 'jasmine', '@angular-devkit/build-angular'], - files: [ - { pattern: '../../node_modules/hammerjs/hammer.min.js', watched: false }, - { pattern: '../../node_modules/hammer-simulator/index.js', watched: false } - ], - plugins: [ - 'karma-parallel', - 'karma-jasmine', - 'karma-coverage', - 'karma-chrome-launcher', - 'karma-spec-reporter' - ], - parallelOptions: { - executors: 3, - shardStrategy: 'round-robin' - }, - client: { - clearContext: false, // leave Jasmine Spec Runner output visible in browser - jasmine: { - random: false - } - }, - coverageReporter: { - dir: require('path').join(__dirname, '../../coverage'), - subdir: '.', - reporters: [ - // reporters not supporting the `file` property - { type: 'lcov' }, - ] - }, - reporters: ['spec'], - specReporter: { - suppressSkipped: true - }, - port: 9876, - colors: true, - logLevel: config.LOG_INFO, - autoWatch: true, - browsers: ['ChromeHeadlessNoSandbox'], - browserDisconnectTimeout: 20000, - customLaunchers: { - ChromeHeadlessNoSandbox: { - base: 'ChromeHeadless', - flags: ['--no-sandbox', '--disable-gpu', '--window-size=820,800', '--js-flags="--expose-gc"'], - debug: false - } - }, - singleRun: false - }); -}; diff --git a/projects/igniteui-angular/karma.grid.conf.js b/projects/igniteui-angular/karma.grid.conf.js deleted file mode 100644 index d339e64f69f..00000000000 --- a/projects/igniteui-angular/karma.grid.conf.js +++ /dev/null @@ -1,69 +0,0 @@ -// Karma configuration file, see link for more information -// https://karma-runner.github.io/1.0/config/configuration-file.html - -module.exports = function (config) { - config.set({ - basePath: '', - frameworks: ['parallel', 'jasmine', 'jasmine-spec-tags', '@angular-devkit/build-angular'], - files: [ - { pattern: '../../node_modules/hammerjs/hammer.min.js', watched: false }, - { pattern: '../../node_modules/hammer-simulator/index.js', watched: false }, - { pattern: './test.css', watched: false }, - { pattern: '../../dist/igniteui-angular/styles/igniteui-angular.css', watched: false } - ], - plugins: [ - require('karma-parallel'), - require('karma-jasmine'), - require('karma-coverage'), - require('karma-chrome-launcher'), - require('karma-jasmine-spec-tags') - ], - parallelOptions: { - executors: 2, - shardStrategy: 'round-robin' - }, - client: { - clearContext: false, // leave Jasmine Spec Runner output visible in browser - jasmine: { - random: false - }, - tagPrefix: '#', - tags: 'grid', - skipTags: 'perf' - }, - preprocessors: { - 'projects/igniteui-angular/**/*.js': ['coverage'] - }, - coverageReporter: { - dir: require('path').join(__dirname, '../../coverage/grid'), - reporters: [ - // reporters not supporting the `file` property - { type: 'html' }, - { type: 'json' }, - { type: 'lcovonly' }, - ] - }, - reporters: ['progress', 'coverage'], - specReporter: { - suppressSkipped: true, - suppressErrorSummary: false, - suppressFailed: false, - suppressPassed: false, - showSpecTiming: false, - failFast: false - }, - port: 9876, - colors: true, - logLevel: config.LOG_INFO, - autoWatch: true, - browsers: ['ChromeHeadlessNoSandbox'], - customLaunchers: { - ChromeHeadlessNoSandbox: { - base: 'ChromeHeadless', - flags: ['--no-sandbox', '--disable-gpu', '--window-size=820,800', '--js-flags="--expose-gc"'], - debug: false - } - }, - singleRun: false - }); -}; diff --git a/projects/igniteui-angular/karma.hierarchical-grid.conf.js b/projects/igniteui-angular/karma.hierarchical-grid.conf.js deleted file mode 100644 index 8c564a10a16..00000000000 --- a/projects/igniteui-angular/karma.hierarchical-grid.conf.js +++ /dev/null @@ -1,68 +0,0 @@ -// Karma configuration file, see link for more information -// https://karma-runner.github.io/1.0/config/configuration-file.html - -module.exports = function (config) { - config.set({ - basePath: '', - frameworks: ['parallel', 'jasmine', 'jasmine-spec-tags', '@angular-devkit/build-angular'], - files: [ - { pattern: '../../node_modules/hammerjs/hammer.min.js', watched: false }, - { pattern: '../../node_modules/hammer-simulator/index.js', watched: false }, - { pattern: './test.css', watched: false }, - { pattern: '../../dist/igniteui-angular/styles/igniteui-angular.css', watched: false } - ], - plugins: [ - require('karma-parallel'), - require('karma-jasmine'), - require('karma-coverage'), - require('karma-chrome-launcher'), - require('karma-jasmine-spec-tags'), - require('@angular-devkit/build-angular/plugins/karma') - ], - parallelOptions: { - executors: 2, - shardStrategy: 'round-robin' - }, - client: { - clearContext: false, // leave Jasmine Spec Runner output visible in browser - jasmine: { - random: false - }, - tagPrefix: '#', - tags: 'hGrid' - }, - preprocessors: { - 'projects/igniteui-angular/**/*.js': ['coverage'] - }, - coverageReporter: { - dir: require('path').join(__dirname, '../../coverage/hierarchical-grid'), - reporters: [ - { type: 'html' }, - { type: 'json' }, - { type: 'lcovonly' }, - ] - }, - reporters: ['progress', 'coverage'], - specReporter: { - suppressSkipped: true, - suppressErrorSummary: false, - suppressFailed: false, - suppressPassed: false, - showSpecTiming: false, - failFast: false - }, - port: 9876, - colors: true, - logLevel: config.LOG_INFO, - autoWatch: true, - browsers: ['ChromeHeadlessNoSandbox'], - customLaunchers: { - ChromeHeadlessNoSandbox: { - base: 'ChromeHeadless', - flags: ['--no-sandbox', '--disable-gpu', '--window-size=820,800', '--js-flags="--expose-gc"'], - debug: false - } - }, - singleRun: false - }); -}; diff --git a/projects/igniteui-angular/karma.non-grid.conf.js b/projects/igniteui-angular/karma.non-grid.conf.js deleted file mode 100644 index 09bd55ea925..00000000000 --- a/projects/igniteui-angular/karma.non-grid.conf.js +++ /dev/null @@ -1,68 +0,0 @@ -// Karma configuration file, see link for more information -// https://karma-runner.github.io/1.0/config/configuration-file.html - -module.exports = function (config) { - config.set({ - basePath: '', - frameworks: ['parallel', 'jasmine', 'jasmine-spec-tags', '@angular-devkit/build-angular'], - files: [ - { pattern: '../../node_modules/hammerjs/hammer.min.js', watched: false }, - { pattern: '../../node_modules/hammer-simulator/index.js', watched: false }, - { pattern: './test.css', watched: false }, - { pattern: '../../dist/igniteui-angular/styles/igniteui-angular.css', watched: false } - ], - plugins: [ - require('karma-parallel'), - require('karma-jasmine'), - require('karma-coverage'), - require('karma-chrome-launcher'), - require('karma-jasmine-spec-tags'), - require('@angular-devkit/build-angular/plugins/karma') - ], - parallelOptions: { - executors: 2, - shardStrategy: 'round-robin' - }, - client: { - clearContext: false, // leave Jasmine Spec Runner output visible in browser - jasmine: { - random: false - }, - tagPrefix: '#', - skipTags: 'hGrid,tGrid,grid,perf' - }, - preprocessors: { - 'projects/igniteui-angular/**/*.js': ['coverage'] - }, - coverageReporter: { - dir: require('path').join(__dirname, '../../coverage/non-grid'), - reporters: [ - { type: 'html' }, - { type: 'json' }, - { type: 'lcovonly' }, - ] - }, - reporters: ['progress', 'coverage'], - specReporter: { - suppressSkipped: true, - suppressErrorSummary: false, - suppressFailed: false, - suppressPassed: false, - showSpecTiming: false, - failFast: false - }, - port: 9876, - colors: true, - logLevel: config.LOG_INFO, - autoWatch: true, - browsers: ['ChromeHeadlessNoSandbox'], - customLaunchers: { - ChromeHeadlessNoSandbox: { - base: 'ChromeHeadless', - flags: ['--no-sandbox', '--disable-gpu', '--window-size=820,800', '--js-flags="--expose-gc"'], - debug: false - } - }, - singleRun: false - }); -}; diff --git a/projects/igniteui-angular/karma.pivot-grid.conf.js b/projects/igniteui-angular/karma.pivot-grid.conf.js deleted file mode 100644 index a037310ecf7..00000000000 --- a/projects/igniteui-angular/karma.pivot-grid.conf.js +++ /dev/null @@ -1,71 +0,0 @@ -// Karma configuration file, see link for more information -// https://karma-runner.github.io/1.0/config/configuration-file.html - -module.exports = function (config) { - config.set({ - basePath: '', - frameworks: ['parallel', 'jasmine', 'jasmine-spec-tags', '@angular-devkit/build-angular'], - files: [ - { pattern: '../../node_modules/hammerjs/hammer.min.js', watched: false }, - { pattern: '../../node_modules/hammer-simulator/index.js', watched: false }, - { pattern: './test.css', watched: false }, - { pattern: '../../dist/igniteui-angular/styles/igniteui-angular.css', watched: false } - ], - plugins: [ - require('karma-parallel'), - require('karma-jasmine'), - require('karma-coverage'), - require('karma-chrome-launcher'), - require('karma-jasmine-spec-tags'), - require('karma-jasmine-html-reporter'), - require('karma-spec-reporter'), - require('@angular-devkit/build-angular/plugins/karma') - ], - parallelOptions: { - executors: 2, - shardStrategy: 'round-robin' - }, - client: { - clearContext: false, // leave Jasmine Spec Runner output visible in browser - jasmine: { - random: false - }, - tagPrefix: '#', - tags: 'pivotGrid' - }, - preprocessors: { - 'projects/igniteui-angular/**/*.js': ['coverage'] - }, - coverageReporter: { - dir: require('path').join(__dirname, '../../coverage/grid'), - reporters: [ - // reporters not supporting the `file` property - { type: 'html' }, - { type: 'json' }, - { type: 'lcovonly' }, - ] - }, - reporters: ['progress', 'coverage'], - specReporter: { - suppressSkipped: true, - suppressErrorSummary: false, - suppressFailed: false, - suppressPassed: false, - showSpecTiming: false, - failFast: false - }, - port: 9876, - colors: true, - logLevel: config.LOG_INFO, - autoWatch: true, - browsers: ['ChromeHeadlessNoSandbox'], - customLaunchers: { - ChromeHeadlessNoSandbox: { - base: 'ChromeHeadless', - flags: ['--no-sandbox', '--disable-gpu', '--window-size=820,800', '--js-flags="--expose-gc"'], - debug: false - } - }, - singleRun: false - }); -}; diff --git a/projects/igniteui-angular/karma.test-perf.conf.js b/projects/igniteui-angular/karma.test-perf.conf.js deleted file mode 100644 index f79b27cc778..00000000000 --- a/projects/igniteui-angular/karma.test-perf.conf.js +++ /dev/null @@ -1,44 +0,0 @@ -// Karma configuration file, see link for more information -// https://karma-runner.github.io/1.0/config/configuration-file.html - -module.exports = function (config) { - config.set({ - basePath: '', - frameworks: ['jasmine', 'jasmine-spec-tags', '@angular-devkit/build-angular'], - files: [ - { pattern: '../../node_modules/hammerjs/hammer.min.js', watched: false }, - { pattern: '../../node_modules/hammer-simulator/index.js', watched: false }, - { pattern: './test.css', watched: false }, - { pattern: '../../dist/igniteui-angular/styles/igniteui-angular.css', watched: false } - ], - plugins: [ - require('karma-jasmine'), - require('karma-chrome-launcher'), - require('karma-jasmine-spec-tags'), - require('@angular-devkit/build-angular/plugins/karma') - ], - client: { - clearContext: false, // leave Jasmine Spec Runner output visible in browser - jasmine: { - random: false - }, - tagPrefix: '#', - tags: 'perf' - }, - reporters: ['spec'], - specReporter: { - suppressSkipped: true, - suppressErrorSummary: false, - suppressFailed: false, - suppressPassed: false, - showSpecTiming: false, - failFast: false - }, - port: 9876, - colors: true, - logLevel: config.LOG_INFO, - autoWatch: true, - browsers: ['ChromeHeadless'], - singleRun: false - }); - }; diff --git a/projects/igniteui-angular/karma.tree-grid.conf.js b/projects/igniteui-angular/karma.tree-grid.conf.js deleted file mode 100644 index 4b2882a6d2a..00000000000 --- a/projects/igniteui-angular/karma.tree-grid.conf.js +++ /dev/null @@ -1,69 +0,0 @@ -// Karma configuration file, see link for more information -// https://karma-runner.github.io/1.0/config/configuration-file.html - -module.exports = function (config) { - config.set({ - basePath: '', - frameworks: ['parallel', 'jasmine', 'jasmine-spec-tags', '@angular-devkit/build-angular'], - files: [ - { pattern: '../../node_modules/hammerjs/hammer.min.js', watched: false }, - { pattern: '../../node_modules/hammer-simulator/index.js', watched: false }, - { pattern: './test.css', watched: false }, - { pattern: '../../dist/igniteui-angular/styles/igniteui-angular.css', watched: false } - ], - plugins: [ - require('karma-parallel'), - require('karma-jasmine'), - require('karma-coverage'), - require('karma-chrome-launcher'), - require('karma-jasmine-spec-tags'), - require('@angular-devkit/build-angular/plugins/karma') - ], - parallelOptions: { - executors: 2, - shardStrategy: 'round-robin' - }, - client: { - clearContext: false, // leave Jasmine Spec Runner output visible in browser - jasmine: { - random: false - }, - tagPrefix: '#', - tags: 'tGrid' - }, - preprocessors: { - 'projects/igniteui-angular/**/*.js': ['coverage'] - }, - coverageReporter: { - dir: require('path').join(__dirname, '../../coverage/tree-grid'), - reporters: [ - // reporters not supporting the `file` property - { type: 'html' }, - { type: 'json' }, - { type: 'lcovonly' }, - ] - }, - reporters: ['progress', 'coverage'], - specReporter: { - suppressSkipped: true, - suppressErrorSummary: false, - suppressFailed: false, - suppressPassed: false, - showSpecTiming: false, - failFast: false - }, - port: 9876, - colors: true, - logLevel: config.LOG_INFO, - autoWatch: true, - browsers: ['ChromeHeadlessNoSandbox'], - customLaunchers: { - ChromeHeadlessNoSandbox: { - base: 'ChromeHeadless', - flags: ['--no-sandbox', '--disable-gpu', '--window-size=820,800', '--js-flags="--expose-gc"'], - debug: false - } - }, - singleRun: false - }); -}; diff --git a/projects/igniteui-angular/karma.watch.conf.js b/projects/igniteui-angular/karma.watch.conf.js deleted file mode 100644 index 6b371d168e1..00000000000 --- a/projects/igniteui-angular/karma.watch.conf.js +++ /dev/null @@ -1,52 +0,0 @@ -// Karma configuration file, see link for more information -// https://karma-runner.github.io/1.0/config/configuration-file.html - -module.exports = function (config) { - config.set({ - basePath: '', - frameworks: ['jasmine', '@angular-devkit/build-angular'], - files: [ - { pattern: '../../node_modules/hammerjs/hammer.min.js', watched: false }, - { pattern: '../../node_modules/hammer-simulator/index.js', watched: false }, - { pattern: './test.css', watched: false } - ], - plugins: [ - 'karma-jasmine', - 'karma-chrome-launcher', - 'karma-spec-reporter' - ], - client: { - clearContext: false, // leave Jasmine Spec Runner output visible in browser - jasmine: { - random: false - }, - tagPrefix: '#', - skipTags: 'perf' - }, - reporters: ['spec'], - specReporter: { - suppressSkipped: true, - suppressErrorSummary: false, - suppressFailed: false, - suppressPassed: false, - showSpecTiming: false, - failFast: false - }, - port: 9876, - colors: true, - logLevel: config.LOG_INFO, - autoWatch: true, - browsers: ['ChromeWithGC'], - customLaunchers: { - ChromeWithGC: { - base: 'Chrome', - flags: [ - '--js-flags="--expose-gc"', - '--disable-backgrounding-occluded-windows', // don't throttle when window is fully hidden behind others - ], - debug: false - } - }, - singleRun: false - }); -}; diff --git a/projects/igniteui-angular/list/src/list/list.component.spec.ts b/projects/igniteui-angular/list/src/list/list.component.spec.ts index b9414781111..cfe449a45a9 100644 --- a/projects/igniteui-angular/list/src/list/list.component.spec.ts +++ b/projects/igniteui-angular/list/src/list/list.component.spec.ts @@ -3,32 +3,12 @@ import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { IgxListItemComponent } from './list-item.component'; import { IgxListPanState } from './list.common'; -import { - IgxListActionDirective, - IgxListComponent, - IgxListLineDirective, - IgxListLineSubTitleDirective, - IgxListLineTitleDirective, - IgxListThumbnailDirective, - IListItemClickEventArgs -} from './list.component'; - -import { - ListWithHeaderComponent, - ListWithPanningComponent, - EmptyListComponent, - CustomEmptyListComponent, - ListLoadingComponent, - ListWithPanningTemplatesComponent, - ListCustomLoadingComponent, - ListWithIgxForAndScrollingComponent, - TwoHeadersListComponent, - TwoHeadersListNoPanningComponent, - ListDirectivesComponent, - ListWithSelectedItemComponent -} from '../../../test-utils/list-components.spec'; +import { IgxListActionDirective, IgxListComponent, IgxListLineDirective, IgxListLineSubTitleDirective, IgxListLineTitleDirective, IgxListThumbnailDirective, IListItemClickEventArgs } from './list.component'; + +import { ListWithHeaderComponent, ListWithPanningComponent, EmptyListComponent, CustomEmptyListComponent, ListLoadingComponent, ListWithPanningTemplatesComponent, ListCustomLoadingComponent, ListWithIgxForAndScrollingComponent, TwoHeadersListComponent, TwoHeadersListNoPanningComponent, ListDirectivesComponent, ListWithSelectedItemComponent } from '../../../test-utils/list-components.spec'; import { wait } from '../../../test-utils/ui-interactions.spec'; import { GridFunctions } from '../../../test-utils/grid-functions.spec'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('List', () => { @@ -129,9 +109,9 @@ describe('List', () => { fixture.detectChanges(); - spyOn(list.leftPan, 'emit').and.callThrough(); - spyOn(list.panStateChange, 'emit').and.callThrough(); - spyOn(list.rightPan, 'emit').and.callThrough(); + vi.spyOn(list.leftPan, 'emit'); + vi.spyOn(list.panStateChange, 'emit'); + vi.spyOn(list.rightPan, 'emit'); const itemNativeElements = fixture.debugElement.queryAll(By.css('igx-list-item')); const listItems = list.items; @@ -155,8 +135,8 @@ describe('List', () => { fixture.detectChanges(); - spyOn(list.startPan, 'emit').and.callThrough(); - spyOn(list.endPan, 'emit').and.callThrough(); + vi.spyOn(list.startPan, 'emit'); + vi.spyOn(list.endPan, 'emit'); const itemNativeElements = fixture.debugElement.queryAll(By.css('igx-list-item')); @@ -178,9 +158,9 @@ describe('List', () => { const list: IgxListComponent = fixture.componentInstance.list; - spyOn(list.leftPan, 'emit').and.callThrough(); - spyOn(list.panStateChange, 'emit').and.callThrough(); - spyOn(list.rightPan, 'emit').and.callThrough(); + vi.spyOn(list.leftPan, 'emit'); + vi.spyOn(list.panStateChange, 'emit'); + vi.spyOn(list.rightPan, 'emit'); const itemNativeElements = fixture.debugElement.queryAll(By.css('igx-list-item')); const listItems = list.items; @@ -205,9 +185,9 @@ describe('List', () => { const list: IgxListComponent = fixture.componentInstance.list; - spyOn(list.leftPan, 'emit').and.callThrough(); - spyOn(list.panStateChange, 'emit').and.callThrough(); - spyOn(list.rightPan, 'emit').and.callThrough(); + vi.spyOn(list.leftPan, 'emit'); + vi.spyOn(list.panStateChange, 'emit'); + vi.spyOn(list.rightPan, 'emit'); const itemNativeElements = fixture.debugElement.queryAll(By.css('igx-list-item')); const listItems = list.items; @@ -309,7 +289,7 @@ describe('List', () => { const list: IgxListComponent = fixture.componentInstance.list; fixture.detectChanges(); - spyOn(list.itemClicked, 'emit').and.callThrough(); + vi.spyOn(list.itemClicked, 'emit'); const event = new Event('click'); list.items[0].element.dispatchEvent(event); @@ -318,7 +298,8 @@ describe('List', () => { event: event, direction: IgxListPanState.NONE }; - expect(list.itemClicked.emit).toHaveBeenCalledOnceWith(args); + expect(list.itemClicked.emit).toHaveBeenCalledTimes(1); + expect(list.itemClicked.emit).toHaveBeenCalledWith(args); // Click the same item again and verify click is fired again list.items[0].element.dispatchEvent(event); @@ -336,7 +317,7 @@ describe('List', () => { const fixture = TestBed.createComponent(ListWithPanningTemplatesComponent); const list = fixture.componentInstance.list; - spyOn(list.itemClicked, 'emit').and.callThrough(); + vi.spyOn(list.itemClicked, 'emit'); fixture.detectChanges(); const itemNativeElements = fixture.debugElement.queryAll(By.css('igx-list-item')); @@ -347,14 +328,15 @@ describe('List', () => { event: null, direction: IgxListPanState.LEFT }; - expect(list.itemClicked.emit).toHaveBeenCalledOnceWith(args); + expect(list.itemClicked.emit).toHaveBeenCalledTimes(1); + expect(list.itemClicked.emit).toHaveBeenCalledWith(args); }); it('should emit ItemClicked with correct direction argument when swiping right', () => { const fixture = TestBed.createComponent(ListWithPanningTemplatesComponent); const list = fixture.componentInstance.list; - spyOn(list.itemClicked, 'emit').and.callThrough(); + vi.spyOn(list.itemClicked, 'emit'); fixture.detectChanges(); const itemNativeElements = fixture.debugElement.queryAll(By.css('igx-list-item')); @@ -365,7 +347,8 @@ describe('List', () => { event: null, direction: IgxListPanState.RIGHT }; - expect(list.itemClicked.emit).toHaveBeenCalledOnceWith(args); + expect(list.itemClicked.emit).toHaveBeenCalledTimes(1); + expect(list.itemClicked.emit).toHaveBeenCalledWith(args); }); it('should display multiple headers properly.', () => { @@ -431,9 +414,9 @@ describe('List', () => { const item = list.items[0] as IgxListItemComponent; - spyOn(list.leftPan, 'emit').and.callThrough(); - spyOn(list.rightPan, 'emit').and.callThrough(); - spyOn(list.panStateChange, 'emit').and.callThrough(); + vi.spyOn(list.leftPan, 'emit'); + vi.spyOn(list.rightPan, 'emit'); + vi.spyOn(list.panStateChange, 'emit'); elementRefCollection = fixture.debugElement.queryAll(By.css('igx-list-item')); panItem(elementRefCollection[1], 0.8); @@ -488,9 +471,9 @@ describe('List', () => { const itemNativeElements = fixture.debugElement.queryAll(By.css('igx-list-item')); - spyOn(list.startPan, 'emit').and.callThrough(); - spyOn(list.endPan, 'emit').and.callThrough(); - spyOn(list.resetPan, 'emit').and.callThrough(); + vi.spyOn(list.startPan, 'emit'); + vi.spyOn(list.endPan, 'emit'); + vi.spyOn(list.resetPan, 'emit'); /* Pan item left */ panItem(itemNativeElements[1], -0.3); @@ -539,8 +522,8 @@ describe('List', () => { const list = fixture.componentInstance.list; fixture.detectChanges(); - spyOn(list.startPan, 'emit').and.callThrough(); - spyOn(list.endPan, 'emit').and.callThrough(); + vi.spyOn(list.startPan, 'emit'); + vi.spyOn(list.endPan, 'emit'); const firstItem = list.items[0] as IgxListItemComponent; const leftPanTmpl = firstItem.leftPanningTemplateElement; @@ -563,8 +546,8 @@ describe('List', () => { const list = fixture.componentInstance.list; fixture.detectChanges(); - spyOn(list.startPan, 'emit').and.callThrough(); - spyOn(list.endPan, 'emit').and.callThrough(); + vi.spyOn(list.startPan, 'emit'); + vi.spyOn(list.endPan, 'emit'); const firstItem = list.items[0] as IgxListItemComponent; const leftPanTmpl = firstItem.leftPanningTemplateElement; @@ -704,9 +687,9 @@ describe('List', () => { expect(thumbnail).toBeDefined(); // Check if the directive removes the classes from the target element - expect(thumbnail.nativeElement).toHaveClass('igx-icon'); + expect(thumbnail.nativeElement.classList.contains('igx-icon')).toBe(true); // Check if the directive wraps the target element and sets the correct class on the parent element - expect(thumbnail.parent.nativeElement).toHaveClass('igx-list__item-thumbnail'); + expect(thumbnail.parent.nativeElement.classList.contains('igx-list__item-thumbnail')).toBe(true); }); it('Initializes igxListLine directive', () => { @@ -716,9 +699,9 @@ describe('List', () => { expect(listLine).toBeDefined(); // Check if the directive removes the classes from the target element - expect(listLine.nativeElement).toHaveClass('text-line'); + expect(listLine.nativeElement.classList.contains('text-line')).toBe(true); // Check if the directive wraps the target element and sets the correct class on the parent element - expect(listLine.parent.nativeElement).toHaveClass('igx-list__item-lines'); + expect(listLine.parent.nativeElement.classList.contains('igx-list__item-lines')).toBe(true); }); it('Initializes igxListAction directive', () => { @@ -728,9 +711,9 @@ describe('List', () => { expect(listLine).toBeDefined(); // Check if the directive removes the classes from the target element - expect(listLine.nativeElement).toHaveClass('action-icon'); + expect(listLine.nativeElement.classList.contains('action-icon')).toBe(true); // Check if the directive wraps the target element and sets the correct class on the parent element - expect(listLine.parent.nativeElement).toHaveClass('igx-list__item-actions'); + expect(listLine.parent.nativeElement.classList.contains('igx-list__item-actions')).toBe(true); }); it('Initializes igxListLineTitle directive', () => { @@ -740,11 +723,11 @@ describe('List', () => { expect(listLine).toBeDefined(); // Check if the directive removes the custom classes from the target element - expect(listLine.nativeElement).toHaveClass('custom'); + expect(listLine.nativeElement.classList.contains('custom')).toBe(true); // Check if the directive add the correct class on the target element - expect(listLine.nativeElement).toHaveClass('igx-list__item-line-title'); + expect(listLine.nativeElement.classList.contains('igx-list__item-line-title')).toBe(true); // Check if the directive wraps the target element and sets the correct class on the parent element - expect(listLine.parent.nativeElement).toHaveClass('igx-list__item-lines'); + expect(listLine.parent.nativeElement.classList.contains('igx-list__item-lines')).toBe(true); }); it('Initializes igxListLineSubTitle directive', () => { @@ -754,11 +737,11 @@ describe('List', () => { expect(listLine).toBeDefined(); // Check if the directive removes the custom classes from the target element - expect(listLine.nativeElement).toHaveClass('custom'); + expect(listLine.nativeElement.classList.contains('custom')).toBe(true); // Check if the directive add the correct class on the target element - expect(listLine.nativeElement).toHaveClass('igx-list__item-line-subtitle'); + expect(listLine.nativeElement.classList.contains('igx-list__item-line-subtitle')).toBe(true); // Check if the directive wraps the target element and sets the correct class on the parent element - expect(listLine.parent.nativeElement).toHaveClass('igx-list__item-lines'); + expect(listLine.parent.nativeElement.classList.contains('igx-list__item-lines')).toBe(true); }); /* factorX - the coefficient used to calculate deltaX. diff --git a/projects/igniteui-angular/migrations/common/UpdateChanges.spec.ts b/projects/igniteui-angular/migrations/common/UpdateChanges.spec.ts index 9d561f24134..c55bb297887 100644 --- a/projects/igniteui-angular/migrations/common/UpdateChanges.spec.ts +++ b/projects/igniteui-angular/migrations/common/UpdateChanges.spec.ts @@ -5,6 +5,7 @@ import { ClassChanges, BindingChanges, SelectorChanges, ThemeChanges, ImportsCha import { UpdateChanges, InputPropertyType, BoundPropertyObject } from './UpdateChanges'; import * as tsUtils from './tsUtils'; import { setupTestTree } from './setup.spec'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('UpdateChanges', () => { let appTree: UnitTestTree; @@ -48,7 +49,7 @@ describe('UpdateChanges', () => { }); }); - it('should replace/remove components', done => { + it('should replace/remove components', async () => { const selectorsJson: SelectorChanges = { changes: [ { type: 'component' as any, selector: 'igx-component', replaceWith: 'igx-replaced' }, @@ -56,26 +57,17 @@ describe('UpdateChanges', () => { ] }; const jsonPath = path.join(__dirname, 'changes', 'selectors.json'); - spyOn(fs, 'existsSync').and.callFake((filePath: fs.PathLike) => { + vi.spyOn(fs, 'existsSync').mockImplementation((filePath: fs.PathLike) => { if (filePath === jsonPath) { return true; } return false; }); - spyOn(fs, 'readFileSync').and.returnValue(JSON.stringify(selectorsJson)); - - appTree.create( - 'test.component.html', - ' ' - ); - appTree.create( - 'test2.component.html', - '' - ); - appTree.create( - 'test3.component.html', - ' ' - ); + vi.spyOn(fs, 'readFileSync').mockReturnValue(JSON.stringify(selectorsJson)); + + appTree.create('test.component.html', ' '); + appTree.create('test2.component.html', ''); + appTree.create('test3.component.html', ' '); const update = new UnitUpdateChanges(__dirname, appTree); expect(fs.existsSync).toHaveBeenCalledWith(jsonPath); @@ -85,13 +77,11 @@ describe('UpdateChanges', () => { update.applyChanges(); expect(appTree.readContent('test.component.html')).toEqual(' '); expect(appTree.readContent('test2.component.html')).toEqual(''); - expect(appTree.readContent('test3.component.html')).toEqual( - ' ' - ); - done(); + expect(appTree.readContent('test3.component.html')).toEqual(' '); + ; }); - it('should replace/remove directives', done => { + it('should replace/remove directives', async () => { const selectorsJson: SelectorChanges = { changes: [ { type: 'directive' as any, selector: 'igxDirective', replaceWith: 'igxReplaced' }, @@ -99,31 +89,27 @@ describe('UpdateChanges', () => { ] }; const jsonPath = path.join(__dirname, 'changes', 'selectors.json'); - spyOn(fs, 'existsSync').and.callFake((filePath: fs.PathLike) => { + vi.spyOn(fs, 'existsSync').mockImplementation((filePath: fs.PathLike) => { if (filePath === jsonPath) { return true; } return false; }); - spyOn(fs, 'readFileSync').and.returnValue(JSON.stringify(selectorsJson)); + vi.spyOn(fs, 'readFileSync').mockReturnValue(JSON.stringify(selectorsJson)); - appTree.create( - 'test.component.html', - ` ` + - ` ` - ); + appTree.create('test.component.html', ` ` + + ` `); const update = new UnitUpdateChanges(__dirname, appTree); expect(update.getSelectorChanges()).toEqual(selectorsJson); update.applyChanges(); - expect(appTree.readContent('test.component.html')).toEqual( - ` ` + + expect(appTree.readContent('test.component.html')).toEqual(` ` + ` `); - done(); + ; }); - it('should replace/remove outputs', done => { + it('should replace/remove outputs', async () => { const outputJson: BindingChanges = { changes: [ { @@ -137,13 +123,13 @@ describe('UpdateChanges', () => { ] }; const jsonPath = path.join(__dirname, 'changes', 'outputs.json'); - spyOn(fs, 'existsSync').and.callFake((filePath: fs.PathLike) => { + vi.spyOn(fs, 'existsSync').mockImplementation((filePath: fs.PathLike) => { if (filePath === jsonPath) { return true; } return false; }); - spyOn(fs, 'readFileSync').and.callFake(() => JSON.stringify(outputJson)); + vi.spyOn(fs, 'readFileSync').mockImplementation(() => JSON.stringify(outputJson)); const fileContent = ` `; appTree.create('test.component.html', fileContent); @@ -154,28 +140,24 @@ describe('UpdateChanges', () => { expect(update.getOutputChanges()).toEqual(outputJson); update.applyChanges(); - expect(appTree.readContent('test.component.html')).toEqual( - ` `); + expect(appTree.readContent('test.component.html')).toEqual(` `); // should only match the defined selector #11666 const fileContent2 = ` `; appTree.overwrite('test.component.html', fileContent2); update.applyChanges(); - expect(appTree.readContent('test.component.html')).toEqual( - ` ` - ); + expect(appTree.readContent('test.component.html')).toEqual(` `); outputJson.changes[0].owner = { type: 'directive' as any, selector: 'tag' }; outputJson.changes[1].owner = { type: 'directive' as any, selector: 'tag' }; appTree.overwrite('test.component.html', fileContent); const update2 = new UnitUpdateChanges(__dirname, appTree); update2.applyChanges(); - expect(appTree.readContent('test.component.html')).toEqual( - ` `); - done(); + expect(appTree.readContent('test.component.html')).toEqual(` `); + ; }); - it('should replace/remove inputs', done => { + it('should replace/remove inputs', async () => { const inputJson: BindingChanges = { changes: [ { @@ -189,13 +171,13 @@ describe('UpdateChanges', () => { ] }; const jsonPath = path.join(__dirname, 'changes', 'inputs.json'); - spyOn(fs, 'existsSync').and.callFake((filePath: fs.PathLike) => { + vi.spyOn(fs, 'existsSync').mockImplementation((filePath: fs.PathLike) => { if (filePath === jsonPath) { return true; } return false; }); - spyOn(fs, 'readFileSync').and.callFake(() => JSON.stringify(inputJson)); + vi.spyOn(fs, 'readFileSync').mockImplementation(() => JSON.stringify(inputJson)); let fileContent = ` `; appTree.create('test.component.html', fileContent); @@ -206,16 +188,14 @@ describe('UpdateChanges', () => { expect(update.getInputChanges()).toEqual(inputJson); update.applyChanges(); - expect(appTree.readContent('test.component.html')).toEqual( - ` `); + expect(appTree.readContent('test.component.html')).toEqual(` `); inputJson.changes[1].remove = false; inputJson.changes[1].replaceWith = 'oldReplaced'; appTree.overwrite('test.component.html', fileContent); const update2 = new UnitUpdateChanges(__dirname, appTree); update2.applyChanges(); - expect(appTree.readContent('test.component.html')).toEqual( - ` `); + expect(appTree.readContent('test.component.html')).toEqual(` `); inputJson.changes[1].remove = true; inputJson.changes[0].owner = { type: 'directive' as any, selector: 'tag' }; @@ -223,39 +203,32 @@ describe('UpdateChanges', () => { appTree.overwrite('test.component.html', fileContent); const update3 = new UnitUpdateChanges(__dirname, appTree); update3.applyChanges(); - expect(appTree.readContent('test.component.html')).toEqual( - ` `); + expect(appTree.readContent('test.component.html')).toEqual(` `); inputJson.changes[1].owner = { type: 'component' as any, selector: 'another' }; inputJson.changes[0].owner = { type: 'component' as any, selector: 'comp' }; - const fileContent2 = - ``; + const fileContent2 = ``; appTree.overwrite('test.component.html', fileContent2); const update4 = new UnitUpdateChanges(__dirname, appTree); update4.applyChanges(); - expect(appTree.readContent('test.component.html')).toEqual( - ``); + expect(appTree.readContent('test.component.html')).toEqual(``); fileContent = ` sike! `; appTree.overwrite('test.component.html', fileContent); update4.applyChanges(); - expect(appTree.readContent('test.component.html')).toEqual( - ` sike! ` - ); + expect(appTree.readContent('test.component.html')).toEqual(` sike! `); // should only match the defined selector #11666 fileContent = ` `; appTree.overwrite('test.component.html', fileContent); update4.applyChanges(); - expect(appTree.readContent('test.component.html')).toEqual( - ` ` - ); + expect(appTree.readContent('test.component.html')).toEqual(` `); - done(); + ; }); - it('should replace class identifiers', done => { + it('should replace class identifiers', async () => { const classJson: ClassChanges = { changes: [ { @@ -267,16 +240,15 @@ describe('UpdateChanges', () => { ] }; const jsonPath = path.join(__dirname, 'changes', 'classes.json'); - spyOn(fs, 'existsSync').and.callFake((filePath: fs.PathLike) => { + vi.spyOn(fs, 'existsSync').mockImplementation((filePath: fs.PathLike) => { if (filePath === jsonPath) { return true; } return false; }); - spyOn(fs, 'readFileSync').and.callFake(() => JSON.stringify(classJson)); + vi.spyOn(fs, 'readFileSync').mockImplementation(() => JSON.stringify(classJson)); - const fileContent = - `import { igxClass, igxClass2 } from "igniteui-angular"; export class Test { prop: igxClass; prop2: igxClass2; }`; + const fileContent = `import { igxClass, igxClass2 } from "igniteui-angular"; export class Test { prop: igxClass; prop2: igxClass2; }`; appTree.create('test.component.ts', fileContent); const update = new UnitUpdateChanges(__dirname, appTree); @@ -285,13 +257,12 @@ describe('UpdateChanges', () => { expect(update.getClassChanges()).toEqual(classJson); update.applyChanges(); - expect(appTree.readContent('test.component.ts')).toEqual( - `import { igxReplace, igxSecond } from "igniteui-angular"; export class Test { prop: igxReplace; prop2: igxSecond; }`); + expect(appTree.readContent('test.component.ts')).toEqual(`import { igxReplace, igxSecond } from "igniteui-angular"; export class Test { prop: igxReplace; prop2: igxSecond; }`); - done(); + ; }); - it('should replace multiple class identifier with the same value', done => { + it('should replace multiple class identifier with the same value', async () => { const classJson: ClassChanges = { changes: [ { @@ -303,16 +274,15 @@ describe('UpdateChanges', () => { ] }; const jsonPath = path.join(__dirname, 'changes', 'classes.json'); - spyOn(fs, 'existsSync').and.callFake((filePath: fs.PathLike) => { + vi.spyOn(fs, 'existsSync').mockImplementation((filePath: fs.PathLike) => { if (filePath === jsonPath) { return true; } return false; }); - spyOn(fs, 'readFileSync').and.callFake(() => JSON.stringify(classJson)); + vi.spyOn(fs, 'readFileSync').mockImplementation(() => JSON.stringify(classJson)); - const fileContent = - `import { igxClass, igxClass2 } from "igniteui-angular"; export class Test { prop: igxClass; prop2: igxClass2; }`; + const fileContent = `import { igxClass, igxClass2 } from "igniteui-angular"; export class Test { prop: igxClass; prop2: igxClass2; }`; appTree.create('test.component.ts', fileContent); const update = new UnitUpdateChanges(__dirname, appTree); @@ -321,13 +291,12 @@ describe('UpdateChanges', () => { expect(update.getClassChanges()).toEqual(classJson); update.applyChanges(); - expect(appTree.readContent('test.component.ts')).toEqual( - `import { igxReplace } from "igniteui-angular"; export class Test { prop: igxReplace; prop2: igxReplace; }`); + expect(appTree.readContent('test.component.ts')).toEqual(`import { igxReplace } from "igniteui-angular"; export class Test { prop: igxReplace; prop2: igxReplace; }`); - done(); + ; }); - it('should replace class identifiers (complex file)', done => { + it('should replace class identifiers (complex file)', async () => { const classJson: ClassChanges = { changes: [ { name: 'IgxGridComponent', replaceWith: 'IgxGridReplace' }, @@ -344,16 +313,15 @@ describe('UpdateChanges', () => { ] }; const jsonPath = path.join(__dirname, 'changes', 'classes.json'); - spyOn(fs, 'existsSync').and.callFake((filePath: fs.PathLike) => { + vi.spyOn(fs, 'existsSync').mockImplementation((filePath: fs.PathLike) => { if (filePath === jsonPath) { return true; } return false; }); - spyOn(fs, 'readFileSync').and.callFake(() => JSON.stringify(classJson)); + vi.spyOn(fs, 'readFileSync').mockImplementation(() => JSON.stringify(classJson)); - const fileContent = - `import { Component, Injectable, ViewChild } from "@angular/core";` + + const fileContent = `import { Component, Injectable, ViewChild } from "@angular/core";` + `import { IgxGridComponent } from "igniteui-angular";` + `import { IgxColumnComponent, IgxProvided, STRING_FILTERS} from "igniteui-angular";\r\n` + `import {` + @@ -380,8 +348,7 @@ describe('UpdateChanges', () => { ` private getOptions(fileName: string): IgxExporterOptionsBase {` + ` return new IgxExcelExporterOptions(fileName);` + ` }` + - `}` - ; + `}`; appTree.create('test.component.ts', fileContent); const update = new UnitUpdateChanges(__dirname, appTree); @@ -390,8 +357,7 @@ describe('UpdateChanges', () => { expect(update.getClassChanges()).toEqual(classJson); update.applyChanges(); - expect(appTree.readContent('test.component.ts')).toEqual( - `import { Component, Injectable, ViewChild } from "@angular/core";` + + expect(appTree.readContent('test.component.ts')).toEqual(`import { Component, Injectable, ViewChild } from "@angular/core";` + `import { IgxGridReplace } from "igniteui-angular";` + `import { IgxColumnReplace, IgxProvidedReplace, REPLACED_CONST} from "igniteui-angular";\r\n` + `import {` + @@ -418,10 +384,9 @@ describe('UpdateChanges', () => { ` private getOptions(fileName: string): ReturnType {` + ` return new IgxNewable(fileName);` + ` }` + - `}` - ); + `}`); - done(); + ; }); it('should correctly ignore types not from igniteui-angular', () => { @@ -432,26 +397,25 @@ describe('UpdateChanges', () => { ] }; const jsonPath = path.join(__dirname, 'changes', 'classes.json'); - spyOn(fs, 'existsSync').and.callFake((filePath: fs.PathLike) => { + vi.spyOn(fs, 'existsSync').mockImplementation((filePath: fs.PathLike) => { if (filePath === jsonPath) { return true; } return false; }); - spyOn(fs, 'readFileSync').and.callFake(() => JSON.stringify(classJson)); + vi.spyOn(fs, 'readFileSync').mockImplementation(() => JSON.stringify(classJson)); - const fileContent = - `import { Name } from ""; import { Another } from "@space/package"; export class Test { prop: Name; prop2: Another; }`; + const fileContent = `import { Name } from ""; import { Another } from "@space/package"; export class Test { prop: Name; prop2: Another; }`; appTree.create('test.component.ts', fileContent); const update = new UnitUpdateChanges(__dirname, appTree); expect(update.getClassChanges()).toEqual(classJson); - spyOn(tsUtils, 'getRenamePositions').and.callThrough(); + vi.spyOn(tsUtils, 'getRenamePositions'); update.applyChanges(); - expect(tsUtils.getRenamePositions).toHaveBeenCalledWith('/test.component.ts', 'Name', jasmine.anything()); - expect(tsUtils.getRenamePositions).toHaveBeenCalledWith('/test.component.ts', 'Another', jasmine.anything()); + expect(tsUtils.getRenamePositions).toHaveBeenCalledWith('/test.component.ts', 'Name', expect.anything()); + expect(tsUtils.getRenamePositions).toHaveBeenCalledWith('/test.component.ts', 'Another', expect.anything()); expect(appTree.readContent('test.component.ts')).toEqual(fileContent); }); @@ -466,16 +430,15 @@ describe('UpdateChanges', () => { ] }; const jsonPath = path.join(__dirname, 'changes', 'classes.json'); - spyOn(fs, 'existsSync').and.callFake((filePath: fs.PathLike) => { + vi.spyOn(fs, 'existsSync').mockImplementation((filePath: fs.PathLike) => { if (filePath === jsonPath) { return true; } return false; }); - spyOn(fs, 'readFileSync').and.callFake(() => JSON.stringify(classJson)); + vi.spyOn(fs, 'readFileSync').mockImplementation(() => JSON.stringify(classJson)); - let fileContent = -`import { Size, Type as someThg } from "igniteui-angular"; + let fileContent = `import { Size, Type as someThg } from "igniteui-angular"; import { IgxService, IgxDiffService as eDiffService, Calendar as Calendar } from 'igniteui-angular'; import { Type } from "@angular/core"; export class Test { @@ -495,8 +458,7 @@ export class Test { expect(update.getClassChanges()).toEqual(classJson); update.applyChanges(); - let expectedFileContent = -`import { IgxSize, IgxType as someThg } from "igniteui-angular"; + let expectedFileContent = `import { IgxSize, IgxType as someThg } from "igniteui-angular"; import { IgxService1, IgxNewDiffService as eDiffService, CalendarActual as Calendar } from 'igniteui-angular'; import { Type } from "@angular/core"; export class Test { @@ -518,7 +480,7 @@ export class Test { expect(appTree.readContent('test.component.ts')).toEqual(expectedFileContent); }); - it('should move property value between element tags', done => { + it('should move property value between element tags', async () => { const inputJson: BindingChanges = { changes: [ { @@ -530,13 +492,13 @@ export class Test { ] }; const jsonPath = path.join(__dirname, 'changes', 'inputs.json'); - spyOn(fs, 'existsSync').and.callFake((filePath: fs.PathLike) => { + vi.spyOn(fs, 'existsSync').mockImplementation((filePath: fs.PathLike) => { if (filePath === jsonPath) { return true; } return false; }); - spyOn(fs, 'readFileSync').and.callFake(() => JSON.stringify(inputJson)); + vi.spyOn(fs, 'readFileSync').mockImplementation(() => JSON.stringify(inputJson)); const fileContent = ` @@ -555,19 +517,17 @@ export class Test { expect(update.getInputChanges()).toEqual(inputJson); update.applyChanges(); - expect(appTree.readContent('test.component.html')).toEqual( -`phone + expect(appTree.readContent('test.component.html')).toEqual(`phone build accessory`); - expect(appTree.readContent('test1.component.html')).toEqual( -`{{'phone'}} + expect(appTree.readContent('test1.component.html')).toEqual(`{{'phone'}} {{getName()}}`); - done(); + ; }); - it('should replace/remove properties', done => { + it('should replace/remove properties', async () => { const themeChangesJson: ThemeChanges = { changes: [ { @@ -588,16 +548,15 @@ export class Test { ] }; const jsonPath = path.join(__dirname, 'changes', 'theme-changes.json'); - spyOn(fs, 'existsSync').and.callFake((filePath: fs.PathLike) => { + vi.spyOn(fs, 'existsSync').mockImplementation((filePath: fs.PathLike) => { if (filePath === jsonPath) { return true; } return false; }); - spyOn(fs, 'readFileSync').and.callFake(() => JSON.stringify(themeChangesJson)); + vi.spyOn(fs, 'readFileSync').mockImplementation(() => JSON.stringify(themeChangesJson)); - const fileContent = -`$var: igx-theme-func( + const fileContent = `$var: igx-theme-func( $prop1: red, $replace-me: 3, $remove-me: 0px, @@ -623,8 +582,7 @@ $var3: igx-comp-theme( expect(update.getThemeChanges()).toEqual(themeChangesJson); update.applyChanges(); - expect(appTree.readContent('styles.scss')).toEqual( -`$var: igx-theme-func( + expect(appTree.readContent('styles.scss')).toEqual(`$var: igx-theme-func( $prop1: red, $replaced: 3, $prop2: 2 @@ -639,10 +597,10 @@ $var3: igx-comp-theme( );`); expect(appTree.readContent('src/app/app.component.scss')).toEqual(`igx-comp-theme($replace-me: not, $prop3: 2);`); expect(appTree.readContent('test.component.scss')).toEqual(`igx-theme-func($replaced: 10px, $old-prop: 3, $prop3: 2);`); - done(); + ; }); - it('should replace imports', done => { + it('should replace imports', async () => { const importsJson: ImportsChanges = { changes: [ { @@ -654,13 +612,13 @@ $var3: igx-comp-theme( ] }; const jsonPath = path.join(__dirname, 'changes', 'imports.json'); - spyOn(fs, 'existsSync').and.callFake((filePath: fs.PathLike) => { + vi.spyOn(fs, 'existsSync').mockImplementation((filePath: fs.PathLike) => { if (filePath === jsonPath) { return true; } return false; }); - spyOn(fs, 'readFileSync').and.callFake(() => JSON.stringify(importsJson)); + vi.spyOn(fs, 'readFileSync').mockImplementation(() => JSON.stringify(importsJson)); const fileContent = ` @NgModule({ @@ -701,56 +659,44 @@ export class AppModule { }`; }) export class AppModule { }`); - done(); + ; }); - it('should handle changes with valueTransform functions', done => { + it('should handle changes with valueTransform functions', async () => { const inputsJson: BindingChanges = { changes: [{ - name: 'someProp', - replaceWith: 'someOtherProp', - valueTransform: 'some_prop_transform', - owner: { - selector: 'igx-component', - type: ElementType.Component - } - }] + name: 'someProp', + replaceWith: 'someOtherProp', + valueTransform: 'some_prop_transform', + owner: { + selector: 'igx-component', + type: ElementType.Component + } + }] }; const jsonPath = path.join(__dirname, 'changes', 'inputs.json'); - spyOn(fs, 'existsSync').and.callFake((filePath: fs.PathLike) => { + vi.spyOn(fs, 'existsSync').mockImplementation((filePath: fs.PathLike) => { if (filePath === jsonPath) { return true; } return false; }); - spyOn(fs, 'readFileSync').and.returnValue(JSON.stringify(inputsJson)); + vi.spyOn(fs, 'readFileSync').mockReturnValue(JSON.stringify(inputsJson)); // bracketed - appTree.create( - 'test.component.html', - '' - ); + appTree.create('test.component.html', ''); // No brackets - appTree.create( - 'test2.component.html', - '' - ); + appTree.create('test2.component.html', ''); // Small quotes - appTree.create( - 'test3.component.html', - `` - ); + appTree.create('test3.component.html', ``); // Multiple occurances - appTree.create( - 'test4.component.html', - ` + appTree.create('test4.component.html', ` -` - ); +`); const update = new UnitUpdateChanges(__dirname, appTree); expect(fs.existsSync).toHaveBeenCalledWith(jsonPath); @@ -758,8 +704,9 @@ export class AppModule { }`); expect(update.getInputChanges()).toEqual(inputsJson); update.addValueTransform('some_prop_transform', (args: BoundPropertyObject): void => { if (args.bindingType === InputPropertyType.EVAL) { - args.value = args.value === 'true' ? '\'trueValue\'' : '\'falseValue\''; - } else { + args.value = args.value === 'true' ? '\'trueValue\'' : '\'falseValue\''; + } + else { args.value = args.value === 'true' ? 'trueValue' : 'falseValue'; } }); @@ -769,46 +716,40 @@ export class AppModule { }`); expect(appTree.readContent('test2.component.html')).toEqual(``); expect(appTree.readContent('test3.component.html')).toEqual(``); expect(appTree.readContent('test4.component.html')).toEqual(`\n` + -// eslint-disable-next-line max-len -` + // eslint-disable-next-line max-len + ` `); - done(); + ; }); - it('Should be able to change binding type via transform function', done => { + it('Should be able to change binding type via transform function', async () => { const inputsJson: BindingChanges = { changes: [{ - name: 'prop', - replaceWith: 'newProp', - valueTransform: 'prop_transform', - owner: { - selector: 'igx-component', - type: ElementType.Component - } - }] + name: 'prop', + replaceWith: 'newProp', + valueTransform: 'prop_transform', + owner: { + selector: 'igx-component', + type: ElementType.Component + } + }] }; const jsonPath = path.join(__dirname, 'changes', 'inputs.json'); - spyOn(fs, 'existsSync').and.callFake((filePath: fs.PathLike) => { + vi.spyOn(fs, 'existsSync').mockImplementation((filePath: fs.PathLike) => { if (filePath === jsonPath) { return true; } return false; }); - spyOn(fs, 'readFileSync').and.returnValue(JSON.stringify(inputsJson)); + vi.spyOn(fs, 'readFileSync').mockReturnValue(JSON.stringify(inputsJson)); // bracketed - appTree.create( - 'test-bound-to-string.component.html', - `STRING + appTree.create('test-bound-to-string.component.html', `STRING STRING -BOUND` - ); - appTree.create( - 'test-string-to-bound.component.html', - `BOUND -STRING` - ); +BOUND`); + appTree.create('test-string-to-bound.component.html', `BOUND +STRING`); const update = new UnitUpdateChanges(__dirname, appTree); expect(fs.existsSync).toHaveBeenCalledWith(jsonPath); @@ -820,7 +761,7 @@ export class AppModule { }`); case 'true': args.value = 'TRUTHY-STRING-VALUE'; args.bindingType = InputPropertyType.STRING; - break; + break; case 'false': args.value = 'FALSY-STRING-VALUE'; args.bindingType = InputPropertyType.STRING; @@ -828,7 +769,8 @@ export class AppModule { }`); default: args.value += ' ? true : false'; } - } else { + } + else { if (args.value === 'changeThisToBound') { args.bindingType = InputPropertyType.EVAL; args.value = 'true'; @@ -837,14 +779,12 @@ export class AppModule { }`); }); update.applyChanges(); - expect(appTree.readContent('test-bound-to-string.component.html')).toEqual( -`STRING + expect(appTree.readContent('test-bound-to-string.component.html')).toEqual(`STRING STRING BOUND`); - expect(appTree.readContent('test-string-to-bound.component.html')).toEqual( -`BOUND + expect(appTree.readContent('test-string-to-bound.component.html')).toEqual(`BOUND STRING`); - done(); + ; }); describe('Project loading', () => { @@ -868,7 +808,7 @@ export class AppModule { }`); appTree.create(sassFile, ''); // skip loading json config files - spyOn(fs, 'existsSync').and.returnValue(false); + vi.spyOn(fs, 'existsSync').mockReturnValue(false); const update = new UnitUpdateChanges(__dirname, appTree); expect(update.tsFiles).toContain(tsFile); @@ -911,7 +851,7 @@ export class AppModule { }`); } // skip loading json config files - spyOn(fs, 'existsSync').and.returnValue(false); + vi.spyOn(fs, 'existsSync').mockReturnValue(false); const update = new UnitUpdateChanges(__dirname, appTree); for (const projName of Object.keys(workspace.projects)) { @@ -935,13 +875,10 @@ export class AppModule { }`); const jsonPath = path.join(__dirname, 'changes', 'members.json'); // leave callThrough on spies for other files the LS test might want to load: - spyOn(fs, 'existsSync').and.callThrough() - .withArgs(jsonPath).and.returnValue(true); - spyOn(fs, 'readFileSync').and.callThrough() - .withArgs(jsonPath, jasmine.any(String)).and.returnValue(JSON.stringify(selectorsJson)); + vi.spyOn(fs, 'existsSync').withArgs(jsonPath).mockReturnValue(true); + vi.spyOn(fs, 'readFileSync').withArgs(jsonPath, expect.any(String)).mockReturnValue(JSON.stringify(selectorsJson)); - const fileContent = -`import { Component } from '@angular/core'; + const fileContent = `import { Component } from '@angular/core'; import { IgxGridComponent, IGridKeydownEventArgs } from 'igniteui-angular'; @Component({ selector: 'app-custom-grid', @@ -955,8 +892,7 @@ export class CustomGridComponent { } `; appTree.create('test.component.ts', fileContent); - const expectedFileContent = -`import { Component } from '@angular/core'; + const expectedFileContent = `import { Component } from '@angular/core'; import { IgxGridComponent, IGridKeydownEventArgs } from 'igniteui-angular'; @Component({ selector: 'app-custom-grid', @@ -975,7 +911,7 @@ export class CustomGridComponent { }); }); - it('Should migrate sass variables names correctly', ()=> { + it('Should migrate sass variables names correctly', () => { const themeChangesJson: ThemeChanges = { changes: [ { @@ -1011,16 +947,15 @@ export class CustomGridComponent { ] }; const jsonPath = path.join(__dirname, 'changes', 'theme-changes.json'); - spyOn(fs, 'existsSync').and.callFake((filePath: fs.PathLike) => { + vi.spyOn(fs, 'existsSync').mockImplementation((filePath: fs.PathLike) => { if (filePath === jsonPath) { return true; } return false; }); - spyOn(fs, 'readFileSync').and.callFake(() => JSON.stringify(themeChangesJson)); + vi.spyOn(fs, 'readFileSync').mockImplementation(() => JSON.stringify(themeChangesJson)); - const fileContent = -`$palette: $light-material-palette; + const fileContent = `$palette: $light-material-palette; $light-material-palette : $some-variable, $palette2: $light-material-palette-primary; $palette3: mat.define-light-theme($light-palette-primary, $elevation, $light-palette); @@ -1046,8 +981,7 @@ $header-border-color: igx-color($dark-theme-palette, "primary", 600) ); `; appTree.create('test.component.scss', fileContent); - const expectedFileContent = -`$palette: $igx-light-material-palette; + const expectedFileContent = `$palette: $igx-light-material-palette; $igx-light-material-palette : $some-variable, $palette2: $light-material-palette-primary; $palette3: mat.define-light-theme($light-palette-primary, $igx-elevation, $igx-light-palette); @@ -1073,10 +1007,10 @@ $header-border-color: igx-color($dark-theme-palette, "primary", 600) ); `; - const update = new UnitUpdateChanges(__dirname, appTree); + const update = new UnitUpdateChanges(__dirname, appTree); - update.applyChanges(); - expect(appTree.readContent('test.component.scss')).toEqual(expectedFileContent); + update.applyChanges(); + expect(appTree.readContent('test.component.scss')).toEqual(expectedFileContent); }); it('Should migrate aliased scss functions', () => { @@ -1106,16 +1040,15 @@ $header-border-color: igx-color($dark-theme-palette, "primary", 600) }; const jsonPath = path.join(__dirname, 'changes', 'theme-changes.json'); - spyOn(fs, 'existsSync').and.callFake((filePath: fs.PathLike) => { + vi.spyOn(fs, 'existsSync').mockImplementation((filePath: fs.PathLike) => { if (filePath === jsonPath) { return true; } return false; }); - spyOn(fs, 'readFileSync').and.callFake(() => JSON.stringify(themeChangesJson)); + vi.spyOn(fs, 'readFileSync').mockImplementation(() => JSON.stringify(themeChangesJson)); - const fileContent = -`@use 'igniteui-angular/theming' as igniteui1; + const fileContent = `@use 'igniteui-angular/theming' as igniteui1; @use 'igniteui-angular/theme' as igniteui2; @use 'igniteui-angular/lib/core/styles/themes/index' as igniteui3; @use 'some/url' as my-namespace; @@ -1129,8 +1062,7 @@ $my-other-theme: my-namespace.function1($color1: igniteui2.igx-contrast-color($p appTree.create('test.component.scss', fileContent); - const expectedFileContent = -`@use 'igniteui-angular/theming' as igniteui1; + const expectedFileContent = `@use 'igniteui-angular/theming' as igniteui1; @use 'igniteui-angular/theme' as igniteui2; @use 'igniteui-angular/lib/core/styles/themes/index' as igniteui3; @use 'some/url' as my-namespace; @@ -1174,16 +1106,15 @@ $my-other-theme: my-namespace.function1($color1: igniteui2.contrast-color($palet }; const jsonPath = path.join(__dirname, 'changes', 'theme-changes.json'); - spyOn(fs, 'existsSync').and.callFake((filePath: fs.PathLike) => { + vi.spyOn(fs, 'existsSync').mockImplementation((filePath: fs.PathLike) => { if (filePath === jsonPath) { return true; } return false; }); - spyOn(fs, 'readFileSync').and.callFake(() => JSON.stringify(themeChangesJson)); + vi.spyOn(fs, 'readFileSync').mockImplementation(() => JSON.stringify(themeChangesJson)); - const fileContent = -`@use 'igniteui-angular/theming' as *; + const fileContent = `@use 'igniteui-angular/theming' as *; @use 'some/url' as my-namespace; $my-palette: igx-palette($primary: red, $secondary: blue); @@ -1195,8 +1126,7 @@ $my-other-theme: my-namespace.function1($color1: igx-contrast-color($palette: ig appTree.create('test.component.scss', fileContent); - const expectedFileContent = -`@use 'igniteui-angular/theming' as *; + const expectedFileContent = `@use 'igniteui-angular/theming' as *; @use 'some/url' as my-namespace; $my-palette: palette($primary: red, $secondary: blue); @@ -1233,16 +1163,15 @@ $my-other-theme: my-namespace.function1($color1: contrast-color($palette: palett }; const jsonPath = path.join(__dirname, 'changes', 'theme-changes.json'); - spyOn(fs, 'existsSync').and.callFake((filePath: fs.PathLike) => { + vi.spyOn(fs, 'existsSync').mockImplementation((filePath: fs.PathLike) => { if (filePath === jsonPath) { return true; } return false; }); - spyOn(fs, 'readFileSync').and.callFake(() => JSON.stringify(themeChangesJson)); + vi.spyOn(fs, 'readFileSync').mockImplementation(() => JSON.stringify(themeChangesJson)); - const fileContent = -`@use 'igniteui-angular/theming' as igniteui1; + const fileContent = `@use 'igniteui-angular/theming' as igniteui1; @use 'igniteui-angular/lib/core/styles/themes/index' as igniteui3; @use 'igniteui-angular/theme' as igniteui2; @use 'some/url' as my-namespace; @@ -1255,8 +1184,7 @@ $my-other-theme: my-namespace.function1($color1: contrast-color($palette: palett appTree.create('test.component.scss', fileContent); - const expectedFileContent = -`@use 'igniteui-angular/theming' as igniteui1; + const expectedFileContent = `@use 'igniteui-angular/theming' as igniteui1; @use 'igniteui-angular/lib/core/styles/themes/index' as igniteui3; @use 'igniteui-angular/theme' as igniteui2; @use 'some/url' as my-namespace; @@ -1294,16 +1222,15 @@ $my-other-theme: my-namespace.function1($color1: contrast-color($palette: palett }; const jsonPath = path.join(__dirname, 'changes', 'theme-changes.json'); - spyOn(fs, 'existsSync').and.callFake((filePath: fs.PathLike) => { + vi.spyOn(fs, 'existsSync').mockImplementation((filePath: fs.PathLike) => { if (filePath === jsonPath) { return true; } return false; }); - spyOn(fs, 'readFileSync').and.callFake(() => JSON.stringify(themeChangesJson)); + vi.spyOn(fs, 'readFileSync').mockImplementation(() => JSON.stringify(themeChangesJson)); - const fileContent = -`@use 'igniteui-angular/theming' as *; + const fileContent = `@use 'igniteui-angular/theming' as *; @use 'some/url' as my-namespace; @include igx-theme($palette: $my-palette); @@ -1314,8 +1241,7 @@ $my-other-theme: my-namespace.function1($color1: contrast-color($palette: palett appTree.create('test.component.scss', fileContent); - const expectedFileContent = -`@use 'igniteui-angular/theming' as *; + const expectedFileContent = `@use 'igniteui-angular/theming' as *; @use 'some/url' as my-namespace; @include theme($palette: $my-palette); diff --git a/projects/igniteui-angular/migrations/common/setup.spec.ts b/projects/igniteui-angular/migrations/common/setup.spec.ts index 3c001e78587..4b070643b83 100644 --- a/projects/igniteui-angular/migrations/common/setup.spec.ts +++ b/projects/igniteui-angular/migrations/common/setup.spec.ts @@ -39,14 +39,15 @@ const tsConfig = readFileSync('tsconfig.json'); class IgxUnitTestTree extends UnitTestTree { public override create(path: string, content: string | Buffer): void { super.create(path, content); - if (!path.endsWith('.ts') && !path.endsWith('.html')) return; + if (!path.endsWith('.ts') && !path.endsWith('.html')) + return; const configured = serviceContainer.configured && serviceContainer.projectService.configuredProjects.size; if (configured) { // rush host update serviceContainer.serverHost.host = this; - const entryPath = tss.server.toNormalizedPath(join(process.cwd(), path)) + const entryPath = tss.server.toNormalizedPath(join(process.cwd(), path)); const scriptInfo = serviceContainer.projectService?.getOrCreateScriptInfoForNormalizedPath(entryPath, false); if (!scriptInfo) { return; @@ -58,11 +59,13 @@ class IgxUnitTestTree extends UnitTestTree { scriptInfo.attachToProject(project); // add root in advance for ng LS discovery if two files test.component.ts/html and html is analyzed first project.addMissingFileRoot(scriptInfo.fileName); - } else { + } + else { // if using same file, force-reload from host for new content scriptInfo.reloadFromFile(tss.server.asNormalizedPath(entryPath)); } - } else { + } + else { // strip leading slash as it messes with the resolve and assign as new main entry path = path.startsWith('/') ? path.substring(1) : path; const config = JSON.parse(this.readContent('angular.json')); diff --git a/projects/igniteui-angular/migrations/update-10_1_0/index.spec.ts b/projects/igniteui-angular/migrations/update-10_1_0/index.spec.ts index c5f476095e5..c4b4af05a81 100644 --- a/projects/igniteui-angular/migrations/update-10_1_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-10_1_0/index.spec.ts @@ -1,6 +1,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Update 10.1.0', () => { let appTree: UnitTestTree; @@ -11,9 +12,7 @@ describe('Update 10.1.0', () => { }); it('should upgrade the igx-action-icon to igx-navbar-action', async () => { - appTree.create( - '/testSrc/appPrefix/component/custom.component.html', - ` + appTree.create('/testSrc/appPrefix/component/custom.component.html', ` arrow_back @@ -21,8 +20,7 @@ describe('Update 10.1.0', () => { const tree = await schematicRunner.runSchematic('migration-16', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/custom.component.html')) - .toEqual( - ` + .toEqual(` arrow_back @@ -30,8 +28,7 @@ describe('Update 10.1.0', () => { }); it('should update IgxActionIconDirective to IgxNavbarActionDirective', async () => { - appTree.create('/testSrc/appPrefix/component/custom.component.ts', - `import { IgxActionIconDirective } from 'igniteui-angular'; + appTree.create('/testSrc/appPrefix/component/custom.component.ts', `import { IgxActionIconDirective } from 'igniteui-angular'; export class TestNavbar { @ViewChild(IgxActionIconDirective, { read: IgxActionIconDirective }) private actionIcon: IgxActionIconDirective; }`); @@ -39,16 +36,14 @@ describe('Update 10.1.0', () => { const tree = await schematicRunner.runSchematic('migration-16', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/custom.component.ts')) - .toEqual( - `import { IgxNavbarActionDirective } from 'igniteui-angular'; + .toEqual(`import { IgxNavbarActionDirective } from 'igniteui-angular'; export class TestNavbar { @ViewChild(IgxNavbarActionDirective, { read: IgxNavbarActionDirective }) private actionIcon: IgxNavbarActionDirective; }`); }); it('should update DropPosition.None', async () => { - const origFileContent = - `import { Component, Injectable, ViewChild } from "@angular/core";` + + const origFileContent = `import { Component, Injectable, ViewChild } from "@angular/core";` + `import { IgxGridComponent, DropPosition } from "igniteui-angular";` + `import { IgxColumnComponent } from "igniteui-angular";\r\n` + `@Component({` + @@ -62,8 +57,7 @@ describe('Update 10.1.0', () => { ` this.grid1.moveColumn(col1, col2, DropPosition.None);` + ` }` + `}`; - const expectedFileContent = - `import { Component, Injectable, ViewChild } from "@angular/core";` + + const expectedFileContent = `import { Component, Injectable, ViewChild } from "@angular/core";` + `import { IgxGridComponent, DropPosition } from "igniteui-angular";` + `import { IgxColumnComponent } from "igniteui-angular";\r\n` + `@Component({` + @@ -77,9 +71,7 @@ describe('Update 10.1.0', () => { ` this.grid1.moveColumn(col1, col2, DropPosition.AfterDropTarget);` + ` }` + `}`; - appTree.create( - '/testSrc/appPrefix/component/drop.component.ts', - origFileContent); + appTree.create('/testSrc/appPrefix/component/drop.component.ts', origFileContent); const tree = await schematicRunner.runSchematic('migration-16', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/drop.component.ts')) @@ -87,10 +79,7 @@ describe('Update 10.1.0', () => { }); it('should replace onDataPreLoad with onScroll ', async () => { - appTree.create( - `/testSrc/appPrefix/component/tree-grid.component.html`, - '' - ); + appTree.create(`/testSrc/appPrefix/component/tree-grid.component.html`, ''); const tree = await schematicRunner.runSchematic('migration-16', {}, appTree); diff --git a/projects/igniteui-angular/migrations/update-10_2_0/index.spec.ts b/projects/igniteui-angular/migrations/update-10_2_0/index.spec.ts index 46cc22eaff7..e198a0d176e 100644 --- a/projects/igniteui-angular/migrations/update-10_2_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-10_2_0/index.spec.ts @@ -1,41 +1,31 @@ import * as path from 'path'; -import { - SchematicTestRunner, - UnitTestTree, -} from '@angular-devkit/schematics/testing'; +import { SchematicTestRunner, UnitTestTree, } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Update 10.2.0', () => { let appTree: UnitTestTree; - const schematicRunner = new SchematicTestRunner( - 'ig-migrate', - path.join(__dirname, '../migration-collection.json') - ); + const schematicRunner = new SchematicTestRunner('ig-migrate', path.join(__dirname, '../migration-collection.json')); beforeEach(() => { appTree = setupTestTree(); }); it('should remove the type property if the value is not a valid type', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', - // eslint-disable-next-line max-len - `` - ); + appTree.create('/testSrc/appPrefix/component/test.component.html', + // eslint-disable-next-line max-len + ``); const tree = await schematicRunner .runSchematic('migration-17', {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html') // eslint-disable-next-line max-len ).toEqual(``); }); it('Should remove references to deprecated `pane` property of `IExpansionPanelEventArgs`', async () => { - appTree.create( - '/testSrc/appPrefix/component/expansion-test.component.ts', - `import { Component, ViewChild } from '@angular/core'; + appTree.create('/testSrc/appPrefix/component/expansion-test.component.ts', `import { Component, ViewChild } from '@angular/core'; import { IExpansionPanelEventArgs, IgxExpansionPanelComponent } from 'igniteui-angular'; @Component({ @@ -51,12 +41,12 @@ export class ExpansionTestComponent { public onPanelOpened(event: IExpansionPanelEventArgs) { console.log(event.panel); } -}` - ); +}`); const tree = await schematicRunner .runSchematic('migration-17', {}, appTree); - const expectedContent = `import { Component, ViewChild } from '@angular/core'; + const expectedContent = `import { Component, ViewChild } from '@angular/core'; import { IExpansionPanelEventArgs, IgxExpansionPanelComponent } from 'igniteui-angular'; +import { describe, it, expect, beforeEach } from 'vitest'; @Component({ selector: 'app-expansion-test', @@ -72,8 +62,6 @@ export class ExpansionTestComponent { console.log(event.owner); } }`; - expect( - tree.readContent('/testSrc/appPrefix/component/expansion-test.component.ts') - ).toEqual(expectedContent); + expect(tree.readContent('/testSrc/appPrefix/component/expansion-test.component.ts')).toEqual(expectedContent); }); }); diff --git a/projects/igniteui-angular/migrations/update-11_0_0/index.spec.ts b/projects/igniteui-angular/migrations/update-11_0_0/index.spec.ts index da54de3ec0b..44310d2603e 100644 --- a/projects/igniteui-angular/migrations/update-11_0_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-11_0_0/index.spec.ts @@ -2,13 +2,11 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Update to 11.0.0', () => { let appTree: UnitTestTree; - const runner = new SchematicTestRunner( - 'ig-migrate', - path.join(__dirname, '../migration-collection.json') - ); + const runner = new SchematicTestRunner('ig-migrate', path.join(__dirname, '../migration-collection.json')); const migrationName = 'migration-18'; const warnMsg = `\n\n`; const stripWhitespaceRe = /\s/g; @@ -61,9 +59,7 @@ describe('Update to 11.0.0', () => { const tree = await runner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent(makeTemplate('toolbar')) - ).toEqual(`\n\nLook, some content`); + expect(tree.readContent(makeTemplate('toolbar'))).toEqual(`\n\nLook, some content`); }); it('should correctly migrate bound property with ngIf', async () => { @@ -71,9 +67,7 @@ describe('Update to 11.0.0', () => { const tree = await runner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent(makeTemplate('toolbar')) - ).toEqual(`\n\n`); + expect(tree.readContent(makeTemplate('toolbar'))).toEqual(`\n\n`); }); it('should correctly migrate template directive without messing other templates', async () => { @@ -81,9 +75,7 @@ describe('Update to 11.0.0', () => { const tree = await runner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent(makeTemplate('toolbar')).replace(stripWhitespaceRe, '') - ).toEqual(` + expect(tree.readContent(makeTemplate('toolbar')).replace(stripWhitespaceRe, '')).toEqual(` ${warnMsg} @@ -94,8 +86,7 @@ describe('Update to 11.0.0', () => { Bla Bla Bla -`.replace(stripWhitespaceRe, '') - ); +`.replace(stripWhitespaceRe, '')); }); it('should correctly migrate hierarchical grid toolbar(s)', async () => { @@ -103,9 +94,7 @@ describe('Update to 11.0.0', () => { const tree = await runner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent(makeTemplate('toolbar')).replace(stripWhitespaceRe, '') - ).toEqual(` + expect(tree.readContent(makeTemplate('toolbar')).replace(stripWhitespaceRe, '')).toEqual(` @@ -122,9 +111,7 @@ describe('Update to 11.0.0', () => { const tree = await runner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent(makeTemplate('toolbar')).replace(stripWhitespaceRe, '') - ).toEqual(` + expect(tree.readContent(makeTemplate('toolbar')).replace(stripWhitespaceRe, '')).toEqual(` @@ -140,7 +127,6 @@ describe('Update to 11.0.0', () => { - `.replace(stripWhitespaceRe, '') - ); + `.replace(stripWhitespaceRe, '')); }); }); diff --git a/projects/igniteui-angular/migrations/update-11_1_0/index.spec.ts b/projects/igniteui-angular/migrations/update-11_1_0/index.spec.ts index aa54dd0e083..af3d863fe63 100644 --- a/projects/igniteui-angular/migrations/update-11_1_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-11_1_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Update to 11.1.0', () => { let appTree: UnitTestTree; @@ -13,38 +14,27 @@ describe('Update to 11.1.0', () => { }); it('should update fontSet to family', async () => { - appTree.create( - `/testSrc/appPrefix/component/icon.component.html`, - 'settings' - ); + appTree.create(`/testSrc/appPrefix/component/icon.component.html`, 'settings'); const tree = await runner .runSchematic('migration-19', {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/icon.component.html') - ).toEqual('settings'); + expect(tree.readContent('/testSrc/appPrefix/component/icon.component.html')).toEqual('settings'); }); it('should update isActive to active', async () => { - appTree.create( - `/testSrc/appPrefix/component/icon.component.html`, - 'settings' - ); + appTree.create(`/testSrc/appPrefix/component/icon.component.html`, 'settings'); const tree = await runner .runSchematic('migration-19', {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/icon.component.html') - ).toEqual('settings'); + expect(tree.readContent('/testSrc/appPrefix/component/icon.component.html')).toEqual('settings'); }); it('should migrate updated getter names', async () => { - appTree.create( - '/testSrc/appPrefix/component/icon-test.component.ts', - `import { Component, ViewChild } from '@angular/core'; + appTree.create('/testSrc/appPrefix/component/icon-test.component.ts', `import { Component, ViewChild } from '@angular/core'; import { IgxIconModule, IgxIconComponent } from 'igniteui-angular'; +import { describe, it, expect, beforeEach } from 'vitest'; @Component({ selector: 'app-icon-test', @@ -96,17 +86,11 @@ export class IconTestComponent { }); `; - expect( - tree.readContent( - '/testSrc/appPrefix/component/icon-test.component.ts' - ) - ).toEqual(expectedContent); + expect(tree.readContent('/testSrc/appPrefix/component/icon-test.component.ts')).toEqual(expectedContent); }); it('should migrate updated members names', async () => { - appTree.create( - '/testSrc/appPrefix/component/icon-test.component.ts', - `import { Component } from '@angular/core'; + appTree.create('/testSrc/appPrefix/component/icon-test.component.ts', `import { Component } from '@angular/core'; import { IgxIconService } from 'igniteui-angular'; @Component({ @@ -153,17 +137,11 @@ export class IconTestComponent { }); `; - expect( - tree.readContent( - '/testSrc/appPrefix/component/icon-test.component.ts' - ) - ).toEqual(expectedContent); + expect(tree.readContent('/testSrc/appPrefix/component/icon-test.component.ts')).toEqual(expectedContent); }); it('should replace on-prefixed outputs in chip and chips-area', async () => { - appTree.create( - `/testSrc/appPrefix/component/chips.component.html`, - ` {{chip.text}} - ` - ); + `); const tree = await runner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/chips.component.html')) @@ -210,100 +187,63 @@ export class IconTestComponent { }); it('should replace IgxTabsComponent event name onTabItemSelected with tabItemSelected', async () => { - appTree.create( - `/testSrc/appPrefix/component/tabs.component.html`, - `` - ); + appTree.create(`/testSrc/appPrefix/component/tabs.component.html`, ``); const tree = await runner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/tabs.component.html') - ).toEqual(``); + expect(tree.readContent('/testSrc/appPrefix/component/tabs.component.html')).toEqual(``); }); it('should replace IgxTabsComponent event name onTabItemDeselected with tabItemDeselected', async () => { - appTree.create( - `/testSrc/appPrefix/component/tabs.component.html`, - `` - ); + appTree.create(`/testSrc/appPrefix/component/tabs.component.html`, ``); const tree = await runner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/tabs.component.html') - ).toEqual(``); + expect(tree.readContent('/testSrc/appPrefix/component/tabs.component.html')).toEqual(``); }); it('should replace IgxListComponent event name onLeftPan with leftPan', async () => { - appTree.create( - `/testSrc/appPrefix/component/list.component.html`, - `` - ); + appTree.create(`/testSrc/appPrefix/component/list.component.html`, ``); const tree = await runner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/list.component.html') - ).toEqual(``); + expect(tree.readContent('/testSrc/appPrefix/component/list.component.html')).toEqual(``); }); it('should replace IgxListComponent event name onRightPan with rightPan', async () => { - appTree.create( - `/testSrc/appPrefix/component/list.component.html`, - `` - ); + appTree.create(`/testSrc/appPrefix/component/list.component.html`, ``); const tree = await runner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/list.component.html') - ).toEqual(``); + expect(tree.readContent('/testSrc/appPrefix/component/list.component.html')).toEqual(``); }); it('should replace IgxListComponent event name onPanStateChange with panStateChange', async () => { - appTree.create( - `/testSrc/appPrefix/component/list.component.html`, - `` - ); + appTree.create(`/testSrc/appPrefix/component/list.component.html`, ``); const tree = await runner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/list.component.html') - ).toEqual(``); + expect(tree.readContent('/testSrc/appPrefix/component/list.component.html')).toEqual(``); }); it('should replace IgxListComponent event name OnItemClicked with itemClicked', async () => { - appTree.create( - `/testSrc/appPrefix/component/list.component.html`, - `` - ); + appTree.create(`/testSrc/appPrefix/component/list.component.html`, ``); const tree = await runner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/list.component.html') - ).toEqual(``); + expect(tree.readContent('/testSrc/appPrefix/component/list.component.html')).toEqual(``); }); it('should replace IgxNavbarComponent event name onAction with action', async () => { - appTree.create( - `/testSrc/appPrefix/component/navbar.component.html`, - `` - ); + appTree.create(`/testSrc/appPrefix/component/navbar.component.html`, ``); const tree = await runner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/navbar.component.html') - ).toEqual(``); + expect(tree.readContent('/testSrc/appPrefix/component/navbar.component.html')).toEqual(``); }); it('should update Excel exporter onExportEnded event name to exportEnded', async () => { - appTree.create( - '/testSrc/appPrefix/component/excel-export.component.ts', -`import { Component } from '@angular/core'; + appTree.create('/testSrc/appPrefix/component/excel-export.component.ts', `import { Component } from '@angular/core'; import { IgxExcelExporterService } from "igniteui-angular"; @Component({ @@ -327,8 +267,7 @@ export class ExcelExportComponent { const tree = await runner .runSchematic('migration-19', {}, appTree); - const expectedContent = -`import { Component } from '@angular/core'; + const expectedContent = `import { Component } from '@angular/core'; import { IgxExcelExporterService } from "igniteui-angular"; @Component({ @@ -349,17 +288,11 @@ export class ExcelExportComponent { }); `; - expect( - tree.readContent( - '/testSrc/appPrefix/component/excel-export.component.ts' - ) - ).toEqual(expectedContent); + expect(tree.readContent('/testSrc/appPrefix/component/excel-export.component.ts')).toEqual(expectedContent); }); it('should update CSV exporter onExportEnded event name to exportEnded', async () => { - appTree.create( - '/testSrc/appPrefix/component/csv-export.component.ts', -`import { Component } from '@angular/core'; + appTree.create('/testSrc/appPrefix/component/csv-export.component.ts', `import { Component } from '@angular/core'; import { IgxCsvExporterService } from "igniteui-angular"; @Component({ @@ -383,8 +316,7 @@ export class CsvExportComponent { const tree = await runner .runSchematic('migration-19', {}, appTree); - const expectedContent = -`import { Component } from '@angular/core'; + const expectedContent = `import { Component } from '@angular/core'; import { IgxCsvExporterService } from "igniteui-angular"; @Component({ @@ -404,90 +336,64 @@ export class CsvExportComponent { providers: [IgxCsvExporterService] }); `; - expect( - tree.readContent( - '/testSrc/appPrefix/component/csv-export.component.ts' - ) - ).toEqual(expectedContent); + expect(tree.readContent('/testSrc/appPrefix/component/csv-export.component.ts')).toEqual(expectedContent); }); it('should replace onSelect and onUnselect with selected and deselected in igx-buttongroup', async () => { - appTree.create( - `/testSrc/appPrefix/component/buttongroup.component.html`, - ` - ` - ); + `); const tree = await runner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/buttongroup.component.html')).toEqual( - ` - ` - ); + `); }); it('should replace onAction with clicked in igx-snackbar', async () => { - appTree.create( - `/testSrc/appPrefix/component/snackbar.component.html`, - `` - ); + appTree.create(`/testSrc/appPrefix/component/snackbar.component.html`, ``); const tree = await runner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/snackbar.component.html')).toEqual( - `` - ); + expect(tree.readContent('/testSrc/appPrefix/component/snackbar.component.html')).toEqual(``); }); it('should replace onShowing, onShown, onHiding, onHidden with showing, shown, hiding, hidden in igx-toast', async () => { - appTree.create( - `/testSrc/appPrefix/component/toast.component.html`, - ` - ` - ); + `); const tree = await runner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/toast.component.html')).toEqual( - ` - ` - ); + `); }); - it('should replace IgxTooltipTargetDirective event names onTooltipShow and onTooltipHide with tooltipShow and tooltipHide', - async () => { - appTree.create( - `/testSrc/appPrefix/component/tooltip.component.html`, - `
Hello, I am a tooltip! -
` - ); +
`); const tree = await runner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/tooltip.component.html') - ).toEqual( - `
@@ -496,108 +402,81 @@ export class CsvExportComponent { }); it('should replace outputs with selected in igx-calendar', async () => { - appTree.create( - `/testSrc/appPrefix/component/calendar.component.html`, -`` - ); +>`); const tree = await runner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/calendar.component.html')).toEqual( -`` - ); +>`); }); it('should replace onSelection and onYearSelection with selected in igx-years-view', async () => { - appTree.create( - `/testSrc/appPrefix/component/yearsview.component.html`, -`` - ); +>`); const tree = await runner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/yearsview.component.html')).toEqual( -`` - ); +>`); }); it('should replace onDateSelection and onViewChanging with selected in igx-days-view', async () => { - appTree.create( - `/testSrc/appPrefix/component/daysview.component.html`, -`` - ); +>`); const tree = await runner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/daysview.component.html')).toEqual( -`` - ); +>`); }); it('should replace onSelection and onMonthSelection with selected in igx-months-view', async () => { - appTree.create( - `/testSrc/appPrefix/component/monthsview.component.html`, -`` - ); +>`); const tree = await runner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/monthsview.component.html')).toEqual( -`` - ); +>`); }); it('should replace onSelection and onMonthSelection with selected in igx-month-picker', async () => { - appTree.create( - `/testSrc/appPrefix/component/monthpicker.component.html`, -`` - ); +>`); const tree = await runner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/monthpicker.component.html')).toEqual( -`` - ); +>`); }); it('should update Excel exporter onColumnExport and onRowExport event names to columnmExporting and rowExporting', async () => { - appTree.create( - '/testSrc/appPrefix/component/excel-export.component.ts', -`import { Component } from '@angular/core'; + appTree.create('/testSrc/appPrefix/component/excel-export.component.ts', `import { Component } from '@angular/core'; import { IgxExcelExporterService } from "igniteui-angular"; @Component({ @@ -622,8 +501,7 @@ export class ExcelExportComponent { const tree = await runner .runSchematic('migration-19', {}, appTree); - const expectedContent = -`import { Component } from '@angular/core'; + const expectedContent = `import { Component } from '@angular/core'; import { IgxExcelExporterService } from "igniteui-angular"; @Component({ @@ -645,17 +523,11 @@ export class ExcelExportComponent { }); `; - expect( - tree.readContent( - '/testSrc/appPrefix/component/excel-export.component.ts' - ) - ).toEqual(expectedContent); + expect(tree.readContent('/testSrc/appPrefix/component/excel-export.component.ts')).toEqual(expectedContent); }); it('should update CSV exporter onColumnExport and onRowExport event names to columnmExporting and rowExporting', async () => { - appTree.create( - '/testSrc/appPrefix/component/csv-export.component.ts', -`import { Component } from '@angular/core'; + appTree.create('/testSrc/appPrefix/component/csv-export.component.ts', `import { Component } from '@angular/core'; import { IgxCsvExporterService } from "igniteui-angular"; @Component({ @@ -680,8 +552,7 @@ export class CsvExportComponent { const tree = await runner .runSchematic('migration-19', {}, appTree); - const expectedContent = -`import { Component } from '@angular/core'; + const expectedContent = `import { Component } from '@angular/core'; import { IgxCsvExporterService } from "igniteui-angular"; @Component({ @@ -702,10 +573,6 @@ export class CsvExportComponent { providers: [IgxCsvExporterService] }); `; - expect( - tree.readContent( - '/testSrc/appPrefix/component/csv-export.component.ts' - ) - ).toEqual(expectedContent); + expect(tree.readContent('/testSrc/appPrefix/component/csv-export.component.ts')).toEqual(expectedContent); }); }); diff --git a/projects/igniteui-angular/migrations/update-12_0_0/index.spec.ts b/projects/igniteui-angular/migrations/update-12_0_0/index.spec.ts index 97edcc18b03..0fc194e9c12 100644 --- a/projects/igniteui-angular/migrations/update-12_0_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-12_0_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '12.0.0'; @@ -17,9 +18,7 @@ describe(`Update to ${version}`, () => { }); it('should update avatar theme args', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, ` $theme: igx-avatar-theme( $initials-background: white, $icon-background: green, @@ -29,98 +28,70 @@ $theme: igx-avatar-theme( $border-radius-round: 14px, $border-radius-square: 12px ); -` - ); +`); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.scss') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(` $theme: igx-avatar-theme( $background: white, $color: black, $border-radius: 14px ); -` - ); +`); }); it('should update onColumnChange', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` -` - ); +`); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` -` - ); +`); }); it('should replace onValueChange and onValueChanged with valueChange and dragFinished in igx-slider', async () => { - appTree.create( - `/testSrc/appPrefix/component/slider.component.html`, - `` - ); + >`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/slider.component.html')).toEqual( - `` - ); + >`); }); it('should replace onProgressChanged with progressChanged in igx-linear-bar', async () => { - appTree.create( - `/testSrc/appPrefix/component/linear.component.html`, - `` - ); + appTree.create(`/testSrc/appPrefix/component/linear.component.html`, ``); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/linear.component.html')).toEqual( - `` - ); + expect(tree.readContent('/testSrc/appPrefix/component/linear.component.html')).toEqual(``); }); it('should replace onProgressChanged with progressChanged in igx-circular-bar', async () => { - appTree.create( - `/testSrc/appPrefix/component/circular.component.html`, - `` - ); + appTree.create(`/testSrc/appPrefix/component/circular.component.html`, ``); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/circular.component.html')).toEqual( - `` - ); + expect(tree.readContent('/testSrc/appPrefix/component/circular.component.html')).toEqual(``); }); // IgxTabs it('Should update igx-tab-group to igx-tab-item', async () => { - appTree.create( - '/testSrc/appPrefix/component/custom.component.html', ` + appTree.create('/testSrc/appPrefix/component/custom.component.html', `
Some Content
@@ -145,8 +116,7 @@ ${noteText} }); it('Should insert routerLink to igx-tab-header', async () => { - appTree.create( - '/testSrc/appPrefix/component/custom.component.html', ` + appTree.create('/testSrc/appPrefix/component/custom.component.html', ` @@ -175,8 +145,7 @@ ${noteText} }); it('Should not create igx-[tab|botton-nav]-content if it\'s already present', async () => { - appTree.create( - '/testSrc/appPrefix/component/custom.component.html', ` + appTree.create('/testSrc/appPrefix/component/custom.component.html', ` @@ -230,8 +199,7 @@ ${noteText} }); it('Should insert ng-template content into igx-tab-header', async () => { - appTree.create( - '/testSrc/appPrefix/component/custom.component.html', ` + appTree.create('/testSrc/appPrefix/component/custom.component.html', ` @@ -259,8 +227,7 @@ ${noteText} // IgxBottomNav it('Should update igx-tab-panel to igx-bottom-nav-item', async () => { - appTree.create( - '/testSrc/appPrefix/component/custom.component.html', ` + appTree.create('/testSrc/appPrefix/component/custom.component.html', ` Some Content @@ -285,8 +252,7 @@ Some Content }); it('Should insert routerLink to igx-bottom-nav-header', async () => { - appTree.create( - '/testSrc/appPrefix/component/custom.component.html', ` + appTree.create('/testSrc/appPrefix/component/custom.component.html', ` @@ -309,8 +275,7 @@ ${noteText} }); it('Should insert ng-template content into igx-bottom-nav-header', async () => { - appTree.create( - '/testSrc/appPrefix/component/custom.component.html', ` + appTree.create('/testSrc/appPrefix/component/custom.component.html', ` @@ -372,1044 +337,685 @@ igx-bottom-nav-header { // IgxDateTimeEditor it('should update isSpinLoop', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update onValueChange', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); // IgxDatePicker it('should update onSelection', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update onClosing', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update onClosed', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update onOpening', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update onOpened', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update onValidationFailed', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should remove onDisabledDate', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update editorTabIndex', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should remove labelVisibility', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update mask', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update format', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update displayData', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update monthsViewNumber', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update vertical', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update dropDownOverlaySettings', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update modalOverlaySettings', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); // IgxTimePicker it('should update onValueChanged', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update onClosing', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update onClosed', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update onOpening', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update onOpened', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update onValidationFailed', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update isSpinLoop', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update vertical', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update format', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); // IgxDateRangePicker it('should update rangeSelected', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update onClosing', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update onClosed', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update onOpening', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update onOpened', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should update monthsViewNumber', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); // Custom migrations // igxDatePicker it('should remove [mode]=dropdown and add default date label', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should remove mode=dropdown', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should not remove [mode]=dialog', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should remove mode=dialog', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should add mode=dialog', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should remove label property and add it as a child elem', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should remove label property and add it as a child elem (interpolation)', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should remove label and labelVisibility properties and add it as a child elem (interpolation) with ngIf', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should not add default label if there is already such', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); // igxTimePicker it('should remove [mode]=dropdown and add default time label', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should remove mode=dropdown', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should not remove [mode]=dialog', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should remove mode=dialog', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should add mode=dialog', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should remove label property and add it as a child elem', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should remove label property and add it as a child elem (interpolation)', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should remove label and labelVisibility properties and add it as a child elem (interpolation) with ngIf', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should not add default label if there is already such', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should rename InteractionMode to PickerInteractionMode', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.ts', - `import { Component } from '@angular/core'; + appTree.create('/testSrc/appPrefix/component/test.component.ts', `import { Component } from '@angular/core'; import { InteractionMode } from 'igniteui-angular'; @Component({ @@ -1438,16 +1044,11 @@ export class PickerModeComponent { } `; - expect( - tree.readContent( - '/testSrc/appPrefix/component/test.component.ts' - ) - ).toEqual(expectedContent); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual(expectedContent); }); it('Should update row component types with RowType', async () => { - appTree.create( - '/testSrc/appPrefix/component/rows.component.ts', ` + appTree.create('/testSrc/appPrefix/component/rows.component.ts', ` import { IgxGridComponent, IgxGridRowComponent, IgxHierarchicalRowComponent, IgxTreeGridRowComponent, IgxGridGroupByRowComponent, RowPinningPosition } from 'igniteui-angular'; export class HGridMultiRowDragComponent { @@ -1493,28 +1094,20 @@ export class HGridMultiRowDragComponent { }); it('should replace output names in toast', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('Should update toast output subscriptions', async () => { - appTree.create( - '/testSrc/appPrefix/component/toast.component.ts', ` + appTree.create('/testSrc/appPrefix/component/toast.component.ts', ` import { IgxToastComponent } from 'igniteui-angular'; import { Component, OnInit, ViewChild } from '@angular/core'; export class SimpleComponent { @@ -1552,9 +1145,7 @@ export class SimpleComponent { }); it('should rename DataType to GridColumnDataType', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.ts', - `import { Component, ViewChild } from '@angular/core'; + appTree.create('/testSrc/appPrefix/component/test.component.ts', `import { Component, ViewChild } from '@angular/core'; import { IgxColumnComponent, DataType } from 'igniteui-angular'; @Component({ @@ -1582,211 +1173,150 @@ export class SimpleComponent { } `; - expect( - tree.readContent( - '/testSrc/appPrefix/component/test.component.ts' - ) - ).toEqual(expectedContent); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual(expectedContent); }); it('Should move input-group disabled property to input child', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('Should move input-group disabled property to input child', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('Should move input group disabled property w/ XHTML syntax closing', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('Should only move input-group disabled to igxInput directive', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('Should move input-group disabled string values to underlying igxInput', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('Should move disabled attribute w/ no value to igxInput', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); // this is the expected output // putting just the disabled attribute on an igx-input-group is an invalid scenario - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('Should not add duplicate disabled to igxInput when moving the property from input-group', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); // this is the expected output // putting just the disabled attribute on an igx-input-group is an invalid scenario - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('Should move disabled input group to textarea w/ igxInput', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); // this is the expected output // putting just the disabled attribute on an igx-input-group is an invalid scenario - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('Should properly rename InteractionMode to PickerInteractionMode', async () => { - appTree.create('/testSrc/appPrefix/component/test.component.ts', - ` + appTree.create('/testSrc/appPrefix/component/test.component.ts', ` import { InteractionMode } from 'igniteui-angular'; export class MyClass { public interactionMode: InteractionMode = InteractionMode.Dialog; @@ -1796,15 +1326,11 @@ export class SimpleComponent { const tree = await schematicRunner .runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.ts') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual(` import { PickerInteractionMode } from 'igniteui-angular'; export class MyClass { public interactionMode: PickerInteractionMode = PickerInteractionMode.Dialog; } - ` - ); + `); }); }); diff --git a/projects/igniteui-angular/migrations/update-12_1_0/index.spec.ts b/projects/igniteui-angular/migrations/update-12_1_0/index.spec.ts index 384682a79f2..c8418cab281 100644 --- a/projects/igniteui-angular/migrations/update-12_1_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-12_1_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '12.1.0'; @@ -17,8 +18,7 @@ describe(`Update to ${version}`, () => { // IgxOverlayService it('should update overlay events subscriptions', async () => { - appTree.create( - '/testSrc/appPrefix/service/test.component.ts', ` + appTree.create('/testSrc/appPrefix/service/test.component.ts', ` import { Component, OnInit } from '@angular/core'; import { IgxOverlayService } from 'igniteui-angular'; export class SimpleComponent implements OnInit { @@ -39,6 +39,7 @@ export class SimpleComponent implements OnInit { .toEqual(` import { Component, OnInit } from '@angular/core'; import { IgxOverlayService } from 'igniteui-angular'; +import { describe, it, expect, beforeEach } from 'vitest'; export class SimpleComponent implements OnInit { constructor(@Inject(IgxOverlayService) protected overlayService: IgxOverlayService){} @@ -54,8 +55,7 @@ export class SimpleComponent implements OnInit { }); it('should update banner event subscriptions in .ts file', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.ts', ` + appTree.create('/testSrc/appPrefix/component/test.component.ts', ` import { Component, OnInit } from '@angular/core'; import { IgxBannerComponent } from 'igniteui-angular'; export class TestComponent implements OnInit { @@ -89,8 +89,7 @@ export class TestComponent implements OnInit { }); it('should update banner event subscriptions in .html file', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` { - appTree.create( - '/testSrc/appPrefix/component/test.component.ts', ` + appTree.create('/testSrc/appPrefix/component/test.component.ts', ` import { Component, OnInit } from '@angular/core'; import { IgxExpansionPanelComponent, IgxExpansionPanelHeaderComponent } from 'igniteui-angular'; export class TestComponent implements OnInit { @@ -153,8 +151,7 @@ export class TestComponent implements OnInit { }); it('should update mask event subscriptions in .html file', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); @@ -164,8 +161,7 @@ export class TestComponent implements OnInit { }); it('should update mask event subscriptions .ts file', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.ts', ` + appTree.create('/testSrc/appPrefix/component/test.component.ts', ` import { Component, OnInit } from '@angular/core'; import { IgxMaskDirective } from 'igniteui-angular'; export class TestComponent implements OnInit { @@ -194,8 +190,7 @@ export class TestComponent implements OnInit { it('should update expansion panel event subscriptions in .html file', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` Trigger something @@ -213,8 +208,7 @@ export class TestComponent implements OnInit { }); it('should remove paging property and define a igx-paginator component instead', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` @@ -233,8 +227,7 @@ export class TestComponent implements OnInit { }); it('should remove paging and paginationTemplate property and define a igx-paginator component with custom content', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` @@ -275,8 +268,7 @@ export class TestComponent implements OnInit { }); it('should remove paging property and define a igx-paginator component instead in hGrid', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` @@ -298,8 +290,7 @@ export class TestComponent implements OnInit { }); it('should remove paging property and paginationTemplate in hGrid', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` @@ -357,8 +348,7 @@ export class TestComponent implements OnInit { }); it('should define correctly paginator when using the component inside custom template', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` @@ -386,8 +376,7 @@ export class TestComponent implements OnInit { // IgxDropDown it('should update dropdown event subscriptions in .html file', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` Display something `); - const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) + .toEqual(` { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', `

Some content that user would like to make it togglable.

`); - const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); + const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) + .toEqual(`
{ - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); - const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); + const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) + .toEqual(` { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); - const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); + const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) + .toEqual(` { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); - const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); + const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) + .toEqual(` { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); - const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); + const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) + .toEqual(` { - appTree.create( - '/testSrc/appPrefix/component/cells.component.ts', ` + appTree.create('/testSrc/appPrefix/component/cells.component.ts', ` import { IgxGridComponent, IgxGridCellComponent, IgxHierarchicalGridCellComponent, IgxTreeGridCellComponent, IgxGridExpandableCellComponent } from 'igniteui-angular'; export class HGridMultiRowDragComponent { @@ -568,10 +551,10 @@ export class TestComponent implements OnInit { const cells = grid.selectedCells as IgxGridCellComponent[]; } }`); - const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); + const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/cells.component.ts')) - .toEqual(` + expect(tree.readContent('/testSrc/appPrefix/component/cells.component.ts')) + .toEqual(` import { IgxGridComponent, CellType } from 'igniteui-angular'; export class HGridMultiRowDragComponent { public onDropAllowed(args: IDropDroppedEventArgs) @@ -594,8 +577,7 @@ export class TestComponent implements OnInit { // Transaction providers it('Should add a comment for the deprecated IgxGridTransactionToken', async () => { - appTree.create( - '/testSrc/appPrefix/component/transaction.component.ts', ` + appTree.create('/testSrc/appPrefix/component/transaction.component.ts', ` import { IgxGridComponent, IgxGridTransaction, IgxTransactionService } from 'igniteui-angular'; @Component({ template: '', @@ -605,7 +587,7 @@ export class TestComponent implements OnInit { @ViewChild(IgxGridComponent, { read: IgxGridComponent }) public IgxGridTransaction!: IgxGridComponent; }`); - const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); + const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/transaction.component.ts')) .toEqual(` @@ -622,8 +604,7 @@ export class TestComponent implements OnInit { }); it('Should add a comment for the deprecated IgxGridTransactionToken, multiple providers', async () => { - appTree.create( - '/testSrc/appPrefix/component/transaction.component.ts', ` + appTree.create('/testSrc/appPrefix/component/transaction.component.ts', ` import { IgxGridComponent, IgxGridTransaction, IgxTransactionService } from 'igniteui-angular'; @Component({ template: '', @@ -637,7 +618,7 @@ export class TestComponent implements OnInit { @ViewChild(IgxGridComponent, { read: IgxGridComponent }) public IgxGridTransaction!: IgxGridComponent; }`); - const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); + const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/transaction.component.ts')) .toEqual(` @@ -657,9 +638,8 @@ export class TestComponent implements OnInit { }`); }); - it('Should properly rename IComboSelectionChangeEventArgs to IComboSelectionChangingEventArgs', async () => { - appTree.create('/testSrc/appPrefix/component/test.component.ts', - ` + it('Should properly rename IComboSelectionChangeEventArgs to IComboSelectionChangingEventArgs', async () => { + appTree.create('/testSrc/appPrefix/component/test.component.ts', ` import { IComboSelectionChangeEventArgs } from 'igniteui-angular'; export class MyClass { public eventArgs: IComboSelectionChangeEventArgs; @@ -669,21 +649,16 @@ export class TestComponent implements OnInit { const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.ts') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual(` import { IComboSelectionChangingEventArgs } from 'igniteui-angular'; export class MyClass { public eventArgs: IComboSelectionChangingEventArgs; } - ` - ); + `); }); - it('Should properly rename AutocompleteItemSelectionEventArgs to AutocompleteSelectionChangingEventArgs', async () => { - appTree.create('/testSrc/appPrefix/component/test.component.ts', - ` + it('Should properly rename AutocompleteItemSelectionEventArgs to AutocompleteSelectionChangingEventArgs', async () => { + appTree.create('/testSrc/appPrefix/component/test.component.ts', ` import { AutocompleteItemSelectionEventArgs } from 'igniteui-angular'; export class MyClass { public eventArgs: AutocompleteItemSelectionEventArgs; @@ -693,16 +668,12 @@ export class TestComponent implements OnInit { const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.ts') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual(` import { AutocompleteSelectionChangingEventArgs } from 'igniteui-angular'; export class MyClass { public eventArgs: AutocompleteSelectionChangingEventArgs; } - ` - ); + `); }); }); diff --git a/projects/igniteui-angular/migrations/update-13_0_0/index.spec.ts b/projects/igniteui-angular/migrations/update-13_0_0/index.spec.ts index d66d5a8876b..b3d4a46c799 100644 --- a/projects/igniteui-angular/migrations/update-13_0_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-13_0_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '13.0.0'; @@ -17,9 +18,7 @@ describe(`Update to ${version}`, () => { const lineBreaksAndSpaceRegex = /\s/g; it('should rename CarouselAnimationType to HorizontalAnimationType', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.ts', - `import { Component, ViewChild } from '@angular/core'; + appTree.create('/testSrc/appPrefix/component/test.component.ts', `import { Component, ViewChild } from '@angular/core'; import { CarouselAnimationType } from 'igniteui-angular'; @Component({ @@ -47,16 +46,11 @@ describe(`Update to ${version}`, () => { } `; - expect( - tree.readContent( - '/testSrc/appPrefix/component/test.component.ts' - ) - ).toEqual(expectedContent); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual(expectedContent); }); it('should rename IgxComboComponent selectedItems() to selection', async () => { - appTree.create('/testSrc/appPrefix/component/test.component.ts', - `import { IgxComboComponent } from 'igniteui-angular'; + appTree.create('/testSrc/appPrefix/component/test.component.ts', `import { IgxComboComponent } from 'igniteui-angular'; export class MyClass { public combo: IgxComboComponent; public ngAfterViewInit() { @@ -66,10 +60,7 @@ describe(`Update to ${version}`, () => { const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: true }, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.ts') - ).toEqual( - `import { IgxComboComponent } from 'igniteui-angular'; + expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual(`import { IgxComboComponent } from 'igniteui-angular'; export class MyClass { public combo: IgxComboComponent; public ngAfterViewInit() { @@ -79,8 +70,7 @@ describe(`Update to ${version}`, () => { }); it('should remove paging and paginationTemplate property and define a igx-paginator component with custom content', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', `
{{col.field}} @@ -119,8 +109,7 @@ describe(`Update to ${version}`, () => { }); it('should insert a comment when exporter services are present in module.ts files', async () => { - appTree.create('/testSrc/appPrefix/component/app.module.ts', -`import { NgModule } from "@angular/core"; + appTree.create('/testSrc/appPrefix/component/app.module.ts', `import { NgModule } from "@angular/core"; import { FormsModule } from "@angular/forms"; import { BrowserModule } from "@angular/platform-browser"; import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; @@ -151,10 +140,7 @@ export class AppModule {} const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/app.module.ts') - ).toEqual( -`// IgxCsvExporterService and IgxExcelExporterService no longer need to be manually provided and can be safely removed. + expect(tree.readContent('/testSrc/appPrefix/component/app.module.ts')).toEqual(`// IgxCsvExporterService and IgxExcelExporterService no longer need to be manually provided and can be safely removed. import { NgModule } from "@angular/core"; import { FormsModule } from "@angular/forms"; import { BrowserModule } from "@angular/platform-browser"; @@ -185,8 +171,7 @@ export class AppModule {} }); it('Should properly rename rowData property to data', async () => { - appTree.create('/testSrc/appPrefix/component/test.component.ts', - ` + appTree.create('/testSrc/appPrefix/component/test.component.ts', ` import { IgxGridComponent, IgxTreeGridComponent, IgxHierarchicalGridComponent } from 'igniteui-angular'; export class MyClass { @ViewChild(IgxGridComponent, { read: IgxGridComponent }) @@ -216,10 +201,7 @@ export class AppModule {} const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.ts') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual(` import { IgxGridComponent, IgxTreeGridComponent, IgxHierarchicalGridComponent } from 'igniteui-angular'; export class MyClass { @ViewChild(IgxGridComponent, { read: IgxGridComponent }) @@ -244,13 +226,11 @@ export class AppModule {} const treeRowID = this.tgrid.getRowByIndex(0).treeRow.key; } } - ` - ); + `); }); it('Should properly rename columnsCollection property to columns', async () => { - appTree.create('/testSrc/appPrefix/component/test.component.ts', - ` + appTree.create('/testSrc/appPrefix/component/test.component.ts', ` import { IgxGridComponent } from 'igniteui-angular'; export class MyClass { @ViewChild(IgxGridComponent, { read: IgxGridComponent }) @@ -264,10 +244,7 @@ export class AppModule {} const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.ts') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual(` import { IgxGridComponent } from 'igniteui-angular'; export class MyClass { @ViewChild(IgxGridComponent, { read: IgxGridComponent }) @@ -276,13 +253,11 @@ export class AppModule {} const columns = this.grid1.columns; } } - ` - ); + `); }); it('Should properly rename columnsCollection property to columns - treeGrid', async () => { - appTree.create('/testSrc/appPrefix/component/test.component.ts', - ` + appTree.create('/testSrc/appPrefix/component/test.component.ts', ` import { IgxTreeGridComponent } from 'igniteui-angular'; export class MyClass { @ViewChild(IgxTreeGridComponent, { read: IgxTreeGridComponent }) @@ -299,10 +274,7 @@ export class AppModule {} const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.ts') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual(` import { IgxTreeGridComponent } from 'igniteui-angular'; export class MyClass { @ViewChild(IgxTreeGridComponent, { read: IgxTreeGridComponent }) @@ -314,13 +286,11 @@ export class AppModule {} const editableColumns = this.tGrid1.columns.filter(c => e.editable); } } - ` - ); + `); }); it('should remove grid toolbar inputs and define a igx-grid-toolbar component instead', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` @@ -347,8 +317,7 @@ export class AppModule {} }); it('should migrate row island toolbar inputs to igx-grid-toolbar component instead', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` @@ -397,8 +366,7 @@ export class AppModule {} }); it('should update existing toolbar component', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` @@ -430,8 +398,7 @@ export class AppModule {} }); it('should remove grid toolbar inputs and define a igx-grid-toolbar component instead', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` @@ -455,8 +422,7 @@ export class AppModule {} }); it('should contain all actions from the before toolbar', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` @@ -489,8 +455,7 @@ export class AppModule {} }); it('should remove grid toolbar exporter inputs and define a igx-grid-toolbar component instead', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` @@ -518,7 +483,7 @@ export class AppModule {} - + @@ -526,8 +491,7 @@ export class AppModule {} }); it('should remove grid toolbar inputs but do not remove all templating inside tooblar component', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` diff --git a/projects/igniteui-angular/migrations/update-13_1_0/index.spec.ts b/projects/igniteui-angular/migrations/update-13_1_0/index.spec.ts index f6afd16ca00..fddaa297333 100644 --- a/projects/igniteui-angular/migrations/update-13_1_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-13_1_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '13.1.0'; @@ -16,79 +17,56 @@ describe(`Update to ${version}`, () => { const migrationName = 'migration-23'; it('should remove columns` movable prop and enable grid`s moving prop if there is movable columns', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` -` - ); +`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` -` - ); +`); }); it('should remove columns` movable prop and don`t set the grid`s moving prop if there isn`t movable columns', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` -` - ); +`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` -` - ); +`); }); it('should rename @import to @use', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, -`@import '~igniteui-angular/lib/core/styles/themes/index';` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `@import '~igniteui-angular/lib/core/styles/themes/index';`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.scss').replace(/\n|\r\n/g, '') - ).toEqual( -`/* Line added via automated migrations. */ -@use "igniteui-angular/theming" as *;`.replace(/\n|\r\n/g, '') - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss').replace(/\n|\r\n/g, '')).toEqual(`/* Line added via automated migrations. */ +@use "igniteui-angular/theming" as *;`.replace(/\n|\r\n/g, '')); }); it('should remove columns` and column-groups` movable prop and set the accurate moving prop to the grid', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` @@ -104,16 +82,12 @@ describe(`Update to ${version}`, () => { -` - ); +`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` @@ -129,63 +103,43 @@ describe(`Update to ${version}`, () => { -` - ); +`); }); it('should remove columns` movable prop and enable grid`s moving prop in multiple files', async () => { - appTree.create( - `/testSrc/appPrefix/component/test1.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test1.component.html`, ` -` - ); - appTree.create( - `/testSrc/appPrefix/component/test2.component.html`, - ` +`); + appTree.create(`/testSrc/appPrefix/component/test2.component.html`, ` -` - ); +`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test1.component.html') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test1.component.html')).toEqual(` -` - ); - expect( - tree.readContent('/testSrc/appPrefix/component/test2.component.html') - ).toEqual( - ` +`); + expect(tree.readContent('/testSrc/appPrefix/component/test2.component.html')).toEqual(` -` - ); +`); }); it('should rename hgridAPI to gridAPI for hierarchical grids', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` -` - ); - appTree.create( - `/testSrc/appPrefix/component/test.component.ts`, - ` +`); + appTree.create(`/testSrc/appPrefix/component/test.component.ts`, ` import { Component } from '@angular/core'; import { IgxHierarchicalGridComponent @@ -202,24 +156,16 @@ export class TestComponent { return this.childGrid.hgridAPI.getChildGrids().length > 0; } } -` - ); +`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( -` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` -` - ); +`); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.ts') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual(` import { Component } from '@angular/core'; import { IgxHierarchicalGridComponent @@ -236,8 +182,7 @@ export class TestComponent { return this.childGrid.gridAPI.getChildGrids().length > 0; } } -` - ); +`); }); }); diff --git a/projects/igniteui-angular/migrations/update-13_2_0/index.spec.ts b/projects/igniteui-angular/migrations/update-13_2_0/index.spec.ts index 903d6f31943..0c2bebc961f 100644 --- a/projects/igniteui-angular/migrations/update-13_2_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-13_2_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '13.2.0'; @@ -16,18 +17,11 @@ describe(`Update to ${version}`, () => { const migrationName = 'migration-24'; it('should remove the $direction prop from the core mixin', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, -`@include igniteui.core($direction: 'rtl');` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `@include igniteui.core($direction: 'rtl');`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.scss') - ).toEqual( -`@include igniteui.core();` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`@include igniteui.core();`); }); }); diff --git a/projects/igniteui-angular/migrations/update-14_1_0/index.spec.ts b/projects/igniteui-angular/migrations/update-14_1_0/index.spec.ts index 12548ffab7a..8c9eb33e4a4 100644 --- a/projects/igniteui-angular/migrations/update-14_1_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-14_1_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '14.1.0'; @@ -16,21 +17,16 @@ describe(`Update to ${version}`, () => { const migrationName = 'migration-25'; it('should remove the $disable-shadow property from the tabs-theme', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-tabs: tabs-theme( + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-tabs: tabs-theme( $item-text-color: red, $disable-shadow: false - );` - ); + );`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-tabs: tabs-theme( + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-tabs: tabs-theme( $item-text-color: red - );` - ); + );`); }); }); diff --git a/projects/igniteui-angular/migrations/update-15_0_0/index.spec.ts b/projects/igniteui-angular/migrations/update-15_0_0/index.spec.ts index 99cfe02909c..3c9753e5737 100644 --- a/projects/igniteui-angular/migrations/update-15_0_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-15_0_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '15.0.0'; @@ -16,221 +17,142 @@ describe(`Update to ${version}`, () => { const migrationName = 'migration-26'; it('should replace CSS custom properties prefix from --igx-primary to --ig-primary', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, -`::ng-deep { + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `::ng-deep { .custom-body { color: var(--igx-primary-500-contrast); background: hsla(var(--igx-primary-500)); } -}` - ); +}`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.scss') - ).toEqual( -`::ng-deep { + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`::ng-deep { .custom-body { color: var(--ig-primary-500-contrast); background: hsla(var(--ig-primary-500)); } -}` - ); +}`); }); it('should replace CSS custom properties from -igx-grays to -ig-gray', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, -`::ng-deep { + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `::ng-deep { .custom-body { color: var(--igx-grays-900); } -}` - ); +}`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.scss') - ).toEqual( -`::ng-deep { + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`::ng-deep { .custom-body { color: var(--ig-gray-900); } -}` - ); +}`); }); it('should replace CSS custom properties prefix from --igx-h[number]- to --ig-h[number]-', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, -`::ng-deep { + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `::ng-deep { .custom-body { font-family: var(--igx-h1-font-family); font-size: var(--igx-h3-font-size); } -}` - ); +}`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.scss') - ).toEqual( -`::ng-deep { + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`::ng-deep { .custom-body { font-family: var(--ig-h1-font-family); font-size: var(--ig-h3-font-size); } -}` - ); +}`); }); it('should NOT replace CSS custom properties prefix for internal variables', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, -`::ng-deep { + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `::ng-deep { .custom-body { width: var(--igx-icon-size); } -}` - ); +}`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.scss') - ).toEqual( -`::ng-deep { + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`::ng-deep { .custom-body { width: var(--igx-icon-size); } -}` - ); +}`); }); it('should remove the $palette prop from component themes', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, -`@include igniteui.avatar-theme($palette: null);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `@include igniteui.avatar-theme($palette: null);`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.scss') - ).toEqual( -`@include igniteui.avatar-theme();` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`@include igniteui.avatar-theme();`); }); it('should remove the $type-scale prop from the type-style mixin', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, -`@include igniteui.type-style($type-scale: $default-type-scale,$category: 'h1');` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `@include igniteui.type-style($type-scale: $default-type-scale,$category: 'h1');`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.scss') - ).toEqual( -`@include igniteui.type-style($category: 'h1');` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`@include igniteui.type-style($category: 'h1');`); }); it('should remove the $wc prop from the typogrpahy mixin', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, -`@include igniteui.typography($font-family: "Roboto, sans-serif",$wc: true);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `@include igniteui.typography($font-family: "Roboto, sans-serif",$wc: true);`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.scss') - ).toEqual( -`@include igniteui.typography($font-family: "Roboto, sans-serif");` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`@include igniteui.typography($font-family: "Roboto, sans-serif");`); }); it('should remove the $wc prop from the theme mixin', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, -`@include igniteui.theme($palette: $my-palette,$wc: true);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `@include igniteui.theme($palette: $my-palette,$wc: true);`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.scss') - ).toEqual( -`@include igniteui.theme($palette: $my-palette);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`@include igniteui.theme($palette: $my-palette);`); }); it('should remove the $elevations prop from the elevations function and rename $elevation to $name', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, -`$elevation: igniteui.elevation($elevations: $elevations,$elevation: 2);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$elevation: igniteui.elevation($elevations: $elevations,$elevation: 2);`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.scss') - ).toEqual( -`$elevation: igniteui.elevation($name: 2);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$elevation: igniteui.elevation($name: 2);`); }); it('should remove the $prefix and the $contrast props from the palette-vars mixin and rename it to palette', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, -`@include igniteui.palette-vars($palette: $my-palette,$contrast: true,$prefix: 'igx');` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `@include igniteui.palette-vars($palette: $my-palette,$contrast: true,$prefix: 'igx');`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.scss') - ).toEqual( -`@include igniteui.palette($palette: $my-palette);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`@include igniteui.palette($palette: $my-palette);`); }); it('should replace elevation-vars mixin with elevations', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, -`@include igniteui.elevation-vars($material-elevations);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `@include igniteui.elevation-vars($material-elevations);`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.scss') - ).toEqual( -`@include igniteui.elevations($material-elevations);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`@include igniteui.elevations($material-elevations);`); }); it('should rename IgxGridToolbarTitleDirective and IgxGridToolbarActionsDirective', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.ts', - `import { Component, ViewChild } from '@angular/core'; + appTree.create('/testSrc/appPrefix/component/test.component.ts', `import { Component, ViewChild } from '@angular/core'; import { IgxGridToolbarTitleDirective, IgxGridToolbarComponent, IgxGridToolbarActionsDirective } from 'igniteui-angular'; @Component({ @@ -266,16 +188,11 @@ describe(`Update to ${version}`, () => { } `; - expect( - tree.readContent( - '/testSrc/appPrefix/component/test.component.ts' - ) - ).toEqual(expectedContent); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual(expectedContent); }); it('should remove the disabled property from the igx-radio-group', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); @@ -285,8 +202,7 @@ describe(`Update to ${version}`, () => { }); it('should remove the labelPosition property from the igx-radio-group', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); diff --git a/projects/igniteui-angular/migrations/update-15_0_11/index.spec.ts b/projects/igniteui-angular/migrations/update-15_0_11/index.spec.ts index 01b8e0f5cc5..9ad8f748429 100644 --- a/projects/igniteui-angular/migrations/update-15_0_11/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-15_0_11/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '15.0.11'; @@ -16,9 +17,7 @@ describe(`Update to ${version}`, () => { const migrationName = 'migration-28'; it('should replace CSS $grays parameters', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, -`$my-palette: palette( + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$my-palette: palette( $primary: #09f, $secondary: #e41c77, $grays: #000 @@ -27,16 +26,12 @@ $my-palette: palette( $primary: #09f, $secondary: #e41c77, $grays: #000123 -);` - ); +);`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.scss') - ).toEqual( -`$my-palette: palette( + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$my-palette: palette( $primary: #09f, $secondary: #e41c77, $gray: #000 @@ -45,14 +40,11 @@ $my-palette: palette( $primary: #09f, $secondary: #e41c77, $gray: #000123 -);` - ); +);`); }); it('should replace CSS $grays parameters variations', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, -`$my-palette: palette( + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$my-palette: palette( $grays: red, $grays: rgb(204, 102, 153), $grays: rgba(107, 113, 127, 0.8), @@ -65,16 +57,12 @@ $my-palette: palette( $grays: rgba(107, 113, 127, 0.8), $grays: hsl(228, 7%, 86%), $grays: hsla(20, 20%, 85%, 0.7), -);` - ); +);`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.scss') - ).toEqual( -`$my-palette: palette( + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$my-palette: palette( $gray: red, $gray: rgb(204, 102, 153), $gray: rgba(107, 113, 127, 0.8), @@ -87,50 +75,33 @@ $my-palette: palette( $gray: rgba(107, 113, 127, 0.8), $gray: hsl(228, 7%, 86%), $gray: hsla(20, 20%, 85%, 0.7), -);` - ); +);`); }); it('should NOT replace $grays as custom var', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, -`$grays: #FFFFFF;` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$grays: #FFFFFF;`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.scss') - ).toEqual( -`$grays: #FFFFFF;` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$grays: #FFFFFF;`); }); it('should replace grays as value', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, -`.my-class { + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `.my-class { color: contrast-color($color: 'grays', $variant: 300); -}` - ); +}`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.scss') - ).toEqual( -`.my-class { + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`.my-class { color: contrast-color($color: 'gray', $variant: 300); -}` - ); +}`); }); it('should replace .igx-typography with .ig-typography as style', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, -`.igx-typography { + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `.igx-typography { h1, h2, h3, h4, h5, h6, p, .igx-typography__body-1 { margin: 0; } @@ -139,34 +110,23 @@ $my-palette: palette( const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.scss') - ).toEqual( -`.ig-typography { + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`.ig-typography { h1, h2, h3, h4, h5, h6, p, .ig-typography__body-1 { margin: 0; } -}` - ); +}`); }); it('should replace igx-typography & igx-scrollbar from template', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, -` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` -` - ); +`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.html') - ).toEqual( -` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` -` - ); +`); }); }); diff --git a/projects/igniteui-angular/migrations/update-15_0_4/index.spec.ts b/projects/igniteui-angular/migrations/update-15_0_4/index.spec.ts index b7ff75534d5..145b48b3d9c 100644 --- a/projects/igniteui-angular/migrations/update-15_0_4/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-15_0_4/index.spec.ts @@ -3,6 +3,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { ProjectType } from '../../schematics/utils/util'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '15.0.4'; @@ -16,8 +17,7 @@ describe(`Update to ${version}`, () => { sourceRoot: '/testSrc', architect: { build: { - options: { - } + options: {} } } } @@ -33,8 +33,7 @@ describe(`Update to ${version}`, () => { projectType: ProjectType.Library, architect: { build: { - options: { - } + options: {} } } } diff --git a/projects/igniteui-angular/migrations/update-15_1_0/index.spec.ts b/projects/igniteui-angular/migrations/update-15_1_0/index.spec.ts index dbccd44a0a6..f0e442d6502 100644 --- a/projects/igniteui-angular/migrations/update-15_1_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-15_1_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '15.1.0'; @@ -16,9 +17,7 @@ describe(`Update to ${version}`, () => { const migrationName = 'migration-29'; it('should replace on-prefixed outputs in carousel', async () => { - appTree.create( - `/testSrc/appPrefix/component/carousel.component.html`, - ` { - ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/carousel.component.html')) @@ -55,9 +53,7 @@ describe(`Update to ${version}`, () => { }); it('should replace on-prefixed typescript outputs in carousel', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.ts', - `import { Component, ViewChild } from '@angular/core'; + appTree.create('/testSrc/appPrefix/component/test.component.ts', `import { Component, ViewChild } from '@angular/core'; import { IgxCarouselComponent } from 'igniteui-angular'; @Component({ @@ -103,9 +99,7 @@ describe(`Update to ${version}`, () => { }); it('should replace on-prefixed outputs for displayDensity and onGroupingDone to groupingDone', async () => { - appTree.create( - `/testSrc/appPrefix/component/carousel.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/carousel.component.html`, ` @@ -126,8 +120,7 @@ describe(`Update to ${version}`, () => { - ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/carousel.component.html')) @@ -156,24 +149,19 @@ describe(`Update to ${version}`, () => { }); it('should replace avatar roundShape property with shape', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should append igxStart and igxEnd directives to the child elements of the igx-card-actions', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` Span @@ -182,13 +170,11 @@ describe(`Update to ${version}`, () => { drag_indicator - ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` Span @@ -197,13 +183,11 @@ describe(`Update to ${version}`, () => { drag_indicator - ` - ); + `); }); it('shouldn\'t append igxStart and igxEnd directives to the child elements of the igx-card-actions if already applied', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` Span @@ -212,13 +196,11 @@ describe(`Update to ${version}`, () => { drag_indicator - ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` Span @@ -227,33 +209,22 @@ describe(`Update to ${version}`, () => { drag_indicator - ` - ); + `); }); it('should rename the $size property to the $scrollbar-size', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-scrollbar: scrollbar-theme($size: 10px);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-scrollbar: scrollbar-theme($size: 10px);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-scrollbar: scrollbar-theme($scrollbar-size: 10px);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-scrollbar: scrollbar-theme($scrollbar-size: 10px);`); }); it('should remove the $label-floated-background amd $label-floated-disabled-background properties from the input-group-theme', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-input: input-group-theme($label-floated-background: transparent, $label-floated-disabled-background: transparent);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-input: input-group-theme($label-floated-background: transparent, $label-floated-disabled-background: transparent);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-input: input-group-theme();` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-input: input-group-theme();`); }); }); diff --git a/projects/igniteui-angular/migrations/update-16_0_0/index.spec.ts b/projects/igniteui-angular/migrations/update-16_0_0/index.spec.ts index 0fc86690c11..006173da0d2 100644 --- a/projects/igniteui-angular/migrations/update-16_0_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-16_0_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '16.0.0'; @@ -16,9 +17,7 @@ describe(`Update to ${version}`, () => { const migrationName = 'migration-30'; it('Should replace IgxProcessBarTextTemplateDirective with IgxProgressBarTextTemplateDirective', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.ts', - `import { Component, ViewChild } from '@angular/core'; + appTree.create('/testSrc/appPrefix/component/test.component.ts', `import { Component, ViewChild } from '@angular/core'; import { IgxProcessBarTextTemplateDirective } from 'igniteui-angular'; @Component({ diff --git a/projects/igniteui-angular/migrations/update-16_1_0/index.spec.ts b/projects/igniteui-angular/migrations/update-16_1_0/index.spec.ts index 436778d4018..a43ef8f7454 100644 --- a/projects/igniteui-angular/migrations/update-16_1_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-16_1_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '16.1.0'; @@ -16,9 +17,7 @@ describe(`Update to ${version}`, () => { const migrationName = 'migration-31'; it('Should replace IgxStepSubTitleDirective with IgxStepSubtitleDirective', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.ts', - `import { Component, ViewChild } from '@angular/core'; + appTree.create('/testSrc/appPrefix/component/test.component.ts', `import { Component, ViewChild } from '@angular/core'; import { IgxStepSubTitleDirective } from 'igniteui-angular'; @Component({ @@ -52,9 +51,7 @@ describe(`Update to ${version}`, () => { }); it('should update IgxStepSubTitle selectors', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', - ` + appTree.create('/testSrc/appPrefix/component/test.component.html', `

Home

Home Sub Title

@@ -64,8 +61,7 @@ describe(`Update to ${version}`, () => { const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual( - ` + .toEqual(`

Home

Home Sub Title

@@ -75,8 +71,7 @@ describe(`Update to ${version}`, () => { }); it('Should properly rename value property to displayValue and selection to value', async () => { - appTree.create('/testSrc/appPrefix/component/test.component.ts', - ` + appTree.create('/testSrc/appPrefix/component/test.component.ts', ` import { IgxComboComponent, IgxSimpleComboComponent } from 'igniteui-angular'; export class MyClass { @ViewChild(IgxComboComponent, { read: IgxComboComponent }) @@ -94,10 +89,7 @@ describe(`Update to ${version}`, () => { const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.ts') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual(` import { IgxComboComponent, IgxSimpleComboComponent } from 'igniteui-angular'; export class MyClass { @ViewChild(IgxComboComponent, { read: IgxComboComponent }) @@ -111,14 +103,11 @@ describe(`Update to ${version}`, () => { const simpleComboSelectionValue = this.simpleCombo.value; } } - ` - ); + `); }); it('Should remove button-group multiSelection property set to "true" and replace it with selectionMode property set to "multi"', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` @@ -130,8 +119,7 @@ describe(`Update to ${version}`, () => { const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual( - ` + .toEqual(` @@ -142,9 +130,7 @@ describe(`Update to ${version}`, () => { }); it('Should remove button-group multiSelection property set to "false"', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', - ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` @@ -156,8 +142,7 @@ describe(`Update to ${version}`, () => { const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual( - ` + .toEqual(` diff --git a/projects/igniteui-angular/migrations/update-17_0_0/index.spec.ts b/projects/igniteui-angular/migrations/update-17_0_0/index.spec.ts index 45a244dcc94..56163e6c23c 100644 --- a/projects/igniteui-angular/migrations/update-17_0_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-17_0_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '17.0.0'; @@ -16,8 +17,7 @@ describe(`Update to ${version}`, () => { const migrationName = 'migration-32'; it('should append elevated attribute and remove type property to card components with type="elevated"', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, `

Title

@@ -33,13 +33,11 @@ describe(`Update to ${version}`, () => {
- ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(`

Title

@@ -55,13 +53,11 @@ describe(`Update to ${version}`, () => {
- ` - ); + `); }); it('should append elevated attribute to card components without type property', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, `

Title

@@ -77,13 +73,11 @@ describe(`Update to ${version}`, () => {
- ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(`

Title

@@ -99,13 +93,11 @@ describe(`Update to ${version}`, () => {
- ` - ); + `); }); it('should remove type property and should not appent elevated attribute to card components with type="outlined"', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, `

Title

@@ -121,13 +113,11 @@ describe(`Update to ${version}`, () => {
- ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(`

Title

@@ -143,13 +133,11 @@ describe(`Update to ${version}`, () => {
- ` - ); + `); }); it('shouldn\'t append elevated attribute to card components if already applied', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, `

Title

@@ -165,13 +153,11 @@ describe(`Update to ${version}`, () => {
- ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(`

Title

@@ -187,13 +173,11 @@ describe(`Update to ${version}`, () => {
- ` - ); + `); }); it('Should properly rename newSelection and oldSelection property to newValue and oldValue in Combo', async () => { - appTree.create('/testSrc/appPrefix/component/test.component.ts', - ` + appTree.create('/testSrc/appPrefix/component/test.component.ts', ` import { IgxComboComponent, IComboSelectionChangingEventArgs } from 'igniteui-angular'; export class MyClass { public handleSelectionChanging(e: IComboSelectionChangingEventArgs) { @@ -205,10 +189,7 @@ describe(`Update to ${version}`, () => { const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.ts') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual(` import { IgxComboComponent, IComboSelectionChangingEventArgs } from 'igniteui-angular'; export class MyClass { public handleSelectionChanging(e: IComboSelectionChangingEventArgs) { @@ -216,13 +197,11 @@ describe(`Update to ${version}`, () => { const oldSelection = e.oldValue; } } - ` - ); + `); }); it('Should properly rename newSelection and oldSelection property to newValue and oldValue SimpleCombo', async () => { - appTree.create('/testSrc/appPrefix/component/test.component.ts', - ` + appTree.create('/testSrc/appPrefix/component/test.component.ts', ` import { ISimpleComboSelectionChangingEventArgs } from 'igniteui-angular'; export class MyClass { public handleSelectionChanging(e: ISimpleComboSelectionChangingEventArgs) { @@ -234,10 +213,7 @@ describe(`Update to ${version}`, () => { const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.ts') - ).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual(` import { ISimpleComboSelectionChangingEventArgs } from 'igniteui-angular'; export class MyClass { public handleSelectionChanging(e: ISimpleComboSelectionChangingEventArgs) { @@ -245,30 +221,25 @@ describe(`Update to ${version}`, () => { const oldSelection = e.oldValue; } } - ` - ); + `); }); for (const igPackage of ['igniteui-angular', '@infragistics/igniteui-angular']) { it('should move animation imports from igniteui-angular to igniteui-angular/animations', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.ts`, -`import { IgxButtonModule, flipRight, IgxIconModule, slideInBr, scaleOutHorLeft, IgxRippleModule, EaseOut } from '${igPackage}'; + appTree.create(`/testSrc/appPrefix/component/test.component.ts`, `import { IgxButtonModule, flipRight, IgxIconModule, slideInBr, scaleOutHorLeft, IgxRippleModule, EaseOut } from '${igPackage}'; import { Component, ViewChild } from '@angular/core'; import { swingOutLeftBck, growVerIn, growVerOut, shakeHor, IgxCardModule } from '${igPackage}'; -` - ); +`); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual( -`import { IgxButtonModule, IgxIconModule, IgxRippleModule } from '${igPackage}'; + expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual(`import { IgxButtonModule, IgxIconModule, IgxRippleModule } from '${igPackage}'; import { Component, ViewChild } from '@angular/core'; import { IgxCardModule } from '${igPackage}'; import { EaseOut, flipRight, growVerIn, growVerOut, scaleOutHorLeft, shakeHor, slideInBr, swingOutLeftBck } from '${igPackage}/animations'; -` - ); +`); }); } }); diff --git a/projects/igniteui-angular/migrations/update-17_1_0/index.spec.ts b/projects/igniteui-angular/migrations/update-17_1_0/index.spec.ts index b4306ba263d..d6ed4e59945 100644 --- a/projects/igniteui-angular/migrations/update-17_1_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-17_1_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '17.1.0'; @@ -16,8 +17,7 @@ describe(`Update to ${version}`, () => { const migrationName = 'migration-33'; it('should rename raised to contained type in all components with igxButton="raised"', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` @@ -27,13 +27,11 @@ describe(`Update to ${version}`, () => {
Button
- ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` @@ -43,65 +41,55 @@ describe(`Update to ${version}`, () => {
Button
- ` - ); + `); }); it('should not rename outlined and flat type buttons', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should replace buttons of icon type with icon buttons of flat type ', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` favorite - ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` favorite - ` - ); + `); }); it('should remove toolbar grid property', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` @@ -115,13 +103,11 @@ describe(`Update to ${version}`, () => { - ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` @@ -135,7 +121,6 @@ describe(`Update to ${version}`, () => { - ` - ); + `); }); }); diff --git a/projects/igniteui-angular/migrations/update-17_1_4/index.spec.ts b/projects/igniteui-angular/migrations/update-17_1_4/index.spec.ts index bb5774bc313..64507324dee 100644 --- a/projects/igniteui-angular/migrations/update-17_1_4/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-17_1_4/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '17.1.4'; @@ -16,15 +17,10 @@ describe(`Update to ${version}`, () => { const migrationName = 'migration-34'; it('should rename the expansion-panel $disabled-color property to $disabled-text-color', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-expansion-panel: expansion-panel-theme($disabled-color: color($default-palette, 'gray', 200));` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-expansion-panel: expansion-panel-theme($disabled-color: color($default-palette, 'gray', 200));`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-expansion-panel: expansion-panel-theme($disabled-text-color: color($default-palette, 'gray', 200));` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-expansion-panel: expansion-panel-theme($disabled-text-color: color($default-palette, 'gray', 200));`); }); }); diff --git a/projects/igniteui-angular/migrations/update-17_2_0/index.spec.ts b/projects/igniteui-angular/migrations/update-17_2_0/index.spec.ts index e55612ba848..87726d6e004 100644 --- a/projects/igniteui-angular/migrations/update-17_2_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-17_2_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '17.2.0'; @@ -16,306 +17,192 @@ describe(`Update to ${version}`, () => { const migrationName = 'migration-35'; it('should rename the $content-text-color property to the $content-text-color', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($content-text-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($content-text-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($content-foreground: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($content-foreground: red);`); }); it('should rename the $month-border-radius property to the $month-year-border-radius', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($month-border-radius: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($month-border-radius: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($month-year-border-radius: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($month-year-border-radius: red);`); }); it('should rename the $month-hover-current-text-color property to the $month-current-hover-foreground', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($month-hover-current-text-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($month-hover-current-text-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($month-current-hover-foreground: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($month-current-hover-foreground: red);`); }); it('should rename the $label-color property to the $weekday-color', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($label-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($label-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($weekday-color: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($weekday-color: red);`); }); it('should rename the $week-number-color property to the $week-number-foreground', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($week-number-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($week-number-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($week-number-foreground: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($week-number-foreground: red);`); }); it('should rename the $header-text-color property to the $header-foreground', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($header-text-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($header-text-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($header-foreground: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($header-foreground: red);`); }); it('should rename the $picker-text-color property to the $picker-foreground', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($picker-text-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($picker-text-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($picker-foreground: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($picker-foreground: red);`); }); it('should rename the $picker-background-color property to the $picker-background', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($picker-background-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($picker-background-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($picker-background: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($picker-background: red);`); }); it('should rename the $picker-text-hover-color property to the $picker-hover-foreground', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($picker-text-hover-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($picker-text-hover-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($picker-hover-foreground: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($picker-hover-foreground: red);`); }); it('should rename the $picker-arrow-color property to the $navigation-color', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($picker-arrow-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($picker-arrow-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($navigation-color: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($navigation-color: red);`); }); it('should rename the $picker-arrow-hover-color property to the $navigation-hover-color', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($picker-arrow-hover-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($picker-arrow-hover-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($navigation-hover-color: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($navigation-hover-color: red);`); }); it('should rename the $inactive-text-color property to the $inactive-color', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($inactive-text-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($inactive-text-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($inactive-color: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($inactive-color: red);`); }); it('should rename the $weekend-text-color property to the $weekend-color', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($weekend-text-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($weekend-text-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($weekend-color: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($weekend-color: red);`); }); it('should rename the $year-current-text-color property to the $year-current-foreground', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($year-current-text-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($year-current-text-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($year-current-foreground: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($year-current-foreground: red);`); }); it('should rename the $year-hover-text-color property to the $year-hover-foreground', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($year-hover-text-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($year-hover-text-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($year-hover-foreground: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($year-hover-foreground: red);`); }); it('should rename the $month-hover-text-color property to the $month-hover-foreground', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($month-hover-text-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($month-hover-text-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($month-hover-foreground: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($month-hover-foreground: red);`); }); it('should rename the $date-selected-text-color property to the $date-selected-foreground', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($date-selected-text-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($date-selected-text-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($date-selected-foreground: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($date-selected-foreground: red);`); }); it('should rename the $date-current-bg-color property to the $date-current-background', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($date-current-bg-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($date-current-bg-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($date-current-background: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($date-current-background: red);`); }); it('should rename the $date-current-text-color property to the $date-current-foreground', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($date-current-text-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($date-current-text-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($date-current-foreground: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($date-current-foreground: red);`); }); it('should rename the $date-special-text-color property to the $date-special-foreground', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($date-special-text-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($date-special-text-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($date-special-foreground: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($date-special-foreground: red);`); }); it('should rename the $date-disabled-text-color property to the $date-disabled-foreground', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($date-disabled-text-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($date-disabled-text-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($date-disabled-foreground: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($date-disabled-foreground: red);`); }); it('should rename the $month-current-text-color property to the $month-current-foreground', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-calendar: calendar-theme($month-current-foreground: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-calendar: calendar-theme($month-current-foreground: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-calendar: calendar-theme($month-current-foreground: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-calendar: calendar-theme($month-current-foreground: red);`); }); it('should replace calendar property `vertical` with `orientation`', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); }); diff --git a/projects/igniteui-angular/migrations/update-17_2_2/index.spec.ts b/projects/igniteui-angular/migrations/update-17_2_2/index.spec.ts index d9c05f99156..77a7edb5ce5 100644 --- a/projects/igniteui-angular/migrations/update-17_2_2/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-17_2_2/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '17.2.2'; @@ -16,54 +17,42 @@ describe(`Update to ${version}`, () => { const migrationName = 'migration-36'; it('should replace button property `igxButtonColor` with `style.--foreground`', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should replace button property `igxButtonBackground` with `style.--background`', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should remove igx-card-actions property `reverse`', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); }); diff --git a/projects/igniteui-angular/migrations/update-17_2_3/index.spec.ts b/projects/igniteui-angular/migrations/update-17_2_3/index.spec.ts index abbc68e4b2f..d8b6418b66e 100644 --- a/projects/igniteui-angular/migrations/update-17_2_3/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-17_2_3/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '17.2.3'; @@ -16,28 +17,18 @@ describe(`Update to ${version}`, () => { const migrationName = 'migration-37'; it('should rename the $idle-item-color property to the $label-color', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-bottom-nav: bottom-nav-theme($idle-item-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-bottom-nav: bottom-nav-theme($idle-item-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-bottom-nav: bottom-nav-theme($label-color: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-bottom-nav: bottom-nav-theme($label-color: red);`); }); it('should rename the $selected-item-color property to the $label-selected-color', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-bottom-nav: bottom-nav-theme($selected-item-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-bottom-nav: bottom-nav-theme($selected-item-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-bottom-nav: bottom-nav-theme($label-selected-color: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-bottom-nav: bottom-nav-theme($label-selected-color: red);`); }); }); diff --git a/projects/igniteui-angular/migrations/update-18_0_0/index.spec.ts b/projects/igniteui-angular/migrations/update-18_0_0/index.spec.ts index d3d41eee5fd..cbe32227324 100644 --- a/projects/igniteui-angular/migrations/update-18_0_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-18_0_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '18.0.0'; @@ -43,8 +44,7 @@ describe(`Update to ${version}`, () => { const migrationName = 'migration-38'; it('should remove displayDensity property from igx-grid and replace it with inline style if its value is not set to a component member', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` @@ -59,7 +59,7 @@ describe(`Update to ${version}`, () => { const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + .toEqual(` @@ -73,8 +73,7 @@ describe(`Update to ${version}`, () => { }); it('should only remove and not replace displayDensity property from igx-grid if it is bound to something different than a value', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` @@ -84,7 +83,7 @@ describe(`Update to ${version}`, () => { const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + .toEqual(` @@ -93,8 +92,7 @@ describe(`Update to ${version}`, () => { }); it('should remove displayDensity property from igx-tree-grid and replace it with inline style if its value is not set to a component member', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` @@ -109,7 +107,7 @@ describe(`Update to ${version}`, () => { const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + .toEqual(` @@ -123,8 +121,7 @@ describe(`Update to ${version}`, () => { }); it('should remove displayDensity property from igx-pivot-grid and replace it with inline style if its value is not set to a component member', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` @@ -139,7 +136,7 @@ describe(`Update to ${version}`, () => { const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + .toEqual(` @@ -153,8 +150,7 @@ describe(`Update to ${version}`, () => { }); it('should remove displayDensity property from igx-hierarchical-grid and igx-row-island and replace it with inline style if its value is not set to a component member', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` @@ -181,7 +177,7 @@ describe(`Update to ${version}`, () => { const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + .toEqual(` @@ -207,237 +203,214 @@ describe(`Update to ${version}`, () => { }); it('should remove displayDensity property from igx-action-strip and replace it with inline style if its value is not set to a component member', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + .toEqual(` `); }); it('should remove displayDensity property from igx-buttongroup and replace it with inline style if its value is not set to a component member', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + .toEqual(` `); }); it('should remove displayDensity property from igx-chip and replace it with inline style if its value is not set to a component member', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + .toEqual(` `); }); it('should remove displayDensity property from igx-combo and replace it with inline style if its value is not set to a component member', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + .toEqual(` `); }); it('should remove displayDensity property from igx-date-picker and replace it with inline style if its value is not set to a component member', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + .toEqual(` `); }); it('should remove displayDensity property from igx-button and replace it with inline style if its value is not set to a component member', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + .toEqual(` `); }); it('should remove displayDensity property from igx-drop-down and replace it with inline style if its value is not set to a component member', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + .toEqual(` `); }); it('should remove displayDensity property from igx-select and replace it with inline style if its value is not set to a component member', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + .toEqual(` `); }); it('should remove displayDensity property from igx-input-group and replace it with inline style if its value is not set to a component member', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + .toEqual(` `); }); it('should remove displayDensity property from igx-list and replace it with inline style if its value is not set to a component member', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + .toEqual(` `); }); it('should remove displayDensity property from igx-paginator and replace it with inline style if its value is not set to a component member', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + .toEqual(` `); }); it('should remove displayDensity property from igx-query-builder and replace it with inline style if its value is not set to a component member', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + .toEqual(` `); }); it('should remove displayDensity property from igx-simple-combo and replace it with inline style if its value is not set to a component member', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + .toEqual(` `); }); it('should remove displayDensity property from igx-tree and replace it with inline style if its value is not set to a component member', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(` + .toEqual(` `); }); it('should replace PivotGrid property `showPivotConfigurationUI` with `pivotUI`', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should replace PivotGrid property `showPivotConfigurationUI` with `pivotUI`', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should add default CSS rule to set all components to their previous Large defaults', async () => { const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/styles.scss')).toEqual( -` + expect(tree.readContent('/testSrc/styles.scss')).toEqual(` @use "mockStyles.scss"; @forward something; // Specifies large size for all components to match the previous defaults @@ -445,8 +418,7 @@ describe(`Update to ${version}`, () => { :root { --ig-size: var(--ig-size-large); } -` - ); +`); }); it('should add default CSS rule to set all components to their previous Large defaults with complex file ref configs', async () => { @@ -455,8 +427,7 @@ describe(`Update to ${version}`, () => { appTree.overwrite('/angular.json', JSON.stringify(_configJson)); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/styles.scss')).toEqual( -` + expect(tree.readContent('/testSrc/styles.scss')).toEqual(` @use "mockStyles.scss"; @forward something; // Specifies large size for all components to match the previous defaults @@ -464,8 +435,7 @@ describe(`Update to ${version}`, () => { :root { --ig-size: var(--ig-size-large); } -` - ); +`); }); it('should not throw when applying default CSS rule with complex file ref configs', async () => { @@ -474,28 +444,22 @@ describe(`Update to ${version}`, () => { appTree.overwrite('/angular.json', JSON.stringify(_configJson)); try { await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - } catch (e) { - fail(e); + } + catch (e) { + throw new Error(e); } }); it('should rename the $active-item-color property to the $icon-selected-color', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-bottom-nav: bottom-nav-theme($active-item-color: red);` - ); + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-bottom-nav: bottom-nav-theme($active-item-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-bottom-nav: bottom-nav-theme($icon-selected-color: red);` - ); + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-bottom-nav: bottom-nav-theme($icon-selected-color: red);`); }); it('Should remove references to deprecated `banner` property of `BannerEventArgs`', async () => { - appTree.create( - '/testSrc/appPrefix/component/expansion-test.component.ts', - `import { Component, ViewChild } from '@angular/core'; + appTree.create('/testSrc/appPrefix/component/expansion-test.component.ts', `import { Component, ViewChild } from '@angular/core'; import { BannerEventArgs, BannerCancelEventArgs } from 'igniteui-angular'; @Component({ @@ -512,10 +476,9 @@ public onBannerOpened(event: BannerCancelEventArgs) { public onBannerOpened(event: BannerEventArgs) { console.log(event.banner); } -}` - ); +}`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - const expectedContent = `import { Component, ViewChild } from '@angular/core'; + const expectedContent = `import { Component, ViewChild } from '@angular/core'; import { BannerEventArgs, BannerCancelEventArgs } from 'igniteui-angular'; @Component({ @@ -533,8 +496,6 @@ public onBannerOpened(event: BannerEventArgs) { console.log(event.owner); } }`; - expect( - tree.readContent('/testSrc/appPrefix/component/expansion-test.component.ts') - ).toEqual(expectedContent); + expect(tree.readContent('/testSrc/appPrefix/component/expansion-test.component.ts')).toEqual(expectedContent); }); }); diff --git a/projects/igniteui-angular/migrations/update-18_1_0/index.spec.ts b/projects/igniteui-angular/migrations/update-18_1_0/index.spec.ts index 8f29050b5e4..71843d89e60 100644 --- a/projects/igniteui-angular/migrations/update-18_1_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-18_1_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '18.1.0'; @@ -16,9 +17,7 @@ describe(`Update to ${version}`, () => { const migrationName = 'migration-39'; it('should migrate calendar theme', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$my-cal: calendar-theme( + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$my-cal: calendar-theme( $month-hover-foreground: wheat, $year-hover-foreground: red, $month-hover-background: black, @@ -57,13 +56,11 @@ describe(`Update to ${version}`, () => { $selected-current-outline-hover-color: wheat, $selected-current-outline-focus-color: wheat, $month-year-border-radius: 2px - );` - ); + );`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$my-cal: calendar-theme( + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$my-cal: calendar-theme( $ym-hover-foreground: wheat, $ym-hover-background: black, $ym-current-foreground: wheat, @@ -88,14 +85,11 @@ describe(`Update to ${version}`, () => { $ym-selected-current-outline-hover-color: wheat, $ym-selected-current-outline-focus-color: wheat, $ym-border-radius: 2px - );` - ); + );`); }); it('Should replace deprecated `children` property of Columns', async () => { - appTree.create( - '/testSrc/appPrefix/component/column-test.component.ts', - `import { Component } from '@angular/core'; + appTree.create('/testSrc/appPrefix/component/column-test.component.ts', `import { Component } from '@angular/core'; import { IgxColumnGroupComponent, ColumnType } from 'igniteui-angular'; @Component({ @@ -110,10 +104,9 @@ export class ColumnsTestComponent { public toggleColumnGroup2(columnGroup: ColumnType) { const columns = columnGroup.children.toArray(); } -}` - ); +}`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - const expectedContent = `import { Component } from '@angular/core'; + const expectedContent = `import { Component } from '@angular/core'; import { IgxColumnGroupComponent, ColumnType } from 'igniteui-angular'; @Component({ @@ -129,16 +122,12 @@ export class ColumnsTestComponent { const columns = columnGroup.childColumns; } }`; - expect( - tree.readContent('/testSrc/appPrefix/component/column-test.component.ts') - ).toEqual(expectedContent); + expect(tree.readContent('/testSrc/appPrefix/component/column-test.component.ts')).toEqual(expectedContent); }); it('Should replace deprecated `isFirstPageDisabled`/`isLastPageDisabled` on paginator', async () => { - appTree.create( - '/testSrc/appPrefix/component/paginator-test.component.ts', - `import { Component } from '@angular/core'; + appTree.create('/testSrc/appPrefix/component/paginator-test.component.ts', `import { Component } from '@angular/core'; import { IgxPaginatorComponent } from 'igniteui-angular'; @Component({ @@ -151,10 +140,9 @@ export class PaginatorTestComponent { public testMethod() { return this.paginator.isFirstPageDisabled || this.paginator.isLastPageDisabled; } -}` - ); +}`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - const expectedContent = `import { Component } from '@angular/core'; + const expectedContent = `import { Component } from '@angular/core'; import { IgxPaginatorComponent } from 'igniteui-angular'; @Component({ @@ -168,8 +156,6 @@ export class PaginatorTestComponent { return this.paginator.isFirstPage || this.paginator.isLastPage; } }`; - expect( - tree.readContent('/testSrc/appPrefix/component/paginator-test.component.ts') - ).toEqual(expectedContent); + expect(tree.readContent('/testSrc/appPrefix/component/paginator-test.component.ts')).toEqual(expectedContent); }); }); diff --git a/projects/igniteui-angular/migrations/update-18_2_0/index.spec.ts b/projects/igniteui-angular/migrations/update-18_2_0/index.spec.ts index da436b5514a..3e079ec395e 100644 --- a/projects/igniteui-angular/migrations/update-18_2_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-18_2_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '18.2.0'; @@ -16,9 +17,7 @@ describe(`Update to ${version}`, () => { const migrationName = 'migration-40'; it('Should replace deprecated `shouldGenerate` property with `autoGenerate`', async () => { - appTree.create( - '/testSrc/appPrefix/component/grid-test.component.ts', - `import { Component } from '@angular/core'; + appTree.create('/testSrc/appPrefix/component/grid-test.component.ts', `import { Component } from '@angular/core'; import { IgxGridComponent, IgxTreeGridComponent, IgxHierarchicalGridComponent, IgxPivotGridComponent } from 'igniteui-angular'; @Component({ @@ -38,8 +37,7 @@ describe(`Update to ${version}`, () => { this.hierarchicalGrid.shouldGenerate = true; this.pivotGrid.shouldGenerate = false; } - }` - ); + }`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); const expectedContent = `import { Component } from '@angular/core'; @@ -68,50 +66,39 @@ describe(`Update to ${version}`, () => { }); it('should remove property `filterable` from Combo component', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should migrate scrollbar theme', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$my-scrollbar: scrollbar-theme( + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$my-scrollbar: scrollbar-theme( $scrollbar-size: 16px, $thumb-background: blue, $track-background: black, - );` - ); + );`); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$my-scrollbar: scrollbar-theme( + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$my-scrollbar: scrollbar-theme( $sb-size: 16px, $sb-thumb-bg-color: blue, $sb-track-bg-color: black, - );` - ); + );`); }); it('should remove hsla and hsl functions', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `.custom-body { + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `.custom-body { color: hsla(var(--ig-primary-A100)); background: hsla(var(--ig-gray-100)); } @@ -119,16 +106,12 @@ describe(`Update to ${version}`, () => { .custom-header { color: hsl(var(--ig-secondary-100)); background: hsl(var(--ig-gray-900)); - }` - ); + }`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect( - tree.readContent('/testSrc/appPrefix/component/test.component.scss') - ).toEqual( - `.custom-body { + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`.custom-body { color: var(--ig-primary-A100); background: var(--ig-gray-100); } @@ -136,26 +119,20 @@ describe(`Update to ${version}`, () => { .custom-header { color: var(--ig-secondary-100); background: var(--ig-gray-900); - }` - ); + }`); }); it('should remove the $border-width property from the badge-theme', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-badge: badge-theme( + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-badge: badge-theme( $text-color: red, $border-width: 2px - );` - ); + );`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-badge: badge-theme( + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-badge: badge-theme( $text-color: red - );` - ); + );`); }); }); diff --git a/projects/igniteui-angular/migrations/update-18_2_3/index.spec.ts b/projects/igniteui-angular/migrations/update-18_2_3/index.spec.ts index 07d9c0729ce..f5be83c25da 100644 --- a/projects/igniteui-angular/migrations/update-18_2_3/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-18_2_3/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '18.2.3'; @@ -16,21 +17,16 @@ describe(`Update to ${version}`, () => { const migrationName = 'migration-41'; it('should remove the $header-time-period-color property from the time-picker-theme', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, - `$custom-time-picker: time-picker-theme( + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$custom-time-picker: time-picker-theme( $text-color: red, $header-time-period-color: pink - );` - ); + );`); const tree = await schematicRunner .runSchematic(migrationName, {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `$custom-time-picker: time-picker-theme( + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`$custom-time-picker: time-picker-theme( $text-color: red - );` - ); + );`); }); }); diff --git a/projects/igniteui-angular/migrations/update-19_1_0/index.spec.ts b/projects/igniteui-angular/migrations/update-19_1_0/index.spec.ts index 2c205d02c54..5cbebacc6c3 100644 --- a/projects/igniteui-angular/migrations/update-19_1_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-19_1_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '19.1.0'; const themes = [ @@ -24,76 +25,57 @@ describe(`Update to ${version}`, () => { themes.forEach(theme => { it('should remove the $elevations property from all component themes', async () => { - appTree.create( - testFilePath, - `$custom-${theme}: ${theme}($elevations: $my-elevations);` - ); + appTree.create(testFilePath, `$custom-${theme}: ${theme}($elevations: $my-elevations);`); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent(testFilePath)).toEqual( - `$custom-${theme}: ${theme}();` - ); + expect(tree.readContent(testFilePath)).toEqual(`$custom-${theme}: ${theme}();`); }); }); it('should remove the $palette property from the color-classes mixin', async () => { - const testFilePath = `/testSrc/appPrefix/component/test.component.scss`; + const testFilePath = `/testSrc/appPrefix/component/test.component.scss`; - appTree.create( - testFilePath, - `@include color-classes( + appTree.create(testFilePath, `@include color-classes( $palette: $some-palette, $prop: 'color', $prefix: 'bg' - );` - ); + );`); - const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); + const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent(testFilePath)).toEqual( - `@include color-classes( + expect(tree.readContent(testFilePath)).toEqual(`@include color-classes( $prop: 'color', $prefix: 'bg' - );` - ); + );`); }); it('should replace Query Builder deprecated property `fields` with `entities`', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should remove Query Builder Header deprecated `showLegend` and `resourceStrings` properties', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should remove igx_query_builder_title from resources ', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.ts`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.ts`, ` export class TestComponent { public resourceStrings = { igx_query_builder_add_condition: '+ Add Condition', @@ -103,20 +85,17 @@ describe(`Update to ${version}`, () => { igx_query_builder_create_or_group: 'My create or group' }; } - ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual(` export class TestComponent { public resourceStrings = { igx_query_builder_add_condition: '+ Add Condition', igx_query_builder_add_group: '+ Add Group' }; } - ` - ); + `); }); }); diff --git a/projects/igniteui-angular/migrations/update-19_1_1/index.spec.ts b/projects/igniteui-angular/migrations/update-19_1_1/index.spec.ts index d7c68ffaf43..b67cca7fa45 100644 --- a/projects/igniteui-angular/migrations/update-19_1_1/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-19_1_1/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '19.1.1'; const themes = [ @@ -21,16 +22,11 @@ describe(`Update to ${version}`, () => { themes.forEach(theme => { it('should rename the progress circle color property of the circular progress', async () => { - appTree.create( - testFilePath, - `$custom-${theme}: ${theme}($progress-circle-color: red);` - ); + appTree.create(testFilePath, `$custom-${theme}: ${theme}($progress-circle-color: red);`); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent(testFilePath)).toEqual( - `$custom-${theme}: ${theme}($fill-color-default: red);` - ); + expect(tree.readContent(testFilePath)).toEqual(`$custom-${theme}: ${theme}($fill-color-default: red);`); }); }); }); diff --git a/projects/igniteui-angular/migrations/update-19_1_4/index.spec.ts b/projects/igniteui-angular/migrations/update-19_1_4/index.spec.ts index 7e84f41eaaa..8d934d28c57 100644 --- a/projects/igniteui-angular/migrations/update-19_1_4/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-19_1_4/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '19.1.4'; const themes = [ @@ -22,23 +23,18 @@ describe(`Update to ${version}`, () => { it('should remove the summaries related properties from the grid theme', async () => { const testFilePath = `/testSrc/appPrefix/component/test.component.scss`; - appTree.create( - testFilePath, - `$my-grid-theme: grid-theme( + appTree.create(testFilePath, `$my-grid-theme: grid-theme( $header-background: orange, $root-summaries-background: orange, $root-summaries-text-color: black, $body-summaries-background: orange, $body-summaries-text-color: black, - );` - ); + );`); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent(testFilePath)).toEqual( - `$my-grid-theme: grid-theme( + expect(tree.readContent(testFilePath)).toEqual(`$my-grid-theme: grid-theme( $header-background: orange, - );` - ); + );`); }); }); diff --git a/projects/igniteui-angular/migrations/update-19_2_0/index.spec.ts b/projects/igniteui-angular/migrations/update-19_2_0/index.spec.ts index 46fd2eaba8c..d8e160f80cb 100644 --- a/projects/igniteui-angular/migrations/update-19_2_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-19_2_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '19.2.0'; @@ -16,69 +17,55 @@ describe(`Update to ${version}`, () => { const migrationName = 'migration-45'; it('should remove igx-caroursel property `keyboardSupport` in template', async () => { - appTree.create(`/testSrc/appPrefix/component/test.component.html`, - ` + appTree.create(`/testSrc/appPrefix/component/test.component.html`, ` - ` - ); + `); const tree = await schematicRunner.runSchematic(migrationName, { shouldInvokeLS: false }, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual( - ` + expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')).toEqual(` - ` - ); + `); }); it('should remove the properties related to invalid state from the switch theme', async () => { const testFilePath = `/testSrc/appPrefix/component/test.component.scss`; - appTree.create( - testFilePath, - `$invalid-switch-theme: switch-theme( + appTree.create(testFilePath, `$invalid-switch-theme: switch-theme( $label-color: orange, $label-invalid-color: red, $track-error-color: red, $thumb-on-error-color: darkred, $error-color: red, $error-color-hover: darkred, - );` - ); + );`); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent(testFilePath)).toEqual( - `$invalid-switch-theme: switch-theme( + expect(tree.readContent(testFilePath)).toEqual(`$invalid-switch-theme: switch-theme( $label-color: orange, - );` - ); + );`); }); it('should remove unused properties from the calendar theme', async () => { const testFilePath = `/testSrc/appPrefix/component/test.component.scss`; - appTree.create( - testFilePath, - `$calendar-theme: calendar-theme( + appTree.create(testFilePath, `$calendar-theme: calendar-theme( $date-special-current-border-color: orange, $date-selected-current-outline: orange, $date-selected-current-hover-outline: orange, $date-selected-current-focus-outline: orange, $content-background: black - );` - ); + );`); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent(testFilePath)).toEqual( - `$calendar-theme: calendar-theme( + expect(tree.readContent(testFilePath)).toEqual(`$calendar-theme: calendar-theme( $content-background: black - );` - ); + );`); }); }); diff --git a/projects/igniteui-angular/migrations/update-20_0_0/index.spec.ts b/projects/igniteui-angular/migrations/update-20_0_0/index.spec.ts index 2abf40d3114..e7b047deff4 100644 --- a/projects/igniteui-angular/migrations/update-20_0_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-20_0_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '20.0.0'; @@ -18,20 +19,15 @@ describe(`Update to ${version}`, () => { it('should remove the $focus-background-color property from the grid summary theme', async () => { const testFilePath = `/testSrc/appPrefix/component/test.component.scss`; - appTree.create( - testFilePath, - `$my-grid-theme: grid-summary-theme( + appTree.create(testFilePath, `$my-grid-theme: grid-summary-theme( $label-color: white, $focus-background-color: orange, - );` - ); + );`); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent(testFilePath)).toEqual( - `$my-grid-theme: grid-summary-theme( + expect(tree.readContent(testFilePath)).toEqual(`$my-grid-theme: grid-summary-theme( $label-color: white, - );` - ); + );`); }); }); diff --git a/projects/igniteui-angular/migrations/update-20_0_2/index.spec.ts b/projects/igniteui-angular/migrations/update-20_0_2/index.spec.ts index c4429655a90..cb37e2015a9 100644 --- a/projects/igniteui-angular/migrations/update-20_0_2/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-20_0_2/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '20.0.2'; @@ -18,20 +19,15 @@ describe(`Update to ${version}`, () => { it('should remove the $interim-bottom-line-color property from the input-group theme', async () => { const testFilePath = `/testSrc/appPrefix/component/test.component.scss`; - appTree.create( - testFilePath, - `$my-input-group-theme: input-group-theme( + appTree.create(testFilePath, `$my-input-group-theme: input-group-theme( $box-background: #ccc, $interim-bottom-line-color: orange, - );` - ); + );`); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent(testFilePath)).toEqual( - `$my-input-group-theme: input-group-theme( + expect(tree.readContent(testFilePath)).toEqual(`$my-input-group-theme: input-group-theme( $box-background: #ccc, - );` - ); + );`); }); }); diff --git a/projects/igniteui-angular/migrations/update-20_0_6/index.spec.ts b/projects/igniteui-angular/migrations/update-20_0_6/index.spec.ts index bc1e1f39be6..c09ff610e93 100644 --- a/projects/igniteui-angular/migrations/update-20_0_6/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-20_0_6/index.spec.ts @@ -1,103 +1,100 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Migration 20.0.6 - Replace filteringOptions.filterable', () => { - let appTree: UnitTestTree; - const runner = new SchematicTestRunner( - 'ig-migrate', - path.join(__dirname, '../migration-collection.json') - ); - const migrationName = 'migration-48'; - const makeTemplate = (name: string) => `/testSrc/appPrefix/component/${name}.component.html`; - const makeScript = (name: string) => `/testSrc/appPrefix/component/${name}.component.ts`; - const components = ['igx-simple-combo', 'igx-combo']; - - const warnMsg = - "Manual migration needed: please use 'disableFiltering' instead of filteringOptions.filterable. Since it has been deprecated."; - - beforeEach(() => { - appTree = setupTestTree(); - }); - - it('should replace simple inline filteringOptions.filterable true with default behavior of the simple combo', async () => { - components.forEach(async component =>{ - const input = `<${component} [filteringOptions]="{ filterable: true }">`; - appTree.create(makeTemplate(`${component}-inline-true`), input); - - const tree = await runner.runSchematic(migrationName, {}, appTree); - const output = tree.readContent(makeTemplate(`${component}-inline-true`)); - - expect(output).not.toContain('[disableFiltering]'); - expect(output).not.toContain('filterable'); - }); - }); - - it('should handle mixed object literal correctly', async () => { - components.forEach(async component =>{ - const input = `<${component} [filteringOptions]="{ filterable: false, caseSensitive: true }">`; - appTree.create(makeTemplate(`${component}-inline2`), input); - - const tree = await runner.runSchematic(migrationName, {}, appTree); - const output = tree.readContent(makeTemplate(`${component}-inline2`)); - - expect(output).toContain(`[disableFiltering]="true"`); - expect(output).toContain(`[filteringOptions]="{ caseSensitive: true }"`); - expect(output).not.toContain('filterable'); + let appTree: UnitTestTree; + const runner = new SchematicTestRunner('ig-migrate', path.join(__dirname, '../migration-collection.json')); + const migrationName = 'migration-48'; + const makeTemplate = (name: string) => `/testSrc/appPrefix/component/${name}.component.html`; + const makeScript = (name: string) => `/testSrc/appPrefix/component/${name}.component.ts`; + const components = ['igx-simple-combo', 'igx-combo']; + + const warnMsg = "Manual migration needed: please use 'disableFiltering' instead of filteringOptions.filterable. Since it has been deprecated."; + + beforeEach(() => { + appTree = setupTestTree(); + }); + + it('should replace simple inline filteringOptions.filterable true with default behavior of the simple combo', async () => { + components.forEach(async (component) => { + const input = `<${component} [filteringOptions]="{ filterable: true }">`; + appTree.create(makeTemplate(`${component}-inline-true`), input); + + const tree = await runner.runSchematic(migrationName, {}, appTree); + const output = tree.readContent(makeTemplate(`${component}-inline-true`)); + + expect(output).not.toContain('[disableFiltering]'); + expect(output).not.toContain('filterable'); + }); + }); + + it('should handle mixed object literal correctly', async () => { + components.forEach(async (component) => { + const input = `<${component} [filteringOptions]="{ filterable: false, caseSensitive: true }">`; + appTree.create(makeTemplate(`${component}-inline2`), input); + + const tree = await runner.runSchematic(migrationName, {}, appTree); + const output = tree.readContent(makeTemplate(`${component}-inline2`)); + + expect(output).toContain(`[disableFiltering]="true"`); + expect(output).toContain(`[filteringOptions]="{ caseSensitive: true }"`); + expect(output).not.toContain('filterable'); + }); }); - }); - it('should warn on variable reference', async () => { - for (const component of components) { - const input = `<${component} [filteringOptions]="filterOpts">`; + it('should warn on variable reference', async () => { + for (const component of components) { + const input = `<${component} [filteringOptions]="filterOpts">`; - appTree.create(makeTemplate(`${component}-referenceInTsFile`), input); + appTree.create(makeTemplate(`${component}-referenceInTsFile`), input); - const tree = await runner.runSchematic(migrationName, {}, appTree); - const output = tree.readContent(makeTemplate(`${component}-referenceInTsFile`)); + const tree = await runner.runSchematic(migrationName, {}, appTree); + const output = tree.readContent(makeTemplate(`${component}-referenceInTsFile`)); - expect(output).toContain('[filteringOptions]'); - expect(output).toContain(warnMsg); - } - }); + expect(output).toContain('[filteringOptions]'); + expect(output).toContain(warnMsg); + } + }); - it('should skip adding new [disableFiltering] if already present on igx-combo', async () => { - const input = ``; - appTree.create(makeTemplate('combo-has-disableFiltering'), input); + it('should skip adding new [disableFiltering] if already present on igx-combo', async () => { + const input = ``; + appTree.create(makeTemplate('combo-has-disableFiltering'), input); - const tree = await runner.runSchematic(migrationName, {}, appTree); - const output = tree.readContent(makeTemplate('combo-has-disableFiltering')); + const tree = await runner.runSchematic(migrationName, {}, appTree); + const output = tree.readContent(makeTemplate('combo-has-disableFiltering')); - const occurrences = (output.match(/\[disableFiltering\]/g) || []).length; + const occurrences = (output.match(/\[disableFiltering\]/g) || []).length; - expect(occurrences).toBe(1); - expect(output).not.toContain('filterable'); - }); + expect(occurrences).toBe(1); + expect(output).not.toContain('filterable'); + }); - // TS file tests + // TS file tests - it('should insert warning comment before `.filteringOptions.filterable = ...` assignment', async () => { - const input = `this.igxCombo.filteringOptions.filterable = false;`; - const expectedComment = `// ${warnMsg}`; + it('should insert warning comment before `.filteringOptions.filterable = ...` assignment', async () => { + const input = `this.igxCombo.filteringOptions.filterable = false;`; + const expectedComment = `// ${warnMsg}`; - appTree.create(makeScript('tsWarnOnDirectAssignment'), input); + appTree.create(makeScript('tsWarnOnDirectAssignment'), input); - const tree = await runner.runSchematic(migrationName, {}, appTree); - const output = tree.readContent(makeScript('tsWarnOnDirectAssignment')); + const tree = await runner.runSchematic(migrationName, {}, appTree); + const output = tree.readContent(makeScript('tsWarnOnDirectAssignment')); - expect(output).toContain(expectedComment); - expect(output).toContain('this.igxCombo.filteringOptions.filterable = false;'); - }); + expect(output).toContain(expectedComment); + expect(output).toContain('this.igxCombo.filteringOptions.filterable = false;'); + }); - it('should insert warning comment before `.filteringOptions = { ... }` assignment', async () => { - const input = `this.igxCombo.filteringOptions = { filterable: false, caseSensitive: true };`; - const expectedComment = `// ${warnMsg}`; - appTree.create(makeScript('tsWarnOnObjectAssignment'), input); + it('should insert warning comment before `.filteringOptions = { ... }` assignment', async () => { + const input = `this.igxCombo.filteringOptions = { filterable: false, caseSensitive: true };`; + const expectedComment = `// ${warnMsg}`; + appTree.create(makeScript('tsWarnOnObjectAssignment'), input); - const tree = await runner.runSchematic(migrationName, {}, appTree); - const output = tree.readContent(makeScript('tsWarnOnObjectAssignment')); + const tree = await runner.runSchematic(migrationName, {}, appTree); + const output = tree.readContent(makeScript('tsWarnOnObjectAssignment')); - expect(output).toContain(expectedComment); - expect(output).toContain('this.igxCombo.filteringOptions = { filterable: false, caseSensitive: true };'); - }); + expect(output).toContain(expectedComment); + expect(output).toContain('this.igxCombo.filteringOptions = { filterable: false, caseSensitive: true };'); + }); }); diff --git a/projects/igniteui-angular/migrations/update-20_1_0/index.spec.ts b/projects/igniteui-angular/migrations/update-20_1_0/index.spec.ts index d0c64749457..341b3c8442b 100644 --- a/projects/igniteui-angular/migrations/update-20_1_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-20_1_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '20.1.0'; @@ -18,24 +19,19 @@ describe(`Update to ${version}`, () => { it('should remove properties related to the advanced filtering from the grid theme', async () => { const testFilePath = `/testSrc/appPrefix/component/test.component.scss`; - appTree.create( - testFilePath, - `$my-input-group-theme: grid-theme( + appTree.create(testFilePath, `$my-input-group-theme: grid-theme( $filtering-row-background: #ccc, $filtering-background-and: red, $filtering-background-and--focus: blue, $filtering-background-or: yellow, $filtering-background-or--focus: green - );` - ); + );`); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent(testFilePath)).toEqual( - `$my-input-group-theme: grid-theme( + expect(tree.readContent(testFilePath)).toEqual(`$my-input-group-theme: grid-theme( $filtering-row-background: #ccc - );` - ); + );`); }); }); diff --git a/projects/igniteui-angular/migrations/update-21_0_0/index.spec.ts b/projects/igniteui-angular/migrations/update-21_0_0/index.spec.ts index 1fa8555f17a..937a805fd49 100644 --- a/projects/igniteui-angular/migrations/update-21_0_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-21_0_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; const version = '21.0.0'; @@ -18,46 +19,36 @@ describe(`Update to ${version}`, () => { it('should remove properties related to box-shadows from the outlined-button theme', async () => { const testFilePath = `/testSrc/appPrefix/component/test.component.scss`; - appTree.create( - testFilePath, - `$my-outlined-button-theme: outlined-button-theme( + appTree.create(testFilePath, `$my-outlined-button-theme: outlined-button-theme( $shadow-color: #ffff00, $resting-shadow: 5px 5px #ff0000, $hover-shadow: 5px 5px #0000ff, $focus-shadow: 5px 5px #008000, $active-shadow: 5px 5px #ffa500 - );` - ); + );`); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent(testFilePath)).toEqual( - `$my-outlined-button-theme: outlined-button-theme( + expect(tree.readContent(testFilePath)).toEqual(`$my-outlined-button-theme: outlined-button-theme( $shadow-color: #ffff00 - );` - ); + );`); }); it('should remove properties related to box-shadows from the flat-button theme', async () => { const testFilePath = `/testSrc/appPrefix/component/test.component.scss`; - appTree.create( - testFilePath, - `$my-flat-button-theme: flat-button-theme( + appTree.create(testFilePath, `$my-flat-button-theme: flat-button-theme( $shadow-color: #ffff00, $resting-shadow: 5px 5px #ff0000, $hover-shadow: 5px 5px #0000ff, $focus-shadow: 5px 5px #008000, $active-shadow: 5px 5px #ffa500 - );` - ); + );`); const tree = await schematicRunner.runSchematic(migrationName, {}, appTree); - expect(tree.readContent(testFilePath)).toEqual( - `$my-flat-button-theme: flat-button-theme( + expect(tree.readContent(testFilePath)).toEqual(`$my-flat-button-theme: flat-button-theme( $shadow-color: #ffff00 - );` - ); + );`); }); }); diff --git a/projects/igniteui-angular/migrations/update-6/index.spec.ts b/projects/igniteui-angular/migrations/update-6/index.spec.ts index 4f47553d965..19c6c8085bd 100644 --- a/projects/igniteui-angular/migrations/update-6/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-6/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Update 6.0.0', () => { let appTree: UnitTestTree; @@ -13,10 +14,7 @@ describe('Update 6.0.0', () => { /* eslint-disable arrow-parens */ it('should update igx-tab-bar selector', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', - ' ' - ); + appTree.create('/testSrc/appPrefix/component/test.component.html', ' '); const tree = await schematicRunner.runSchematic('migration-01', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) @@ -24,13 +22,10 @@ describe('Update 6.0.0', () => { }); it('should remove igxForRemote directive', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', - `` - ); + appTree.create('/testSrc/appPrefix/component/test.component.html', ``); const tree = await schematicRunner.runSchematic('migration-01', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual(''); + .toEqual(''); }); }); diff --git a/projects/igniteui-angular/migrations/update-6_01/index.spec.ts b/projects/igniteui-angular/migrations/update-6_01/index.spec.ts index b5db0134d90..f79f028d4fe 100644 --- a/projects/igniteui-angular/migrations/update-6_01/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-6_01/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Update 6.0.1', () => { let appTree: UnitTestTree; @@ -12,26 +13,16 @@ describe('Update 6.0.1', () => { }); it('should update submodule imports', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.ts', - `import { IgxGridComponent } from 'igniteui-angular/main';` + + appTree.create('/testSrc/appPrefix/component/test.component.ts', `import { IgxGridComponent } from 'igniteui-angular/main';` + `import { IgxCsvExporterService } from 'igniteui-angular/services/csv/csv-exporter';` + - `import { IgxButtonDirective } from 'igniteui-angular/directives/button/button.directive';` - ); - appTree.create( - '/testSrc/appPrefix/app.module.ts', - `import { } from 'igniteui-angular';` + - `import { IgxGridModule, IgxGridAPIService } from 'igniteui-angular/grid';` - ); + `import { IgxButtonDirective } from 'igniteui-angular/directives/button/button.directive';`); + appTree.create('/testSrc/appPrefix/app.module.ts', `import { } from 'igniteui-angular';` + + `import { IgxGridModule, IgxGridAPIService } from 'igniteui-angular/grid';`); const tree = await schematicRunner.runSchematic('migration-02', {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual( - `import { IgxGridComponent } from 'igniteui-angular';` + + expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')).toEqual(`import { IgxGridComponent } from 'igniteui-angular';` + `import { IgxCsvExporterService } from 'igniteui-angular';` + - `import { IgxButtonDirective } from 'igniteui-angular';` - ); - expect(tree.readContent('/testSrc/appPrefix/app.module.ts')).toEqual( - `import { } from 'igniteui-angular';` + - `import { IgxGridModule, IgxGridAPIService } from 'igniteui-angular';` - ); + `import { IgxButtonDirective } from 'igniteui-angular';`); + expect(tree.readContent('/testSrc/appPrefix/app.module.ts')).toEqual(`import { } from 'igniteui-angular';` + + `import { IgxGridModule, IgxGridAPIService } from 'igniteui-angular';`); }); }); diff --git a/projects/igniteui-angular/migrations/update-6_02/index.spec.ts b/projects/igniteui-angular/migrations/update-6_02/index.spec.ts index b60f1c80358..39dac264a38 100644 --- a/projects/igniteui-angular/migrations/update-6_02/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-6_02/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Update 6.0.2', () => { let appTree: UnitTestTree; @@ -12,34 +13,24 @@ describe('Update 6.0.2', () => { }); it('should update theme import', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.scss', - `// Import the IgniteUI themes library first` + + appTree.create('/testSrc/appPrefix/component/test.component.scss', `// Import the IgniteUI themes library first` + `@import "~igniteui-angular/core/styles/themes/index";` + `$company-color: #2ab759; // Some green shade I like` + `$secondary-color: #f96a88; // Watermelon pink` + `$my-color-palette: igx-palette(` + ` $primary: $company-color,` + ` $secondary: $secondary-color` + - `);` - ); - appTree.create( - '/testSrc/testSrc/styles.scss', - `@import "~igniteui-angular/core/styles/themes/_index.scss";` - ); + `);`); + appTree.create('/testSrc/testSrc/styles.scss', `@import "~igniteui-angular/core/styles/themes/_index.scss";`); const tree = await schematicRunner.runSchematic('migration-03', {}, appTree); - expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual( - `// Import the IgniteUI themes library first` + + expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')).toEqual(`// Import the IgniteUI themes library first` + `@import "~igniteui-angular/lib/core/styles/themes/index";` + `$company-color: #2ab759; // Some green shade I like` + `$secondary-color: #f96a88; // Watermelon pink` + `$my-color-palette: igx-palette(` + ` $primary: $company-color,` + ` $secondary: $secondary-color` + - `);` - ); - expect(tree.readContent('/testSrc/testSrc/styles.scss')).toEqual( - `@import "~igniteui-angular/lib/core/styles/themes/_index.scss";` - ); + `);`); + expect(tree.readContent('/testSrc/testSrc/styles.scss')).toEqual(`@import "~igniteui-angular/lib/core/styles/themes/_index.scss";`); }); }); diff --git a/projects/igniteui-angular/migrations/update-6_1/index.spec.ts b/projects/igniteui-angular/migrations/update-6_1/index.spec.ts index e6e3fefccc4..8df040e3d34 100644 --- a/projects/igniteui-angular/migrations/update-6_1/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-6_1/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Update 6.1.0', () => { let appTree: UnitTestTree; @@ -12,15 +13,11 @@ describe('Update 6.1.0', () => { }); it('should update igxToggle events and selectors', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', - `` + - `` - ); + appTree.create('/testSrc/appPrefix/component/test.component.html', `` + + ``); const tree = await schematicRunner.runSchematic('migration-04', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual( - `` + - ``); + .toEqual(`` + + ``); }); }); diff --git a/projects/igniteui-angular/migrations/update-6_2/index.spec.ts b/projects/igniteui-angular/migrations/update-6_2/index.spec.ts index 040f1fa094d..3931d2d132f 100644 --- a/projects/igniteui-angular/migrations/update-6_2/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-6_2/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Update 6.2.0', () => { let appTree: UnitTestTree; @@ -12,33 +13,24 @@ describe('Update 6.2.0', () => { }); it('should update igxDatePicker selector', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', - `` - ); + appTree.create('/testSrc/appPrefix/component/test.component.html', ``); const tree = await schematicRunner.runSchematic('migration-05', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) .toEqual(``); }); it('should remove igx-combo height property', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', - `` - ); + appTree.create('/testSrc/appPrefix/component/test.component.html', ``); const tree = await schematicRunner.runSchematic('migration-05', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) .toEqual(``); }); it('should move igx-icon name property value between element tags only for material fontSet', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', - ` + appTree.create('/testSrc/appPrefix/component/test.component.html', ` -` - ); +`); const tree = await schematicRunner.runSchematic('migration-05', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) @@ -49,10 +41,7 @@ describe('Update 6.2.0', () => { }); it('should rename igx-grid onEditDone event', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', - ` ` - ); + appTree.create('/testSrc/appPrefix/component/test.component.html', ` `); const tree = await schematicRunner.runSchematic('migration-05', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) .toEqual(` `); diff --git a/projects/igniteui-angular/migrations/update-6_2_1/index.spec.ts b/projects/igniteui-angular/migrations/update-6_2_1/index.spec.ts index d34de1a05df..6aeb548f708 100644 --- a/projects/igniteui-angular/migrations/update-6_2_1/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-6_2_1/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Update 6.2.1', () => { let appTree: UnitTestTree; @@ -12,26 +13,21 @@ describe('Update 6.2.1', () => { }); it('should update Sass files', async () => { - appTree.create( - '/testSrc/appPrefix/style.scss', -`$dark-chip-theme: igx-chip-theme( + appTree.create('/testSrc/appPrefix/style.scss', `$dark-chip-theme: igx-chip-theme( $roundness: 4px, $chip-background: #180505, $chip-hover-background: white, $remove-icon-color: red, $dir-icon-color: yellow, $selected-chip-hover-background: gray -);` - ); +);`); const tree = await schematicRunner.runSchematic('migration-06', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/style.scss')) - .toEqual( -`$dark-chip-theme: igx-chip-theme( + .toEqual(`$dark-chip-theme: igx-chip-theme( $roundness: 4px, $background: #180505, $hover-background: white, $hover-selected-background: gray -);` - ); +);`); }); }); diff --git a/projects/igniteui-angular/migrations/update-7_0_2/index.spec.ts b/projects/igniteui-angular/migrations/update-7_0_2/index.spec.ts index 97ac45248e8..2afe71dfc67 100644 --- a/projects/igniteui-angular/migrations/update-7_0_2/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-7_0_2/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Update 7.0.2', () => { let appTree: UnitTestTree; @@ -12,9 +13,7 @@ describe('Update 7.0.2', () => { }); it('should remove .forRoot() from imports', async () => { - appTree.create( - '/testSrc/appPrefix/module/test.module.ts', - `@NgModule({ + appTree.create('/testSrc/appPrefix/module/test.module.ts', `@NgModule({ declarations: components, imports: [ IgxIconModule.forRoot(), @@ -31,8 +30,7 @@ describe('Update 7.0.2', () => { const tree = await schematicRunner.runSchematic('migration-07', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/module/test.module.ts')) - .toEqual( - `@NgModule({ + .toEqual(`@NgModule({ declarations: components, imports: [ IgxIconModule, diff --git a/projects/igniteui-angular/migrations/update-7_2_0/index.spec.ts b/projects/igniteui-angular/migrations/update-7_2_0/index.spec.ts index 3c51268d05e..c15983ecffd 100644 --- a/projects/igniteui-angular/migrations/update-7_2_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-7_2_0/index.spec.ts @@ -6,6 +6,7 @@ import { workspaces } from '@angular-devkit/core'; import * as addNormalize from '../../schematics/ng-add/add-normalize'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('Update 7.2.0', () => { let appTree: UnitTestTree; @@ -16,9 +17,7 @@ describe('Update 7.2.0', () => { }); it(`should replace **ONLY** 'isSelected' and 'isFocused'`, async () => { - appTree.create( - '/testSrc/appPrefix/component/custom.component.html', - ` + appTree.create('/testSrc/appPrefix/component/custom.component.html', ` { const tree = await schematicRunner.runSchematic('migration-08', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/custom.component.html')) - .toEqual( - ` + .toEqual(` { it(`should add minireset css package and import`, async () => { appTree.create('/testSrc/styles.scss', ''); appTree.create('package.json', '{}'); - spyOn(addNormalize, 'addResetCss').and.callThrough(); + vi.spyOn(addNormalize, 'addResetCss'); const tree = await schematicRunner.runSchematic('migration-08', {}, appTree); - expect(addNormalize.addResetCss).toHaveBeenCalledWith( - jasmine.objectContaining({ - extensions: jasmine.anything(), - projects: jasmine.anything() - }), appTree); + expect(addNormalize.addResetCss).toHaveBeenCalledWith(expect.objectContaining({ + extensions: expect.anything(), + projects: expect.anything() + }), appTree); expect(tree.readContent('/testSrc/styles.scss')).toContain(addNormalize.scssImport); expect(JSON.parse(tree.readContent('package.json'))).toEqual({ dependencies: { 'minireset.css': '~0.0.4' } diff --git a/projects/igniteui-angular/migrations/update-7_3_4/index.spec.ts b/projects/igniteui-angular/migrations/update-7_3_4/index.spec.ts index f909467c214..ad4306c8fb0 100644 --- a/projects/igniteui-angular/migrations/update-7_3_4/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-7_3_4/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Update 7.3.4', () => { let appTree: UnitTestTree; @@ -12,24 +13,16 @@ describe('Update 7.3.4', () => { }); it('should update time picker events', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', - `` - ); + appTree.create('/testSrc/appPrefix/component/test.component.html', ``); const tree = await schematicRunner.runSchematic('migration-09', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual( - ``); + .toEqual(``); }); it('should update date picker events', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.html', - `` - ); + appTree.create('/testSrc/appPrefix/component/test.component.html', ``); const tree = await schematicRunner.runSchematic('migration-09', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.html')) - .toEqual( - ``); + .toEqual(``); }); }); diff --git a/projects/igniteui-angular/migrations/update-8_2_0/index.spec.ts b/projects/igniteui-angular/migrations/update-8_2_0/index.spec.ts index 97816070b61..dc85782f95e 100644 --- a/projects/igniteui-angular/migrations/update-8_2_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-8_2_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Update 8.2.0', () => { let appTree: UnitTestTree; @@ -12,9 +13,7 @@ describe('Update 8.2.0', () => { }); it('should update Excel Style Filtering template selectors', async () => { - appTree.create( - '/testSrc/appPrefix/component/custom.component.html', - ` + appTree.create('/testSrc/appPrefix/component/custom.component.html', `
Sorting Template
Hiding Template
Moving Template
@@ -23,8 +22,7 @@ describe('Update 8.2.0', () => { const tree = await schematicRunner.runSchematic('migration-10', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/custom.component.html')) - .toEqual( - ` + .toEqual(`
Sorting Template
Hiding Template
Moving Template
@@ -34,20 +32,15 @@ describe('Update 8.2.0', () => { }); it('should update igxDrag input bindings', async () => { - appTree.create( - '/testSrc/appPrefix/component/custom.component.html', - `
Drag me
`); + appTree.create('/testSrc/appPrefix/component/custom.component.html', `
Drag me
`); const tree = await schematicRunner.runSchematic('migration-10', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/custom.component.html')) - .toEqual( - `
Drag me
`); + .toEqual(`
Drag me
`); }); it('should update igxDrag and igxDrop outputs bindings', async () => { - appTree.create( - '/testSrc/appPrefix/component/custom.component.html', - `
@@ -58,8 +51,7 @@ describe('Update 8.2.0', () => { const tree = await schematicRunner.runSchematic('migration-10', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/custom.component.html')) - .toEqual( - `
@@ -70,9 +62,7 @@ describe('Update 8.2.0', () => { }); it('should update igxDrag and igxDrop event argument interfaces', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.ts', - `import { IgxDragDirective, IgxDropDirective, IgxDropEnterEventArgs, + appTree.create('/testSrc/appPrefix/component/test.component.ts', `import { IgxDragDirective, IgxDropDirective, IgxDropEnterEventArgs, IgxDropLeaveEventArgs, IgxDropEventArgs } from 'igniteui-angular'; export class DragDropSampleComponent { @@ -82,10 +72,9 @@ describe('Update 8.2.0', () => { }`); const tree = await schematicRunner.runSchematic('migration-10', {}, appTree); - // V.S. 18th May 2021: No longer leave duplicate imports in post-migration file + // V.S. 18th May 2021: No longer leave duplicate imports in post-migration file expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')) - .toEqual( - `import { IgxDragDirective, IgxDropDirective, IDropBaseEventArgs, + .toEqual(`import { IgxDragDirective, IgxDropDirective, IDropBaseEventArgs, IDropDroppedEventArgs } from 'igniteui-angular'; export class DragDropSampleComponent { diff --git a/projects/igniteui-angular/migrations/update-8_2_3/index.spec.ts b/projects/igniteui-angular/migrations/update-8_2_3/index.spec.ts index 7759314db74..44bd3b282b9 100644 --- a/projects/igniteui-angular/migrations/update-8_2_3/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-8_2_3/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Update 8.2.3', () => { let appTree: UnitTestTree; @@ -12,22 +13,17 @@ describe('Update 8.2.3', () => { }); it('should update igx-carousel-theme prop', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.scss', - `$my-carousel-theme: igx-carousel-theme( + appTree.create('/testSrc/appPrefix/component/test.component.scss', `$my-carousel-theme: igx-carousel-theme( $button-background: black, $disable-button-shadow: black, $button-hover-background: white - );` - ); + );`); const tree = await schematicRunner.runSchematic('migration-11', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')) - .toEqual( - `$my-carousel-theme: igx-carousel-theme( + .toEqual(`$my-carousel-theme: igx-carousel-theme( $button-background: black, $button-shadow: black, $button-hover-background: white - );` - ); + );`); }); }); diff --git a/projects/igniteui-angular/migrations/update-8_2_6/index.spec.ts b/projects/igniteui-angular/migrations/update-8_2_6/index.spec.ts index 6bf82b6b0d3..c04ff893df5 100644 --- a/projects/igniteui-angular/migrations/update-8_2_6/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-8_2_6/index.spec.ts @@ -1,6 +1,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Update 8.2.6', () => { let appTree: UnitTestTree; @@ -11,9 +12,7 @@ describe('Update 8.2.6', () => { }); it('should update igx-carousel-theme prop', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.scss', - `$my-toolbar-theme: igx-grid-toolbar-theme( + appTree.create('/testSrc/appPrefix/component/test.component.scss', `$my-toolbar-theme: igx-grid-toolbar-theme( $background-color: null, $button-background: null, $title-text-color: null, @@ -28,12 +27,10 @@ describe('Update 8.2.6', () => { $item-hover-text-color: null, $item-focus-background: null, $item-focus-text-color: null - );` - ); + );`); const tree = await schematicRunner.runSchematic('migration-12', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')) - .toEqual( - `$my-toolbar-theme: igx-grid-toolbar-theme( + .toEqual(`$my-toolbar-theme: igx-grid-toolbar-theme( $background-color: null, $title-text-color: null, $dropdown-background: null, @@ -42,33 +39,27 @@ describe('Update 8.2.6', () => { $item-hover-text-color: null, $item-focus-background: null, $item-focus-text-color: null - );` - ); + );`); }); it('should update igx-grid-paginator-theme', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.scss', - `@import '~igniteui-angular/lib/core/styles/components/grid-paginator/grid-paginator-component'; + appTree.create('/testSrc/appPrefix/component/test.component.scss', `@import '~igniteui-angular/lib/core/styles/components/grid-paginator/grid-paginator-component'; @import '~igniteui-angular/lib/core/styles/components/grid-paginator/grid-paginator-theme'; $dark-grid-paginator: igx-grid-paginator-theme($color: black); @include igx-grid-paginator($dark-grid-paginator); .igx-grid-paginator__pager { @include igx-button($dark-button); } - $dark-grid-paginator-schema: extend($_dark-grid-pagination,());` - ); + $dark-grid-paginator-schema: extend($_dark-grid-pagination,());`); const tree = await schematicRunner.runSchematic('migration-12', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')) - .toEqual( - `@import '~igniteui-angular/lib/core/styles/components/paginator/paginator-component'; + .toEqual(`@import '~igniteui-angular/lib/core/styles/components/paginator/paginator-component'; @import '~igniteui-angular/lib/core/styles/components/paginator/paginator-theme'; $dark-grid-paginator: igx-paginator-theme($color: black); @include igx-paginator($dark-grid-paginator); .igx-grid-paginator__pager { @include igx-button($dark-button); } - $dark-grid-paginator-schema: extend($_dark-pagination,());` - ); + $dark-grid-paginator-schema: extend($_dark-pagination,());`); }); }); diff --git a/projects/igniteui-angular/migrations/update-9_0_0/index.spec.ts b/projects/igniteui-angular/migrations/update-9_0_0/index.spec.ts index d4f9a6ac977..582bec56c22 100644 --- a/projects/igniteui-angular/migrations/update-9_0_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-9_0_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Update 9.0.0', () => { let appTree: UnitTestTree; @@ -12,38 +13,29 @@ describe('Update 9.0.0', () => { }); it('should update base class names.', async () => { - appTree.create( - '/testSrc/appPrefix/component/test.component.ts', - `import { IgxDropDownBase, IgxDropDownItemBase, IgxGridBaseComponent, + appTree.create('/testSrc/appPrefix/component/test.component.ts', `import { IgxDropDownBase, IgxDropDownItemBase, IgxGridBaseComponent, IgxRowComponent, IgxHierarchicalGridBaseComponent } from 'igniteui-angular'; `); const tree = await schematicRunner.runSchematic('migration-13', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.ts')) - .toEqual( - `import { IgxDropDownBaseDirective, IgxDropDownItemBaseDirective, IgxGridBaseDirective, + .toEqual(`import { IgxDropDownBaseDirective, IgxDropDownItemBaseDirective, IgxGridBaseDirective, IgxRowDirective, IgxHierarchicalGridBaseDirective } from 'igniteui-angular'; `); }); it('should update Enum names.', async () => { - appTree.create( - '/testSrc/appPrefix/component/enum.component.ts', - `import { AvatarType, Size, Type, SliderType } from 'igniteui-angular'; + appTree.create('/testSrc/appPrefix/component/enum.component.ts', `import { AvatarType, Size, Type, SliderType } from 'igniteui-angular'; `); const tree = await schematicRunner.runSchematic('migration-13', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/enum.component.ts')) - .toEqual( - `import { IgxAvatarType, IgxAvatarSize, IgxBadgeType, IgxSliderType } from 'igniteui-angular'; + .toEqual(`import { IgxAvatarType, IgxAvatarSize, IgxBadgeType, IgxSliderType } from 'igniteui-angular'; `); }); it('should update input prop from tabsType to type', async () => { - appTree.create( - '/testSrc/appPrefix/component/tabs.component.html', - '' - ); + appTree.create('/testSrc/appPrefix/component/tabs.component.html', ''); const tree = await schematicRunner.runSchematic('migration-13', {}, appTree); diff --git a/projects/igniteui-angular/migrations/update-9_0_1/index.spec.ts b/projects/igniteui-angular/migrations/update-9_0_1/index.spec.ts index a9be020a46c..83ccddcd0c0 100644 --- a/projects/igniteui-angular/migrations/update-9_0_1/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-9_0_1/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Update 9.0.1', () => { let appTree: UnitTestTree; @@ -14,20 +15,17 @@ describe('Update 9.0.1', () => { }); it('Should remove $base-color', async () => { - appTree.create( - `/testSrc/appPrefix/component/test.component.scss`, -`$typography: igx-typography( + appTree.create(`/testSrc/appPrefix/component/test.component.scss`, `$typography: igx-typography( $base-color: white, $font-family: null, $type-scale: null ); `); - const tree = await _schematicRunner - .runSchematic(migrationName, {}, appTree); + const tree = await _schematicRunner + .runSchematic(migrationName, {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/test.component.scss')) - .toEqual( -`$typography: igx-typography( + .toEqual(`$typography: igx-typography( $font-family: null, $type-scale: null ); diff --git a/projects/igniteui-angular/migrations/update-9_1_0/index.spec.ts b/projects/igniteui-angular/migrations/update-9_1_0/index.spec.ts index 2a18acc8f11..c3460e71795 100644 --- a/projects/igniteui-angular/migrations/update-9_1_0/index.spec.ts +++ b/projects/igniteui-angular/migrations/update-9_1_0/index.spec.ts @@ -2,6 +2,7 @@ import * as path from 'path'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import { setupTestTree } from '../common/setup.spec'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('Update 9.1.0', () => { let appTree: UnitTestTree; @@ -12,10 +13,7 @@ describe('Update 9.1.0', () => { }); it('should update igx-group supressInputAutofocus to suppressInputAutofocus', async () => { - appTree.create( - `/testSrc/appPrefix/component/input.component.html`, - '' - ); + appTree.create(`/testSrc/appPrefix/component/input.component.html`, ''); const tree = await schematicRunner.runSchematic('migration-15', {}, appTree); @@ -25,36 +23,28 @@ describe('Update 9.1.0', () => { }); it('should move igx-toast message property between element tags', async () => { - appTree.create( - `/testSrc/appPrefix/component/input.component.html`, - '' - ); + appTree.create(`/testSrc/appPrefix/component/input.component.html`, ''); const tree = await schematicRunner.runSchematic('migration-15', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/input.component.html')) - .toEqual('test message'); + .toEqual('test message'); }); // Except for testing for true and false (' and ") check for binded scenarios like "'prop'" it('should update rowSelectable to rowSelection', async () => { - appTree.create( - `/testSrc/appPrefix/component/input.component.html`, - `` - ); + appTree.create(`/testSrc/appPrefix/component/input.component.html`, ``); const tree = await schematicRunner.runSchematic('migration-15', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/input.component.html')) - .toEqual(``); + .toEqual(``); }); it('should update rowSelectable to rowSelection when false', async () => { - appTree.create( - `/testSrc/appPrefix/component/input.component.html`, - `
[rowSelectable]="true"
+ appTree.create(`/testSrc/appPrefix/component/input.component.html`, `
[rowSelectable]="true"
{ const tree = await schematicRunner.runSchematic('migration-15', {}, appTree); expect(tree.readContent('/testSrc/appPrefix/component/input.component.html')) - .toEqual(`
[rowSelectable]="true"
+ .toEqual(`
[rowSelectable]="true"
{ }).compileComponents(); })); - let fixture; let component; let domNavbar; + let fixture; + let component; + let domNavbar; describe('Default Action Icon', () => { beforeEach(() => { @@ -66,7 +69,7 @@ describe('IgxNavbar', () => { component.actionButtonIcon = 'home'; fixture.detectChanges(); - spyOn(component.navbar.action, 'emit'); + vi.spyOn(component.navbar.action, 'emit'); fixture.debugElement.nativeElement.querySelector('igx-icon').click(); fixture.detectChanges(); @@ -84,14 +87,14 @@ describe('IgxNavbar', () => { // Verify there is no custom content on the left const customContent = leftArea.query(By.css('igx-navbar-action')); - expect(customContent).toBeNull('Custom action icon content is found on the left.'); + expect(customContent, 'Custom action icon content is found on the left.').toBeNull(); // Verify there is a default icon on the left. const defaultIcon = leftArea.query(By.css('igx-icon')); expect(defaultIcon).not.toBeNull('Default icon is not found on the left.'); const leftAreaLeft = leftArea.nativeElement.getBoundingClientRect().left; const defaultIconLeft = defaultIcon.nativeElement.getBoundingClientRect().left; - expect(leftAreaLeft).toBe(defaultIconLeft, 'Default icon is not first on the left.'); + expect(leftAreaLeft, 'Default icon is not first on the left.').toBe(defaultIconLeft); }); }); @@ -104,14 +107,14 @@ describe('IgxNavbar', () => { // Verify there is no default icon on the left. const defaultIcon = leftArea.query(By.css('igx-icon')); - expect(defaultIcon).toBeNull('Default icon is found on the left.'); + expect(defaultIcon, 'Default icon is found on the left.').toBeNull(); // Verify there is a custom content on the left. const customContent = leftArea.query(By.css('igx-navbar-action')); expect(customContent).not.toBeNull('Custom action icon content is not found on the left.'); const leftAreaLeft = leftArea.nativeElement.getBoundingClientRect().left; const customContentLeft = customContent.nativeElement.getBoundingClientRect().left; - expect(leftAreaLeft).toBe(customContentLeft, 'Custom action icon content is not first on the left.'); + expect(leftAreaLeft, 'Custom action icon content is not first on the left.').toBe(customContentLeft); }); it('should have vertically-centered custom action icon content', (async () => { @@ -130,7 +133,7 @@ describe('IgxNavbar', () => { const navbarMidpoint = Math.round(navbarRect.top + (navbarRect.height / 2)); const iconMidpoint = Math.round(iconRect.top + (iconRect.height / 2)); - expect(navbarMidpoint).toBe(iconMidpoint, 'Custom icon is not exactly vertically centered within the navbar.'); + expect(navbarMidpoint, 'Custom icon is not exactly vertically centered within the navbar.').toBe(iconMidpoint); })); it('action icon via directive', (async () => { @@ -143,7 +146,7 @@ describe('IgxNavbar', () => { const leftAreaLeft = leftArea.nativeElement.getBoundingClientRect().left; const customContentLeft = customContent.nativeElement.getBoundingClientRect().left; - expect(leftAreaLeft).toBe(customContentLeft, 'Custom action icon content is not first on the left.'); + expect(leftAreaLeft, 'Custom action icon content is not first on the left.').toBe(customContentLeft); })); }); @@ -163,10 +166,10 @@ describe('IgxNavbar', () => { // Verify there is no default icon on the left. const customTitle = midArea.query(By.css('igx-navbar-title')); - expect(customTitle.nativeElement.textContent).toBe('Custom Title', 'Custom title is missing'); + expect(customTitle.nativeElement.textContent, 'Custom title is missing').toBe('Custom Title'); const defaultTitle = midArea.query(By.css('igx-navbar__title')); - expect(defaultTitle).toBeNull('Default title should not be present'); + expect(defaultTitle, 'Default title should not be present').toBeNull(); }); it('Custom content should override the default title property', () => { @@ -177,11 +180,11 @@ describe('IgxNavbar', () => { // Verify there is no default icon on the left. const customTitle = midArea.query(By.directive(IgxNavbarTitleDirective)); - expect(customTitle.nativeElement.children[0].textContent).toBe('Custom', 'Custom title is missing'); - expect(customTitle.nativeElement.children[1].textContent).toBe('Title', 'Custom title is missing'); + expect(customTitle.nativeElement.children[0].textContent, 'Custom title is missing').toBe('Custom'); + expect(customTitle.nativeElement.children[1].textContent, 'Custom title is missing').toBe('Title'); const defaultTitle = midArea.query(By.css('igx-navbar__title')); - expect(defaultTitle).toBeNull('Default title should not be present'); + expect(defaultTitle, 'Default title should not be present').toBeNull(); }); }); }); @@ -195,7 +198,8 @@ describe('IgxNavbar', () => { imports: [IgxNavbarComponent] }) class NavbarIntializeTestComponent { - @ViewChild(IgxNavbarComponent, { static: true }) public navbar: IgxNavbarComponent; + @ViewChild(IgxNavbarComponent, { static: true }) + public navbar: IgxNavbarComponent; public title: string; public actionButtonIcon: string; public isActionButtonVisible: boolean; @@ -214,7 +218,8 @@ class NavbarIntializeTestComponent { imports: [IgxNavbarComponent, IgxNavbarActionDirective] }) class NavbarCustomActionIconTestComponent { - @ViewChild(IgxNavbarComponent, { static: true }) public navbar: IgxNavbarComponent; + @ViewChild(IgxNavbarComponent, { static: true }) + public navbar: IgxNavbarComponent; } @Component({ @@ -230,7 +235,8 @@ class NavbarCustomActionIconTestComponent { imports: [IgxNavbarComponent, IgxNavbarActionDirective, IgxIconComponent] }) class NavbarCustomIgxIconTestComponent { - @ViewChild(IgxNavbarComponent, { static: true }) public navbar: IgxNavbarComponent; + @ViewChild(IgxNavbarComponent, { static: true }) + public navbar: IgxNavbarComponent; } @Component({ @@ -244,7 +250,8 @@ class NavbarCustomIgxIconTestComponent { imports: [IgxNavbarComponent, IgxIconComponent, IgxNavbarActionDirective] }) class NavbarCustomIgxIconDirectiveTestComponent { - @ViewChild(IgxNavbarComponent, { static: true }) public navbar: IgxNavbarComponent; + @ViewChild(IgxNavbarComponent, { static: true }) + public navbar: IgxNavbarComponent; } @Component({ @@ -261,7 +268,8 @@ class NavbarCustomIgxIconDirectiveTestComponent { imports: [IgxNavbarComponent, IgxNavbarActionDirective, IgxNavbarTitleDirective, IgxIconComponent] }) class NavbarCustomTitleTestComponent { - @ViewChild(IgxNavbarComponent, { static: true }) public navbar: IgxNavbarComponent; + @ViewChild(IgxNavbarComponent, { static: true }) + public navbar: IgxNavbarComponent; } @Component({ @@ -281,5 +289,6 @@ class NavbarCustomTitleTestComponent { imports: [IgxNavbarComponent, IgxNavbarActionDirective, IgxNavbarTitleDirective, IgxIconComponent] }) class NavbarCustomTitleDirectiveTestComponent { - @ViewChild(IgxNavbarComponent, { static: true }) public navbar: IgxNavbarComponent; + @ViewChild(IgxNavbarComponent, { static: true }) + public navbar: IgxNavbarComponent; } diff --git a/projects/igniteui-angular/navigation-drawer/src/navigation-drawer/navigation-drawer.component.spec.ts b/projects/igniteui-angular/navigation-drawer/src/navigation-drawer/navigation-drawer.component.spec.ts index 6361e9eaa1e..bade2699e60 100644 --- a/projects/igniteui-angular/navigation-drawer/src/navigation-drawer/navigation-drawer.component.spec.ts +++ b/projects/igniteui-angular/navigation-drawer/src/navigation-drawer/navigation-drawer.component.spec.ts @@ -1,3 +1,4 @@ +import type { Mock } from "vitest"; import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { Component, ElementRef, Renderer2, ViewChild } from '@angular/core'; import { By } from '@angular/platform-browser'; @@ -7,12 +8,13 @@ import { HammerGesturesManager, IgxNavigationService } from 'igniteui-angular/co import { IgxNavDrawerItemDirective, IgxNavDrawerMiniTemplateDirective, IgxNavDrawerTemplateDirective } from './navigation-drawer.directives'; import { IgxNavbarComponent } from 'igniteui-angular/navbar'; import { IgxFlexDirective, IgxLayoutDirective } from 'igniteui-angular/directives'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; // HammerJS simulator from https://github.com/hammerjs/simulator, manual typings TODO declare let Simulator: any; describe('Navigation Drawer', () => { - let widthSpyOverride: jasmine.Spy; + let widthSpyOverride: Mock; beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [ @@ -31,8 +33,7 @@ describe('Navigation Drawer', () => { // Using Window through DI causes AOT error (https://github.com/angular/angular/issues/15640) // so for tests just force override the the `getWindowWidth` - widthSpyOverride = spyOn(IgxNavigationDrawerComponent.prototype as any, 'getWindowWidth') - .and.returnValue(915 /* chosen at random by fair dice roll*/); + widthSpyOverride = vi.spyOn(IgxNavigationDrawerComponent.prototype as any, 'getWindowWidth').mockReturnValue(915 /* chosen at random by fair dice roll*/); })); it('should initialize without DI service', waitForAsync(() => { @@ -154,28 +155,28 @@ describe('Navigation Drawer', () => { fixture.detectChanges(); drawer = fixture.componentInstance.navDrawer; - spyOn(drawer.closing, 'emit'); - spyOn(drawer.closed, 'emit'); - spyOn(drawer.opening, 'emit'); - spyOn(drawer.opened, 'emit'); + vi.spyOn(drawer.closing, 'emit'); + vi.spyOn(drawer.closed, 'emit'); + vi.spyOn(drawer.opening, 'emit'); + vi.spyOn(drawer.opened, 'emit'); const _re = drawer.open(true); fixture.detectChanges(); fixture.debugElement.children[0].nativeElement.dispatchEvent(new Event('transitionend')); }) .then(() => { - expect(drawer.opening.emit).toHaveBeenCalled(); - expect(drawer.opened.emit).toHaveBeenCalled(); + expect(drawer.opening.emit).toHaveBeenCalled(); + expect(drawer.opened.emit).toHaveBeenCalled(); - const _re = drawer.toggle(true); - fixture.detectChanges(); - fixture.debugElement.children[0].nativeElement.dispatchEvent(new Event('transitionend')); - }) + const _re = drawer.toggle(true); + fixture.detectChanges(); + fixture.debugElement.children[0].nativeElement.dispatchEvent(new Event('transitionend')); + }) .then(() => { - expect(drawer.closing.emit).toHaveBeenCalled(); - expect(drawer.closed.emit).toHaveBeenCalled(); - // resolver(); - }); + expect(drawer.closing.emit).toHaveBeenCalled(); + expect(drawer.closed.emit).toHaveBeenCalled(); + // resolver(); + }); })); it('should properly initialize with min template', waitForAsync(() => { @@ -204,8 +205,9 @@ describe('Navigation Drawer', () => { it('should update with dynamic min template', waitForAsync(() => { // immediate requestAnimationFrame for testing - spyOn(window, 'requestAnimationFrame').and.callFake(callback => { - callback(0); return 0; + vi.spyOn(window, 'requestAnimationFrame').mockImplementation(callback => { + callback(0); + return 0; }); const template = ` @@ -281,30 +283,30 @@ describe('Navigation Drawer', () => { TestBed.overrideComponent(TestComponentPinComponent, { set: { template } }); TestBed.compileComponents() .then(() => { - document.body.style.overflow = 'hidden'; - const fixture = TestBed.createComponent(TestComponentPinComponent); - fixture.detectChanges(); - const windowHeight = window.innerHeight; - const container = fixture.debugElement.query(By.css('div')).nativeElement; - const navdrawer = fixture.debugElement.query(By.css('igx-nav-drawer > .igx-nav-drawer__aside')).nativeElement; - - fixture.componentInstance.pin = false; - fixture.detectChanges(); - expect(navdrawer.clientHeight).toEqual(windowHeight); - - fixture.componentInstance.pin = true; - fixture.detectChanges(); - expect(navdrawer.clientHeight).toEqual(container.clientHeight); - - container.style.height = `${windowHeight - 50}px`; - fixture.detectChanges(); - expect(navdrawer.clientHeight).toEqual(windowHeight - 50); - - // unpin : - fixture.componentInstance.pin = false; - fixture.detectChanges(); - expect(navdrawer.clientHeight).toEqual(windowHeight); - }); + document.body.style.overflow = 'hidden'; + const fixture = TestBed.createComponent(TestComponentPinComponent); + fixture.detectChanges(); + const windowHeight = window.innerHeight; + const container = fixture.debugElement.query(By.css('div')).nativeElement; + const navdrawer = fixture.debugElement.query(By.css('igx-nav-drawer > .igx-nav-drawer__aside')).nativeElement; + + fixture.componentInstance.pin = false; + fixture.detectChanges(); + expect(navdrawer.clientHeight).toEqual(windowHeight); + + fixture.componentInstance.pin = true; + fixture.detectChanges(); + expect(navdrawer.clientHeight).toEqual(container.clientHeight); + + container.style.height = `${windowHeight - 50}px`; + fixture.detectChanges(); + expect(navdrawer.clientHeight).toEqual(windowHeight - 50); + + // unpin : + fixture.componentInstance.pin = false; + fixture.detectChanges(); + expect(navdrawer.clientHeight).toEqual(windowHeight); + }); })); it('should set flex-basis and order when pinned', waitForAsync(() => { @@ -313,47 +315,48 @@ describe('Navigation Drawer', () => { let fixture: ComponentFixture; TestBed.compileComponents() .then(() => { - fixture = TestBed.createComponent(TestComponentPinComponent); - const drawer = fixture.componentInstance.navDrawer; - drawer.isOpen = true; - fixture.detectChanges(); - const drawerElem = fixture.debugElement.query((x) => x.nativeNode.nodeName === 'IGX-NAV-DRAWER').nativeElement; - const flexBasis = getComputedStyle(drawerElem).getPropertyValue('flex-basis').trim(); - - expect(drawer.pin).toBeTruthy(); - expect(flexBasis).toEqual('240px'); - expect(drawerElem.style.order).toEqual('0'); - - drawer.width = '345px'; - drawer.position = 'right'; - fixture.detectChanges(); - - // Adjusting for transition duration - return new Promise(resolve => setTimeout(resolve, 350)); - }).then(()=> { - const drawer = fixture.componentInstance.navDrawer; - - const drawerElem = fixture.debugElement.query(By.directive(IgxNavigationDrawerComponent)).nativeElement; - const flexBasis = getComputedStyle(drawerElem).getPropertyValue('flex-basis').trim(); - - expect(flexBasis).toEqual('345px'); - expect(drawerElem.style.order).toEqual('1'); - - fixture.componentInstance.pin = false; - fixture.detectChanges(); - expect(drawer.pin).toBeFalsy(); - - // Adjusting for transition duration - return new Promise(resolve => setTimeout(resolve, 350)); - }).then(()=> { - const drawerElem = fixture.debugElement.query(By.directive(IgxNavigationDrawerComponent)).nativeElement; - const flexBasis = getComputedStyle(drawerElem).getPropertyValue('flex-basis').trim(); - - expect(flexBasis).toEqual('0px'); - expect(drawerElem.style.order).toEqual('0'); + fixture = TestBed.createComponent(TestComponentPinComponent); + const drawer = fixture.componentInstance.navDrawer; + drawer.isOpen = true; + fixture.detectChanges(); + const drawerElem = fixture.debugElement.query((x) => x.nativeNode.nodeName === 'IGX-NAV-DRAWER').nativeElement; + const flexBasis = getComputedStyle(drawerElem).getPropertyValue('flex-basis').trim(); + + expect(drawer.pin).toBeTruthy(); + expect(flexBasis).toEqual('240px'); + expect(drawerElem.style.order).toEqual('0'); + + drawer.width = '345px'; + drawer.position = 'right'; + fixture.detectChanges(); + + // Adjusting for transition duration + return new Promise(resolve => setTimeout(resolve, 350)); + }).then(() => { + const drawer = fixture.componentInstance.navDrawer; + + const drawerElem = fixture.debugElement.query(By.directive(IgxNavigationDrawerComponent)).nativeElement; + const flexBasis = getComputedStyle(drawerElem).getPropertyValue('flex-basis').trim(); + + expect(flexBasis).toEqual('345px'); + expect(drawerElem.style.order).toEqual('1'); + + fixture.componentInstance.pin = false; + fixture.detectChanges(); + expect(drawer.pin).toBeFalsy(); + + // Adjusting for transition duration + return new Promise(resolve => setTimeout(resolve, 350)); + }).then(() => { + const drawerElem = fixture.debugElement.query(By.directive(IgxNavigationDrawerComponent)).nativeElement; + const flexBasis = getComputedStyle(drawerElem).getPropertyValue('flex-basis').trim(); + + expect(flexBasis).toEqual('0px'); + expect(drawerElem.style.order).toEqual('0'); }); })); + // TODO: vitest-migration: The 'done' callback was used in an unhandled way. Please migrate manually. it('should toggle on edge swipe gesture', (done) => { let fixture: ComponentFixture; @@ -366,23 +369,23 @@ describe('Navigation Drawer', () => { return swipe(document.body, 80, 10, 100, 250, 0); }) .then(() => { - expect(fixture.componentInstance.navDrawer.isOpen) - .toEqual(false, 'should ignore swipes too far away from the edge'); - return swipe(document.body, 10, 10, 150, 250, 0); - }) + expect(fixture.componentInstance.navDrawer.isOpen, 'should ignore swipes too far away from the edge').toEqual(false); + return swipe(document.body, 10, 10, 150, 250, 0); + }) .then(() => { - expect(fixture.componentInstance.navDrawer.isOpen).toEqual(true, 'Should accept edge swipe'); - return swipe(document.body, 180, 10, 150, -180, 0); - }) + expect(fixture.componentInstance.navDrawer.isOpen, 'Should accept edge swipe').toEqual(true); + return swipe(document.body, 180, 10, 150, -180, 0); + }) .then(() => { - expect(fixture.componentInstance.navDrawer.isOpen).toEqual(false); - done(); - }) + expect(fixture.componentInstance.navDrawer.isOpen).toEqual(false); + done(); + }) .catch(() => { - done(); - }); + done(); + }); }, 10000); + // TODO: vitest-migration: The 'done' callback was used in an unhandled way. Please migrate manually. it('should toggle on edge pan gesture', (done) => { let navDrawer; let fixture: ComponentFixture; @@ -402,34 +405,33 @@ describe('Navigation Drawer', () => { // mid gesture expect(navDrawer.drawer.classList).toContain('panning'); - expect(navDrawer.drawer.style.transform) - .toMatch(/translate3d\(-2\d\dpx, 0px, 0px\)/, 'Drawer should be moving with the pan'); + expect(navDrawer.drawer.style.transform, 'Drawer should be moving with the pan').toMatch(/translate3d\(-2\d\dpx, 0px, 0px\)/); listener(); }); return pan(document.body, 10, 10, 150, 20, 0); }) .then(() => { - expect(navDrawer.isOpen).toEqual(false, 'should ignore too short pan'); - - // valid pan - return pan(document.body, 10, 10, 100, 200, 0); - }).then(() => { - expect(navDrawer.isOpen).toEqual(true, 'should open on valid pan'); - - // not enough distance, closing - return pan(document.body, 200, 10, 100, -20, 0); - }).then(() => { - expect(navDrawer.isOpen).toEqual(true, 'should remain open on too short pan'); - - // close - return pan(document.body, 250, 10, 100, -200, 0); - }).then(() => { - expect(navDrawer.isOpen).toEqual(false, 'should close on valid pan'); - done(); - }).catch(() => { - done(); - }); + expect(navDrawer.isOpen, 'should ignore too short pan').toEqual(false); + + // valid pan + return pan(document.body, 10, 10, 100, 200, 0); + }).then(() => { + expect(navDrawer.isOpen, 'should open on valid pan').toEqual(true); + + // not enough distance, closing + return pan(document.body, 200, 10, 100, -20, 0); + }).then(() => { + expect(navDrawer.isOpen, 'should remain open on too short pan').toEqual(true); + + // close + return pan(document.body, 250, 10, 100, -200, 0); + }).then(() => { + expect(navDrawer.isOpen, 'should close on valid pan').toEqual(false); + done(); + }).catch(() => { + done(); + }); }, 10000); it('should update edge zone with mini width', waitForAsync(() => { @@ -545,8 +547,8 @@ describe('Navigation Drawer', () => { await fixture.whenStable(); // defaults: - expect(fixture.componentInstance.navDrawer.pin).toBe(false, 'Should be initially unpinned'); - expect(fixture.componentInstance.pin).toBe(false, 'Parent component pin should update initially'); + expect(fixture.componentInstance.navDrawer.pin, 'Should be initially unpinned').toBe(false); + expect(fixture.componentInstance.pin, 'Parent component pin should update initially').toBe(false); // manual pin override fixture.componentInstance.pin = true; @@ -555,39 +557,39 @@ describe('Navigation Drawer', () => { // wait for debounce await wait(200); - expect(fixture.componentInstance.navDrawer.pin).toBe(false, `Shouldn't change state on resize if window width is the same`); - expect(fixture.componentInstance.pin).toBe(true, 'Parent component pin remain on resize if window width is the same'); + expect(fixture.componentInstance.navDrawer.pin, `Shouldn't change state on resize if window width is the same`).toBe(false); + expect(fixture.componentInstance.pin, 'Parent component pin remain on resize if window width is the same').toBe(true); fixture.componentInstance.pin = true; fixture.detectChanges(); - widthSpyOverride.and.returnValue(fixture.componentInstance.pinThreshold); + widthSpyOverride.mockReturnValue(fixture.componentInstance.pinThreshold); window.dispatchEvent(new Event('resize')); // wait for debounce await wait(200); - expect(fixture.componentInstance.navDrawer.pin).toBe(true, 'Should pin on window resize over threshold'); - expect(fixture.componentInstance.pin).toBe(true, 'Parent pin update on window resize over threshold'); + expect(fixture.componentInstance.navDrawer.pin, 'Should pin on window resize over threshold').toBe(true); + expect(fixture.componentInstance.pin, 'Parent pin update on window resize over threshold').toBe(true); - widthSpyOverride.and.returnValue(768); + widthSpyOverride.mockReturnValue(768); window.dispatchEvent(new Event('resize')); // wait for debounce await wait(200); - expect(fixture.componentInstance.navDrawer.pin).toBe(false, 'Should un-pin on window resize below threshold'); - expect(fixture.componentInstance.pin).toBe(false, 'Parent pin update on window resize below threshold'); + expect(fixture.componentInstance.navDrawer.pin, 'Should un-pin on window resize below threshold').toBe(false); + expect(fixture.componentInstance.pin, 'Parent pin update on window resize below threshold').toBe(false); fixture.componentInstance.pinThreshold = 500; expect(() => fixture.detectChanges()).not.toThrow(); await fixture.whenStable(); - expect(fixture.componentInstance.navDrawer.pin).toBe(true, 'Should re-pin on window resize over threshold'); - expect(fixture.componentInstance.pin).toBe(true, 'Parent pin update on re-pin'); + expect(fixture.componentInstance.navDrawer.pin, 'Should re-pin on window resize over threshold').toBe(true); + expect(fixture.componentInstance.pin, 'Parent pin update on re-pin').toBe(true); }); - it('should get correct window width', (done) => { + it('should get correct window width', async () => { const originalWidth = window.innerWidth; const drawer = TestBed.inject(IgxNavigationDrawerComponent); // re-enable `getWindowWidth` - const widthSpy = (widthSpyOverride as jasmine.Spy).and.callThrough(); + const widthSpy = (widthSpyOverride as Mock); let width = widthSpy.call(drawer); expect(width).toEqual(originalWidth); @@ -595,7 +597,7 @@ describe('Navigation Drawer', () => { width = widthSpy.call(drawer); expect(width).toEqual(screen.width); (window as any).innerWidth = originalWidth; - done(); + ; }); it('should retain classes added in markup, fix for #6508', () => { @@ -607,34 +609,35 @@ describe('Navigation Drawer', () => { }); it('should maintain size when mini pinned has `fixed` position', async () => { - const fix = TestBed.createComponent(TestFixedMiniComponent); - fix.detectChanges(); + const fix = TestBed.createComponent(TestFixedMiniComponent); + fix.detectChanges(); - fix.componentInstance.navDrawer.pin = true; - fix.detectChanges(); + fix.componentInstance.navDrawer.pin = true; + fix.detectChanges(); - // Account for transition duration - await wait(350); + // Account for transition duration + await wait(350); - const drawerEl = fix.debugElement.query(By.directive(IgxNavigationDrawerComponent)).nativeElement; - const navbarEl = fix.debugElement.query(By.directive(IgxNavbarComponent)).nativeElement; + const drawerEl = fix.debugElement.query(By.directive(IgxNavigationDrawerComponent)).nativeElement; + const navbarEl = fix.debugElement.query(By.directive(IgxNavbarComponent)).nativeElement; - let flexBasis = getComputedStyle(drawerEl).width; + let flexBasis = getComputedStyle(drawerEl).width; - // Mini variant pinned by default - expect(parseInt(flexBasis)).toBeGreaterThan(0); - expect(navbarEl.offsetLeft).toEqual(parseInt(flexBasis)); + // Mini variant pinned by default + expect(parseInt(flexBasis)).toBeGreaterThan(0); + expect(navbarEl.offsetLeft).toEqual(parseInt(flexBasis)); - fix.componentInstance.navDrawer.toggle(); - fix.detectChanges(); + fix.componentInstance.navDrawer.toggle(); + fix.detectChanges(); - // Account for transition duration - await wait(350); + // Account for transition duration + await wait(350); - flexBasis = getComputedStyle(drawerEl).getPropertyValue('flex-basis'); + flexBasis = getComputedStyle(drawerEl).getPropertyValue('flex-basis'); - expect(flexBasis).toEqual('240px');; - expect(navbarEl.offsetLeft).toEqual(parseInt(flexBasis)); + expect(flexBasis).toEqual('240px'); + ; + expect(navbarEl.offsetLeft).toEqual(parseInt(flexBasis)); }); const swipe = (element, posX, posY, duration, deltaX, deltaY) => { @@ -680,7 +683,8 @@ describe('Navigation Drawer', () => { imports: [IgxNavigationDrawerComponent] }) class TestComponent { - @ViewChild(IgxNavigationDrawerComponent, { static: true }) public navDrawer: IgxNavigationDrawerComponent; + @ViewChild(IgxNavigationDrawerComponent, { static: true }) + public navDrawer: IgxNavigationDrawerComponent; } @Component({ @@ -690,7 +694,8 @@ class TestComponent { imports: [IgxNavigationDrawerComponent] }) class TestComponentDIComponent { - @ViewChild(IgxNavigationDrawerComponent, { static: true }) public navDrawer: IgxNavigationDrawerComponent; + @ViewChild(IgxNavigationDrawerComponent, { static: true }) + public navDrawer: IgxNavigationDrawerComponent; public drawerMiniWidth: string | number; public drawerWidth: string | number; } @@ -758,4 +763,5 @@ class TestComponentMiniComponent extends TestComponentDIComponent {
` }) -class TestFixedMiniComponent extends TestComponentDIComponent { } +class TestFixedMiniComponent extends TestComponentDIComponent { +} diff --git a/projects/igniteui-angular/paginator/src/paginator/paginator.component.spec.ts b/projects/igniteui-angular/paginator/src/paginator/paginator.component.spec.ts index 5ed16eff38e..6f67344e797 100644 --- a/projects/igniteui-angular/paginator/src/paginator/paginator.component.spec.ts +++ b/projects/igniteui-angular/paginator/src/paginator/paginator.component.spec.ts @@ -7,6 +7,7 @@ import { GridFunctions } from '../../../test-utils/grid-functions.spec'; import { ControlsFunction } from '../../../test-utils/controls-functions.spec'; import { first } from 'rxjs/operators'; import { IgxButtonDirective } from '../../../directives/src/directives/button/button.directive'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxPaginator with default settings', () => { beforeEach(waitForAsync(() => { @@ -91,7 +92,7 @@ describe('IgxPaginator with default settings', () => { paginator.perPage = 100; fix.detectChanges(); - const pagingButtons = GridFunctions.getPagingButtons(fix.nativeElement); + const pagingButtons = GridFunctions.getPagingButtons(fix.nativeElement); pagingButtons.forEach(element => { expect(element.className.includes('igx-button--disabled')).toBe(true); }); @@ -110,9 +111,9 @@ describe('IgxPaginator with default settings', () => { const currPage = fix.debugElement.query(By.css('.currPage')); expect(customPaging).toBeDefined(); - expect(prevBtn.properties.disabled).toBeTrue(); + expect(prevBtn.properties.disabled).toBe(true); expect(currPage.nativeElement.innerText).toEqual('0'); - expect(nextBtn.properties.disabled).toBeFalse(); + expect(nextBtn.properties.disabled).toBe(false); }); it('should be able to operate correctly with paging api from custom template', () => { @@ -130,7 +131,7 @@ describe('IgxPaginator with default settings', () => { let currPage = fix.debugElement.query(By.css('.currPage')); expect(currPage.nativeElement.innerText).toEqual('1'); - expect(nextBtn.properties.disabled).toBeFalse(); + expect(nextBtn.properties.disabled).toBe(false); nextBtn.nativeElement.click(); fix.detectChanges(); @@ -138,7 +139,7 @@ describe('IgxPaginator with default settings', () => { currPage = fix.debugElement.query(By.css('.currPage')); expect(currPage.nativeElement.innerText).toEqual('2'); - expect(nextBtn.properties.disabled).toBeTrue(); + expect(nextBtn.properties.disabled).toBe(true); }); it('paging and pagingDone events should be emitted correctly', () => { @@ -147,8 +148,8 @@ describe('IgxPaginator with default settings', () => { const paginator = fix.componentInstance.paginator; - spyOn(paginator.paging, 'emit').and.callThrough(); - spyOn(paginator.pagingDone, 'emit').and.callThrough(); + vi.spyOn(paginator.paging, 'emit'); + vi.spyOn(paginator.pagingDone, 'emit'); const allBtns = fix.debugElement.queryAll(By.css('.igx-icon-button')); const prevBtn = allBtns[1]; @@ -161,8 +162,8 @@ describe('IgxPaginator with default settings', () => { lastBtn.nativeElement.click(); fix.detectChanges(); - expect(paginator.paging.emit).toHaveBeenCalledWith({current: 1, next: 2, cancel: false}); - expect(paginator.pagingDone.emit).toHaveBeenCalledWith({current: 2, previous: 1}); + expect(paginator.paging.emit).toHaveBeenCalledWith({ current: 1, next: 2, cancel: false }); + expect(paginator.pagingDone.emit).toHaveBeenCalledWith({ current: 2, previous: 1 }); expect(paginator.paging.emit).toHaveBeenCalledTimes(2); expect(paginator.pagingDone.emit).toHaveBeenCalledTimes(2); @@ -182,7 +183,7 @@ describe('IgxPaginator with default settings', () => { fix.detectChanges(); const paginator = fix.componentInstance.paginator; - spyOn(paginator.pageChange, 'emit').and.callThrough(); + vi.spyOn(paginator.pageChange, 'emit'); const allBtns = fix.debugElement.queryAll(By.css('.igx-icon-button ')); const nextBtn = allBtns[2]; @@ -206,7 +207,7 @@ describe('IgxPaginator with default settings', () => { fix.detectChanges(); const paginator = fix.componentInstance.paginator; - spyOn(paginator.perPageChange, 'emit').and.callThrough(); + vi.spyOn(paginator.perPageChange, 'emit'); paginator.perPage = 3; @@ -318,7 +319,8 @@ describe('IgxPaginator with custom settings', () => { imports: [IgxPaginatorComponent, IgxPaginatorContentDirective, IgxButtonDirective] }) export class DefaultPaginatorComponent { - @ViewChild(IgxPaginatorComponent, { static: true }) public paginator: IgxPaginatorComponent; + @ViewChild(IgxPaginatorComponent, { static: true }) + public paginator: IgxPaginatorComponent; public customContent = false; public setCustomPager() { @@ -335,6 +337,7 @@ export class DefaultPaginatorComponent { imports: [IgxPaginatorComponent] }) export class CustomizedPaginatorComponent { - @ViewChild(IgxPaginatorComponent, { static: true }) public paginator: IgxPaginatorComponent; + @ViewChild(IgxPaginatorComponent, { static: true }) + public paginator: IgxPaginatorComponent; } diff --git a/projects/igniteui-angular/progressbar/src/progressbar/circularbar.component.spec.ts b/projects/igniteui-angular/progressbar/src/progressbar/circularbar.component.spec.ts index 66eb86e9d72..d6df3f9fbe0 100644 --- a/projects/igniteui-angular/progressbar/src/progressbar/circularbar.component.spec.ts +++ b/projects/igniteui-angular/progressbar/src/progressbar/circularbar.component.spec.ts @@ -1,6 +1,7 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { IgxCircularProgressBarComponent } from './progressbar.component'; import { hasClass } from "../../../test-utils/helper-utils.spec"; +import { describe, it, expect, beforeEach } from 'vitest'; describe('IgxCircularProgressBarComponent', () => { let fixture: ComponentFixture; diff --git a/projects/igniteui-angular/progressbar/src/progressbar/linearbar.component.spec.ts b/projects/igniteui-angular/progressbar/src/progressbar/linearbar.component.spec.ts index 5f24e39ba7a..5646387cc2e 100644 --- a/projects/igniteui-angular/progressbar/src/progressbar/linearbar.component.spec.ts +++ b/projects/igniteui-angular/progressbar/src/progressbar/linearbar.component.spec.ts @@ -1,6 +1,7 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { IgxLinearProgressBarComponent } from './progressbar.component'; import { hasClass } from "../../../test-utils/helper-utils.spec"; +import { describe, it, expect, beforeEach } from 'vitest'; describe('IgxLinearProgressBarComponent', () => { let fixture: ComponentFixture; diff --git a/projects/igniteui-angular/progressbar/src/progressbar/progressbar.component.spec.ts b/projects/igniteui-angular/progressbar/src/progressbar/progressbar.component.spec.ts index d77c076568d..61790981f97 100644 --- a/projects/igniteui-angular/progressbar/src/progressbar/progressbar.component.spec.ts +++ b/projects/igniteui-angular/progressbar/src/progressbar/progressbar.component.spec.ts @@ -1,11 +1,13 @@ import { Component } from '@angular/core'; import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { BaseProgressDirective } from './progressbar.component'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; @Component({ template: ``, }) -class TestComponent extends BaseProgressDirective {} +class TestComponent extends BaseProgressDirective { +} describe('BaseProgressDirective', () => { let fixture: ComponentFixture; @@ -14,7 +16,7 @@ describe('BaseProgressDirective', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [TestComponent], // Declare the test component + imports: [TestComponent], // Declare the test component }).compileComponents(); fixture = TestBed.createComponent(TestComponent); @@ -173,7 +175,7 @@ describe('BaseProgressDirective', () => { })); it('should trigger progressChanged event when value changes', () => { - spyOn(component.progressChanged, 'emit'); + vi.spyOn(component.progressChanged, 'emit'); component.value = 30; expect(component.progressChanged.emit).toHaveBeenCalledWith({ @@ -189,14 +191,14 @@ describe('BaseProgressDirective', () => { }); it('should not trigger progressChanged event when value remains the same', () => { - spyOn(component.progressChanged, 'emit'); + vi.spyOn(component.progressChanged, 'emit'); component.value = 0; // Default value is already 0 expect(component.progressChanged.emit).not.toHaveBeenCalled(); }); it('should trigger progressChanged event when indeterminate is true', () => { - spyOn(component.progressChanged, 'emit'); + vi.spyOn(component.progressChanged, 'emit'); component.indeterminate = true; component.value = 30; diff --git a/projects/igniteui-angular/query-builder/src/query-builder/query-builder-functions.spec.ts b/projects/igniteui-angular/query-builder/src/query-builder/query-builder-functions.spec.ts index 4fd473be534..da9cde2a49e 100644 --- a/projects/igniteui-angular/query-builder/src/query-builder/query-builder-functions.spec.ts +++ b/projects/igniteui-angular/query-builder/src/query-builder/query-builder-functions.spec.ts @@ -7,6 +7,7 @@ import { IgxChipComponent } from 'igniteui-angular/chips'; import { ControlsFunction } from '../../../test-utils/controls-functions.spec'; import { UIInteractions } from '../../../test-utils/ui-interactions.spec'; import { QueryBuilderSelectors } from './query-builder.common'; +import { expect, vi } from 'vitest'; export const SampleEntities = [ { @@ -130,7 +131,7 @@ export class QueryBuilderFunctions { * Get the expressions container that contains all groups and expressions. */ public static getQueryBuilderExpressionsContainer(fix: ComponentFixture, level = 0) { - const searchClass = `${QueryBuilderSelectors.QUERY_BUILDER_TREE}--level-${level}` + const searchClass = `${QueryBuilderSelectors.QUERY_BUILDER_TREE}--level-${level}`; const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${searchClass}`))[0].nativeElement; const exprContainer = queryBuilderElement.querySelector(`.${QueryBuilderSelectors.QUERY_BUILDER_BODY}`); return exprContainer; @@ -200,9 +201,7 @@ export class QueryBuilderFunctions { * (NOTE: Only the items that are groups have children.) * The returned element is the one that has been gotten last. */ - public static getQueryBuilderTreeItem(fix: ComponentFixture, - path: number[], - level = 0) { + public static getQueryBuilderTreeItem(fix: ComponentFixture, path: number[], level = 0) { let node = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix, level); for (const pos of path) { const directChildren = QueryBuilderFunctions.getQueryBuilderTreeChildItems(node as HTMLElement, true); @@ -376,7 +375,7 @@ export class QueryBuilderFunctions { } public static getQueryBuilderGroupContextMenuDropDownItems(fix: ComponentFixture) { - const dropDownItems = fix.nativeElement.querySelectorAll('igx-drop-down-item') + const dropDownItems = fix.nativeElement.querySelectorAll('igx-drop-down-item'); return dropDownItems; } @@ -399,15 +398,11 @@ export class QueryBuilderFunctions { * Get tabbable elements in a container element. Result is returned as node elements ordered they way they will be tabbed */ public static getTabbableElements(inElement: HTMLElement) { - const focusableElements = - 'a:not([disabled]), button:not([disabled]), input[type=text]:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"])'; + const focusableElements = 'a:not([disabled]), button:not([disabled]), input[type=text]:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"])'; - return Array.prototype.filter.call( - inElement.querySelectorAll(focusableElements), - element => { - return (element.offsetWidth > 0 || element.offsetHeight > 0); - } - ); + return Array.prototype.filter.call(inElement.querySelectorAll(focusableElements), element => { + return (element.offsetWidth > 0 || element.offsetHeight > 0); + }); } public static clickQueryBuilderInitialAddConditionBtn(fix: ComponentFixture, level = 0) { @@ -443,7 +438,7 @@ export class QueryBuilderFunctions { * Click the operator select for the expression that is currently in edit mode. */ public static clickQueryBuilderOperatorSelect(fix: ComponentFixture, level = 0) { - const operatorInputGroup = QueryBuilderFunctions.getQueryBuilderOperatorSelect(fix, level).querySelector('igx-input-group') as HTMLElement + const operatorInputGroup = QueryBuilderFunctions.getQueryBuilderOperatorSelect(fix, level).querySelector('igx-input-group') as HTMLElement; operatorInputGroup.click(); } @@ -506,7 +501,7 @@ export class QueryBuilderFunctions { public static clickQueryBuilderTreeAddOption(fix: ComponentFixture, index: number) { const outlet = Array.from(fix.debugElement.nativeElement.querySelectorAll(`.igx-drop-down__list-scroll`)).filter(item => (item as HTMLElement).checkVisibility())[0]; const item = Array.from((outlet as HTMLElement).querySelectorAll('.igx-drop-down__item'))[index] as HTMLElement; - UIInteractions.simulateClickAndSelectEvent(item) + UIInteractions.simulateClickAndSelectEvent(item); tick(100); fix.detectChanges(); } @@ -526,60 +521,44 @@ export class QueryBuilderFunctions { * (NOTE: The 'operator' argument must be a string with a value that is either 'and' or 'or'.) */ public static verifyOperatorLine(operatorLine: HTMLElement, operator: string) { - expect(operator === 'and' || operator === 'or').toBe(true, 'operator must be \'and\' or \'or\''); + expect(operator === 'and' || operator === 'or', 'operator must be \'and\' or \'or\'').toBe(true); if (operator === 'and') { - expect(operatorLine.classList.contains(QueryBuilderSelectors.FILTER_TREE_LINE_AND)).toBe(true, 'incorrect operator line'); - expect(operatorLine.classList.contains(QueryBuilderSelectors.FILTER_TREE_LINE_OR)).toBe(false, 'incorrect operator line'); + expect(operatorLine.classList.contains(QueryBuilderSelectors.FILTER_TREE_LINE_AND), 'incorrect operator line').toBe(true); + expect(operatorLine.classList.contains(QueryBuilderSelectors.FILTER_TREE_LINE_OR), 'incorrect operator line').toBe(false); } else { - expect(operatorLine.classList.contains(QueryBuilderSelectors.FILTER_TREE_LINE_AND)).toBe(false, 'incorrect operator line'); - expect(operatorLine.classList.contains(QueryBuilderSelectors.FILTER_TREE_LINE_OR)).toBe(true, 'incorrect operator line'); + expect(operatorLine.classList.contains(QueryBuilderSelectors.FILTER_TREE_LINE_AND), 'incorrect operator line').toBe(false); + expect(operatorLine.classList.contains(QueryBuilderSelectors.FILTER_TREE_LINE_OR), 'incorrect operator line').toBe(true); } } - public static verifyEditModeQueryExpressionInputStates(fix, - entitySelectEnabled: boolean, - fieldComboEnabled: boolean, - columnSelectEnabled?: boolean, - operatorSelectEnabled?: boolean, - valueInputEnabled?: boolean, - commitButtonEnabled?: boolean, - level = 0) { + public static verifyEditModeQueryExpressionInputStates(fix, entitySelectEnabled: boolean, fieldComboEnabled: boolean, columnSelectEnabled?: boolean, operatorSelectEnabled?: boolean, valueInputEnabled?: boolean, commitButtonEnabled?: boolean, level = 0) { // Verify the entity select state. const entityInputGroup = QueryBuilderFunctions.getQueryBuilderEntitySelect(fix, level).querySelector('igx-input-group'); - expect(!entityInputGroup.classList.contains('igx-input-group--disabled')).toBe(entitySelectEnabled, - 'incorrect entity select state'); + expect(!entityInputGroup.classList.contains('igx-input-group--disabled'), 'incorrect entity select state').toBe(entitySelectEnabled); // Verify the fields combo state. const fieldInputGroup = QueryBuilderFunctions.getQueryBuilderFieldsCombo(fix, level).querySelector('igx-input-group'); - expect(!fieldInputGroup.classList.contains('igx-input-group--disabled')).toBe(fieldComboEnabled, - 'incorrect fields combo state'); + expect(!fieldInputGroup.classList.contains('igx-input-group--disabled'), 'incorrect fields combo state').toBe(fieldComboEnabled); if (columnSelectEnabled || operatorSelectEnabled || valueInputEnabled || commitButtonEnabled) { QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, columnSelectEnabled, operatorSelectEnabled, valueInputEnabled, commitButtonEnabled, level); } - }; + } + ; - public static verifyEditModeExpressionInputStates(fix, - columnSelectEnabled: boolean, - operatorSelectEnabled: boolean, - valueInputEnabled: boolean, - commitButtonEnabled: boolean, - level = 0) { + public static verifyEditModeExpressionInputStates(fix, columnSelectEnabled: boolean, operatorSelectEnabled: boolean, valueInputEnabled: boolean, commitButtonEnabled: boolean, level = 0) { // Verify the column select state. const columnInputGroup = QueryBuilderFunctions.getQueryBuilderColumnSelect(fix, level).querySelector('igx-input-group'); - expect(!columnInputGroup.classList.contains('igx-input-group--disabled')).toBe(columnSelectEnabled, - 'incorrect column select state'); + expect(!columnInputGroup.classList.contains('igx-input-group--disabled'), 'incorrect column select state').toBe(columnSelectEnabled); // Verify the operator select state. const operatorInputGroup = QueryBuilderFunctions.getQueryBuilderOperatorSelect(fix, level).querySelector('igx-input-group'); - expect(!operatorInputGroup.classList.contains('igx-input-group--disabled')).toBe(operatorSelectEnabled, - 'incorrect operator select state'); + expect(!operatorInputGroup.classList.contains('igx-input-group--disabled'), 'incorrect operator select state').toBe(operatorSelectEnabled); // Verify the value input state. const editModeContainer = QueryBuilderFunctions.getQueryBuilderEditModeContainer(fix, false, level); const valueInputGroup = Array.from(editModeContainer.querySelectorAll('igx-input-group'))[2]; - expect(!valueInputGroup.classList.contains('igx-input-group--disabled')).toBe(valueInputEnabled, - 'incorrect value input state'); + expect(!valueInputGroup.classList.contains('igx-input-group--disabled'), 'incorrect value input state').toBe(valueInputEnabled); // Verify commit expression button state const commitButton = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix, level); @@ -588,15 +567,10 @@ export class QueryBuilderFunctions { // Verify close expression button is enabled. const closeButton = QueryBuilderFunctions.getQueryBuilderExpressionCloseButton(fix, level); ControlsFunction.verifyButtonIsDisabled(closeButton, false); - }; + } + ; - public static verifyQueryEditModeExpressionInputValues(fix, - entityText: string, - fieldsText: string, - columnText?: string, - operatorText?: string, - valueText?: string, - level = 0) { + public static verifyQueryEditModeExpressionInputValues(fix, entityText: string, fieldsText: string, columnText?: string, operatorText?: string, valueText?: string, level = 0) { const entityInput = QueryBuilderFunctions.getQueryBuilderEntitySelect(fix, level).querySelector('input'); const fieldInput = QueryBuilderFunctions.getQueryBuilderFieldsCombo(fix, level).querySelector('input'); expect(entityInput.value).toBe(entityText); @@ -605,20 +579,18 @@ export class QueryBuilderFunctions { if (columnText || operatorText || valueText) { QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, columnText, operatorText, valueText, level); } - }; + } + ; - public static verifyEditModeExpressionInputValues(fix, - columnText: string, - operatorText: string, - valueText: string, - level = 0) { + public static verifyEditModeExpressionInputValues(fix, columnText: string, operatorText: string, valueText: string, level = 0) { const columnInput = QueryBuilderFunctions.getQueryBuilderColumnSelect(fix, level).querySelector('input'); const operatorInput = QueryBuilderFunctions.getQueryBuilderOperatorSelect(fix, level).querySelector('input'); const valueInput = QueryBuilderFunctions.getQueryBuilderValueInput(fix, false, level).querySelector('input') as HTMLInputElement; expect(columnInput.value).toBe(columnText); expect(operatorInput.value).toBe(operatorText); expect(valueInput.value).toBe(valueText); - }; + } + ; public static verifyQueryBuilderTabbableElements = (fixture: ComponentFixture) => { const tabElements = QueryBuilderFunctions.getTabbableElements(fixture.nativeElement); @@ -626,24 +598,54 @@ export class QueryBuilderFunctions { let i = 0; tabElements.forEach((element: HTMLElement) => { switch (i) { - case 0: expect(element).toHaveClass('igx-input-group__input'); break; - case 1: expect(element).toHaveClass('igx-input-group__input'); break; - case 2: expect(element).toHaveClass('igx-combo__toggle-button'); break; - case 3: expect(element).toHaveClass('igx-button'); - expect(element.innerText).toContain('and'); break; - case 4: expect(element).toHaveClass('igx-chip'); break; - case 5: expect(element).toHaveClass('igx-icon'); break; - case 6: expect(element).toHaveClass('igx-chip__remove'); break; - case 7: expect(element).toHaveClass('igx-chip'); break; - case 8: expect(element).toHaveClass('igx-icon'); break; - case 9: expect(element).toHaveClass('igx-chip__remove'); break; - case 10: expect(element).toHaveClass('igx-chip'); break; - case 11: expect(element).toHaveClass('igx-icon'); break; - case 12: expect(element).toHaveClass('igx-chip__remove'); break; - case 13: expect(element).toHaveClass('igx-button'); - expect(element.innerText).toContain('Condition'); break; - case 14: expect(element).toHaveClass('igx-button'); - expect(element.innerText).toContain('Group'); break; + case 0: + expect(element.classList.contains('igx-input-group__input')).toBe(true); + break; + case 1: + expect(element.classList.contains('igx-input-group__input')).toBe(true); + break; + case 2: + expect(element.classList.contains('igx-combo__toggle-button')).toBe(true); + break; + case 3: + expect(element.classList.contains('igx-button')).toBe(true); + expect(element.innerText).toContain('and'); + break; + case 4: + expect(element.classList.contains('igx-chip')).toBe(true); + break; + case 5: + expect(element.classList.contains('igx-icon')).toBe(true); + break; + case 6: + expect(element.classList.contains('igx-chip__remove')).toBe(true); + break; + case 7: + expect(element.classList.contains('igx-chip')).toBe(true); + break; + case 8: + expect(element.classList.contains('igx-icon')).toBe(true); + break; + case 9: + expect(element.classList.contains('igx-chip__remove')).toBe(true); + break; + case 10: + expect(element.classList.contains('igx-chip')).toBe(true); + break; + case 11: + expect(element.classList.contains('igx-icon')).toBe(true); + break; + case 12: + expect(element.classList.contains('igx-chip__remove')).toBe(true); + break; + case 13: + expect(element.classList.contains('igx-button')).toBe(true); + expect(element.innerText).toContain('Condition'); + break; + case 14: + expect(element.classList.contains('igx-button')).toBe(true); + expect(element.innerText).toContain('Group'); + break; } i++; }); @@ -655,7 +657,8 @@ export class QueryBuilderFunctions { let i = 0; tabElements.forEach((element: HTMLElement) => { switch (i) { - case 0: expect(element.firstChild).toHaveClass('igx-icon'); + case 0: + expect(element.firstChild.classList.contains('igx-icon')).toBe(true); expect(element.firstChild.textContent).toContain('add'); break; } @@ -672,7 +675,7 @@ export class QueryBuilderFunctions { if (valueText) { expect((chipElement.querySelector('.igx-chip__content') as HTMLElement).innerText).toEqual(valueText); } - } + }; public static verifyTabbableConditionEditLineElements = (editLine: DebugElement) => { const tabElements = QueryBuilderFunctions.getTabbableElements(editLine.nativeElement); @@ -680,10 +683,18 @@ export class QueryBuilderFunctions { let i = 0; tabElements.forEach((element: HTMLElement) => { switch (i) { - case 0: expect(element).toHaveClass('igx-input-group__input'); break; - case 1: expect(element).toHaveClass('igx-input-group__input'); break; - case 2: expect(element).toHaveClass('igx-icon-button'); break; - case 3: expect(element).toHaveClass('igx-icon-button'); break; + case 0: + expect(element.classList.contains('igx-input-group__input')).toBe(true); + break; + case 1: + expect(element.classList.contains('igx-input-group__input')).toBe(true); + break; + case 2: + expect(element.classList.contains('igx-icon-button')).toBe(true); + break; + case 3: + expect(element.classList.contains('igx-icon-button')).toBe(true); + break; } i++; }); @@ -695,19 +706,39 @@ export class QueryBuilderFunctions { let i = 0; tabElements.forEach((element: HTMLElement) => { switch (i) { - case 0: expect(element).toHaveClass('igx-input-group__input'); break; - case 1: expect(element).toHaveClass('igx-input-group__input'); break; - case 2: expect(element).toHaveClass('igx-button'); break; - case 3: expect(element).toHaveClass('igx-chip'); break; - case 4: expect(element).toHaveClass('igx-icon'); break; - case 5: expect(element).toHaveClass('igx-chip__remove'); break; - case 6: expect(element).toHaveClass('igx-chip'); break; - case 7: expect(element).toHaveClass('igx-icon'); break; - case 8: expect(element).toHaveClass('igx-chip__remove'); break; - case 9: expect(element).toHaveClass('igx-button'); + case 0: + expect(element.classList.contains('igx-input-group__input')).toBe(true); + break; + case 1: + expect(element.classList.contains('igx-input-group__input')).toBe(true); + break; + case 2: + expect(element.classList.contains('igx-button')).toBe(true); + break; + case 3: + expect(element.classList.contains('igx-chip')).toBe(true); + break; + case 4: + expect(element.classList.contains('igx-icon')).toBe(true); + break; + case 5: + expect(element.classList.contains('igx-chip__remove')).toBe(true); + break; + case 6: + expect(element.classList.contains('igx-chip')).toBe(true); + break; + case 7: + expect(element.classList.contains('igx-icon')).toBe(true); + break; + case 8: + expect(element.classList.contains('igx-chip__remove')).toBe(true); + break; + case 9: + expect(element.classList.contains('igx-button')).toBe(true); expect(element.innerText).toContain('Condition'); break; - case 10: expect(element).toHaveClass('igx-button'); + case 10: + expect(element.classList.contains('igx-button')).toBe(true); expect(element.innerText).toContain('Group'); break; } @@ -721,32 +752,39 @@ export class QueryBuilderFunctions { const columnSpan = chipSpans[0]; const operatorSpan = chipSpans[1]; const valueSpan = chipSpans[2]; - expect(columnSpan.textContent.toLowerCase().trim()).toBe(columnText.toLowerCase(), 'incorrect chip column'); - expect(operatorSpan.textContent.toLowerCase().trim()).toBe(operatorText.toLowerCase(), 'incorrect chip operator'); + expect(columnSpan.textContent.toLowerCase().trim(), 'incorrect chip column').toBe(columnText.toLowerCase()); + expect(operatorSpan.textContent.toLowerCase().trim(), 'incorrect chip operator').toBe(operatorText.toLowerCase()); if (valueSpan != undefined && valueText != undefined) { - expect(valueSpan.textContent.toLowerCase().trim().replaceAll(/\s/g, '')).toBe(valueText.toLowerCase().replaceAll(/\s/g, ''), 'incorrect chip filter value'); + expect(valueSpan.textContent.toLowerCase().trim().replaceAll(/\s/g, ''), 'incorrect chip filter value').toBe(valueText.toLowerCase().replaceAll(/\s/g, '')); } - }; + } + ; public static verifyGroupLineCount(fix: ComponentFixture, andLineCount: number = null, orLineCount: number = null) { const andLines = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.FILTER_TREE_LINE_AND}`)); const orLines = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.FILTER_TREE_LINE_OR}`)); - if (andLineCount) expect(andLines.length).toBe(andLineCount, "AND groups not the right count"); - if (orLineCount) expect(orLines.length).toBe(orLineCount, "OR groups not the right count"); - }; + if (andLineCount) + expect(andLines.length, "AND groups not the right count").toBe(andLineCount); + if (orLineCount) + expect(orLines.length, "OR groups not the right count").toBe(orLineCount); + } + ; public static verifyRootAndSubGroupExpressionsCount(fix: ComponentFixture, rootDirect: number, rootTotal: number = null, subGroupPath: number[] = null, subGroupDirect: number = null, subGroupTotal: number = null) { const rootGroup = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement; expect(rootGroup).not.toBeNull('There is no root group.'); - expect(QueryBuilderFunctions.getQueryBuilderTreeChildItems(rootGroup, true).length).toBe(rootDirect, 'Root direct condition count not correct'); - expect(QueryBuilderFunctions.getQueryBuilderTreeChildItems(rootGroup, false).length).toBe(rootTotal, 'Root direct + child condition count not correct'); + expect(QueryBuilderFunctions.getQueryBuilderTreeChildItems(rootGroup, true).length, 'Root direct condition count not correct').toBe(rootDirect); + expect(QueryBuilderFunctions.getQueryBuilderTreeChildItems(rootGroup, false).length, 'Root direct + child condition count not correct').toBe(rootTotal); if (subGroupPath) { const subGroup = QueryBuilderFunctions.getQueryBuilderTreeItem(fix, subGroupPath) as HTMLElement; - if (subGroupDirect) expect(QueryBuilderFunctions.getQueryBuilderTreeChildItems(subGroup, true).length).toBe(subGroupDirect, 'Child direct condition count not correct'); - if (subGroupTotal) expect(QueryBuilderFunctions.getQueryBuilderTreeChildItems(subGroup, false).length).toBe(subGroupTotal, 'Child direct + child condition count not correct'); + if (subGroupDirect) + expect(QueryBuilderFunctions.getQueryBuilderTreeChildItems(subGroup, true).length, 'Child direct condition count not correct').toBe(subGroupDirect); + if (subGroupTotal) + expect(QueryBuilderFunctions.getQueryBuilderTreeChildItems(subGroup, false).length, 'Child direct + child condition count not correct').toBe(subGroupTotal); } - }; + } + ; public static selectEntityInEditModeExpression(fix: ComponentFixture, dropdownItemIndex: number, level = 0) { QueryBuilderFunctions.clickQueryBuilderEntitySelect(fix, level); @@ -754,7 +792,7 @@ export class QueryBuilderFunctions { const outlet = Array.from(fix.debugElement.nativeElement.querySelectorAll(`.igx-drop-down__list-scroll`)).filter(item => (item as HTMLElement).checkVisibility())[0]; const item = Array.from((outlet as HTMLElement).querySelectorAll('.igx-drop-down__item'))[dropdownItemIndex] as HTMLElement; - UIInteractions.simulateClickAndSelectEvent(item) + UIInteractions.simulateClickAndSelectEvent(item); tick(); fix.detectChanges(); } @@ -766,7 +804,7 @@ export class QueryBuilderFunctions { const outlet = Array.from(fix.debugElement.nativeElement.querySelectorAll(`.igx-drop-down__list-scroll`)).filter(item => (item as HTMLElement).checkVisibility())[0]; deselectItemIndexes.forEach(index => { const item = Array.from((outlet as HTMLElement).querySelectorAll('.igx-drop-down__item'))[index] as HTMLElement; - UIInteractions.simulateClickAndSelectEvent(item) + UIInteractions.simulateClickAndSelectEvent(item); tick(); fix.detectChanges(); }); @@ -782,7 +820,7 @@ export class QueryBuilderFunctions { QueryBuilderFunctions.clickQueryBuilderColumnSelect(fix, level); fix.detectChanges(); - const searchClass = `${QueryBuilderSelectors.QUERY_BUILDER_TREE}--level-${level}` + const searchClass = `${QueryBuilderSelectors.QUERY_BUILDER_TREE}--level-${level}`; const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${searchClass}`))[0].nativeElement; QueryBuilderFunctions.clickQueryBuilderSelectDropdownItem(queryBuilderElement, dropdownItemIndex); tick(); @@ -792,7 +830,7 @@ export class QueryBuilderFunctions { public static selectOperatorInEditModeExpression(fix, dropdownItemIndex: number, level = 0) { QueryBuilderFunctions.clickQueryBuilderOperatorSelect(fix, level); fix.detectChanges(); - const searchClass = `${QueryBuilderSelectors.QUERY_BUILDER_TREE}--level-${level}` + const searchClass = `${QueryBuilderSelectors.QUERY_BUILDER_TREE}--level-${level}`; const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${searchClass}`))[0].nativeElement; QueryBuilderFunctions.clickQueryBuilderSelectDropdownItem(queryBuilderElement, dropdownItemIndex); tick(); @@ -872,7 +910,8 @@ export class QueryBuilderFunctions { let text: string = ''; Array.from(chip.querySelectorAll('span')).forEach(element => { - if (element?.textContent) text += element.textContent; + if (element?.textContent) + text += element.textContent; }); return text.trim(); @@ -899,7 +938,7 @@ export class QueryBuilderFunctions { return { X: (bounds.left + bounds.right) / 2, Y: (bounds.top + bounds.bottom) / 2 - } + }; } public static dragMove(dragDirective, X: number, Y: number, pointerUp?: boolean) { @@ -915,7 +954,12 @@ export class QueryBuilderFunctions { } } - public static getDropGhostAndItsSiblings(fixture: ComponentFixture): [Element, string, string, string[]] { + public static getDropGhostAndItsSiblings(fixture: ComponentFixture): [ + Element, + string, + string, + string[] + ] { const dropGhost = this.getDropGhost(fixture); const newChipContents = QueryBuilderFunctions.GetChipsContentAsArray(fixture); let prevElement: string, nextElement: string; @@ -951,10 +995,10 @@ export class QueryBuilderFunctions { QueryBuilderFunctions.dragMove(dragDir, draggedChipCenter.X + 10, draggedChipCenter.Y + 10); fix.detectChanges(); - spyOn(dragDir.ghostElement, 'dispatchEvent').and.callThrough(); + vi.spyOn(dragDir.ghostElement, 'dispatchEvent'); const target = moveDown ? 350 : 0; - const shift = moveDown ? 1 : -1 + const shift = moveDown ? 1 : -1; //Drag ghost up or down and check if drop ghost is rendered in the expected positions for (let i = moveDown ? 0 : 350; moveDown ? i <= target : i >= target; i += shift) { Y += moveDown ? 1 : -1; @@ -966,42 +1010,51 @@ export class QueryBuilderFunctions { const [dropGhost, prevElement, nextElement] = QueryBuilderFunctions.getDropGhostAndItsSiblings(fix); if (i < 40 && !ghostPositionVisits[0]) { - if (i <= 42) tick(50); - if (!dropGhost) ghostPositionVisits[0] = true; + if (i <= 42) + tick(50); + if (!dropGhost) + ghostPositionVisits[0] = true; } if (i > 35 && i < 122 && !ghostPositionVisits[1]) { - if (dropGhost && !prevElement && nextElement == 'OrderName Equals foo') ghostPositionVisits[1] = true; + if (dropGhost && !prevElement && nextElement == 'OrderName Equals foo') + ghostPositionVisits[1] = true; } if (i > 120 && i < 165 && !ghostPositionVisits[2]) { - if (dropGhost && prevElement == 'OrderName Equals foo' && nextElement === 'or OrderName Ends With a OrderDate Today') ghostPositionVisits[2] = true; + if (dropGhost && prevElement == 'OrderName Equals foo' && nextElement === 'or OrderName Ends With a OrderDate Today') + ghostPositionVisits[2] = true; } if (i > 166 && i < 201 && !ghostPositionVisits[3]) { - if (dropGhost && !prevElement && nextElement == 'OrderName Ends With a') ghostPositionVisits[3] = true; + if (dropGhost && !prevElement && nextElement == 'OrderName Ends With a') + ghostPositionVisits[3] = true; } if (i > 202 && i < 241 && !ghostPositionVisits[4]) { - if (dropGhost && prevElement == 'OrderName Ends With a' && nextElement === 'OrderDate Today') ghostPositionVisits[4] = true; + if (dropGhost && prevElement == 'OrderName Ends With a' && nextElement === 'OrderDate Today') + ghostPositionVisits[4] = true; } if (i > 240 && i < 273 && !ghostPositionVisits[5]) { - if (dropGhost && prevElement == 'OrderDate Today' && !nextElement) ghostPositionVisits[5] = true; + if (dropGhost && prevElement == 'OrderDate Today' && !nextElement) + ghostPositionVisits[5] = true; } if (i > 256 && i < 316 && !ghostPositionVisits[6]) { - if (X > 400 || (dropGhost && prevElement == 'or OrderName Ends With a OrderDate Today' && !nextElement)) ghostPositionVisits[6] = true; + if (X > 400 || (dropGhost && prevElement == 'or OrderName Ends With a OrderDate Today' && !nextElement)) + ghostPositionVisits[6] = true; } if (i > 320 && !ghostPositionVisits[7]) { - if (i >= 340) tick(50); - if (!dropGhost) ghostPositionVisits[7] = true; + if (i >= 340) + tick(50); + if (!dropGhost) + ghostPositionVisits[7] = true; } } //When dragged to the end, check results - expect(ghostPositionVisits).not.toContain(false, - `Ghost was not rendered on position(s) ${ghostPositionVisits.reduce((arr, e, ix) => ((e == false) && arr.push(ix), arr), []).toString()}`); + expect(ghostPositionVisits).not.toContain(false, `Ghost was not rendered on position(s) ${ghostPositionVisits.reduce((arr, e, ix) => ((e == false) && arr.push(ix), arr), []).toString()}`); } } diff --git a/projects/igniteui-angular/query-builder/src/query-builder/query-builder.component.spec.ts b/projects/igniteui-angular/query-builder/src/query-builder/query-builder.component.spec.ts index ff9428c85c8..f04b4291ebb 100644 --- a/projects/igniteui-angular/query-builder/src/query-builder/query-builder.component.spec.ts +++ b/projects/igniteui-angular/query-builder/src/query-builder/query-builder.component.spec.ts @@ -4,7 +4,9 @@ import { IgxChipComponent } from 'igniteui-angular/chips'; import { IgxComboComponent } from 'igniteui-angular/combo'; import { IgxIconComponent } from 'igniteui-angular/icon'; import { IgxInputGroupComponent } from 'igniteui-angular/input-group'; -import { IgxSelectComponent } from 'igniteui-angular/select';; +import { IgxSelectComponent } from 'igniteui-angular/select'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; +; import { Component, OnInit, ViewChild } from '@angular/core'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { By } from '@angular/platform-browser'; @@ -19,400 +21,400 @@ import { IgxQueryBuilderHeaderComponent } from './query-builder-header.component import { IgxQueryBuilderSearchValueTemplateDirective } from './query-builder.directives'; describe('IgxQueryBuilder', () => { - let fix: ComponentFixture; - let queryBuilder: IgxQueryBuilderComponent; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule, - IgxQueryBuilderComponent, - IgxQueryBuilderSampleTestComponent, - IgxQueryBuilderCustomTemplateSampleTestComponent, - IgxComboComponent - ] - }).compileComponents(); - })); - - beforeEach(fakeAsync(() => { - fix = TestBed.createComponent(IgxQueryBuilderSampleTestComponent); - fix.detectChanges(); - queryBuilder = fix.componentInstance.queryBuilder; - })); - - describe('Basic', () => { - it('Should render empty Query Builder properly.', fakeAsync(() => { - tick(100); - fix.detectChanges(); - const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER}`))[0].nativeElement; - expect(queryBuilderElement).toBeDefined(); - expect(queryBuilderElement.children.length).toEqual(1); - - const queryTreeElement = queryBuilderElement.children[0]; - expect(queryTreeElement).toHaveClass(QueryBuilderSelectors.QUERY_BUILDER_TREE); - - expect(queryBuilder.expressionTree).toBeUndefined(); - - expect(queryTreeElement.children.length).toEqual(3); - const bodyElement = queryTreeElement.children[0]; - expect(bodyElement).toHaveClass(QueryBuilderSelectors.QUERY_BUILDER_BODY); - expect(bodyElement.children.length).toEqual(1); - - QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, false); - QueryBuilderFunctions.verifyQueryEditModeExpressionInputValues(fix, '', ''); - - // Select 'Products' entity - QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 0); - tick(100); - fix.detectChanges(); - - QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, true); - QueryBuilderFunctions.verifyQueryEditModeExpressionInputValues(fix, 'Products', 'Id, ProductName, OrderId, Released'); - })); - - it('Should render Query Builder with initially set expression tree properly.', fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - - const queryTreeElement: HTMLElement = fix.debugElement.queryAll(By.css(QueryBuilderSelectors.QUERY_BUILDER_TREE))[0].nativeElement; - const bodyElement = queryTreeElement.children[0]; - expect(bodyElement).toHaveClass(QueryBuilderSelectors.QUERY_BUILDER_BODY); - expect(bodyElement.children.length).toEqual(2); - - // Verify the operator line of the root group is an 'And' line. - QueryBuilderFunctions.verifyOperatorLine(QueryBuilderFunctions.getQueryBuilderTreeRootGroupOperatorLine(fix) as HTMLElement, 'and'); - // all inputs should be displayed correctly - const selectFromContainer = bodyElement.children[0]; - expect(selectFromContainer).toHaveClass('igx-filter-tree__inputs'); - expect(selectFromContainer.children[0].children[1].tagName).toEqual('IGX-SELECT'); - expect(selectFromContainer.children[1].children[1].tagName).toEqual('IGX-COMBO'); - const queryTreeExpressionContainer = bodyElement.children[1].children[1]; - expect(queryTreeExpressionContainer).toHaveClass('igx-filter-tree'); - expect(queryTreeExpressionContainer.children[1]).toHaveClass('igx-filter-tree__expressions'); - - const selectEntity = QueryBuilderFunctions.getQueryBuilderEntitySelect(fix, 0); - expect(selectEntity.children[0].classList.contains('igx-input-group--disabled')).toBeFalse(); - - const fieldsCombo = QueryBuilderFunctions.getQueryBuilderFieldsCombo(fix, 0); - expect(fieldsCombo.children[0].classList.contains('igx-input-group--disabled')).toBeFalse(); - - const expressionItems = queryTreeExpressionContainer.children[1].children[1].querySelectorAll(':scope > .igx-filter-tree__expression-item'); - expect(expressionItems.length).toEqual(queryBuilder.expressionTree.filteringOperands.length); - // entity select should have proper value - expect(queryBuilder.queryTree.selectedEntity.name).toEqual(queryBuilder.expressionTree.entity); - // fields input should have proper value - expect(queryBuilder.queryTree.selectedReturnFields.length).toEqual(4); - // nested queries should be collapsed - const nestedQueryTrees = queryTreeExpressionContainer.querySelectorAll(QueryBuilderSelectors.QUERY_BUILDER_TREE); - for (let i = 0; i < nestedQueryTrees.length; i++) { - expect(nestedQueryTrees[i].checkVisibility()).toBeFalse(); - } - // adding buttons should be enabled - const buttons = QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtons(fix, 0); - for (const button of buttons) { - ControlsFunction.verifyButtonIsDisabled(button as HTMLElement, false); - } - })); - - it('Should render combo for main entity return fields and select for nested entity return field.', fakeAsync(() => { - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); - - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); // Select 'OrderId' column. - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 10); // Select 'In' operator. - - const mainEntityContainer = QueryBuilderFunctions.getQueryBuilderEditModeContainer(fix, true, 0); - const nestedEntityContainer = QueryBuilderFunctions.getQueryBuilderEditModeContainer(fix, true, 1); - - expect(mainEntityContainer.children[1].children[1].tagName).toBe('IGX-COMBO'); - expect(nestedEntityContainer.children[1].children[1].tagName).toBe('IGX-SELECT'); - })); - - it('Should return proper fields collection without additional props.', fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - - queryBuilder.entities[0].fields.forEach(field => { - expect(field.filters).toBeUndefined(); - expect(field.pipeArgs).toBeUndefined(); - }); + let fix: ComponentFixture; + let queryBuilder: IgxQueryBuilderComponent; + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [ + NoopAnimationsModule, + IgxQueryBuilderComponent, + IgxQueryBuilderSampleTestComponent, + IgxQueryBuilderCustomTemplateSampleTestComponent, + IgxComboComponent + ] + }).compileComponents(); })); - it('Should not throw error when entities are empty and expressionTree is set.', fakeAsync(() => { - expect(() => { - fix = TestBed.createComponent(IgxQueryBuilderInvalidSampleTestComponent); + beforeEach(fakeAsync(() => { + fix = TestBed.createComponent(IgxQueryBuilderSampleTestComponent); fix.detectChanges(); - }).not.toThrow(); - })); - }); - - describe('Interactions', () => { - it('Should correctly initialize a newly added \'And\' group.', fakeAsync(() => { - QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1); // Select 'Orders' entity - tick(100); - fix.detectChanges(); - - // Click the initial 'Add Condition' button. - QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); - tick(100); - fix.detectChanges(); - - // Verify there is a new root group, which is empty. - QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 0, 0); - - // Verify the operator line of the root group is an 'And' line. - QueryBuilderFunctions.verifyOperatorLine(QueryBuilderFunctions.getQueryBuilderTreeRootGroupOperatorLine(fix) as HTMLElement, 'and'); - - // Verify the enabled/disabled state of each input of the expression in edit mode. - QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, true, true, false, false, false); - - // Verify the edit inputs are empty. - QueryBuilderFunctions.verifyQueryEditModeExpressionInputValues(fix, 'Orders', 'OrderId, OrderName, OrderDate, Delivered', '', '', ''); - - // Verify adding buttons are not displayed - expect(QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtonsContainer(fix, 0)).toBe(undefined); - })); - - it(`Should discard newly added group when clicking on the 'cancel' button of its initial condition.`, fakeAsync(() => { - spyOn(queryBuilder.expressionTreeChange, 'emit').and.callThrough(); - expect(queryBuilder.expressionTreeChange.emit).toHaveBeenCalledTimes(0); - - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); - - expect(queryBuilder.expressionTreeChange.emit).toHaveBeenCalledTimes(1); - - // Verify there is a new root group, which is empty. - const group = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix); - expect(group).not.toBeNull('There is no root group.'); - - // Click on the 'cancel' button - const closeButton = QueryBuilderFunctions.getQueryBuilderExpressionCloseButton(fix); - UIInteractions.simulateClickEvent(closeButton); - tick(100); - fix.detectChanges(); - - // Verify there is a new root group, which is empty. - QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 0, 0); - })); - - it('Should add a new condition to existing group by using add buttons.', fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - - spyOn(queryBuilder.expressionTreeChange, 'emit').and.callThrough(); - - // Verify group's children count before adding a new child. - let group = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement; - QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 3, 6); - - - // Add new 'expression'. - const buttonsContainer = Array.from(group.querySelectorAll('.igx-filter-tree__buttons'))[1]; - const buttons = Array.from(buttonsContainer.querySelectorAll('button')); - (buttons[0] as HTMLElement).click(); - tick(); - fix.detectChanges(); - - // Newly added condition should be empty - QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, false, false, false); - QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, '', '', ''); - - // Populate edit inputs. - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'OrderName' column. - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. - const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, 'a'); - tick(100); - fix.detectChanges(); - // Commit the populated expression. - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); - fix.detectChanges(); - - group = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement; - QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 4, 7); - expect(queryBuilder.expressionTreeChange.emit).toHaveBeenCalled(); - })); - - it(`Should add a new 'Or' group to existing group by using add buttons.`, fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - - spyOn(queryBuilder.expressionTreeChange, 'emit').and.callThrough(); - - // Verify group's children count before adding a new child. - let group = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement; - QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 3, 6); - - // Add new 'Or' group. - const buttonsContainer = Array.from(group.querySelectorAll('.igx-filter-tree__buttons'))[1]; - const buttons = Array.from(buttonsContainer.querySelectorAll('button')); - (buttons[1] as HTMLElement).click(); - tick(); - fix.detectChanges(); - - // Newly added condition should be empty - QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, false, false, false); - QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, '', '', ''); - - // Verify adding buttons are not displayed - expect(QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtonsContainer(fix, 0)).toBe(undefined); - - // Populate edit inputs. - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'OrderName' column. - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. - const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, 'a'); - tick(100); - fix.detectChanges(); - // Commit the populated expression. - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); - fix.detectChanges(); - - // Verify the operator line of the new group is an 'And' line. - QueryBuilderFunctions.verifyOperatorLine(QueryBuilderFunctions.getQueryBuilderTreeGroupOperatorLine(fix, [0]) as HTMLElement, 'or'); - - // adding buttons should be enabled - const addingButtons = QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtons(fix, 0); - expect(addingButtons.length).toBe(2); - for (const button of addingButtons) { - ControlsFunction.verifyButtonIsDisabled(button as HTMLElement, false); - } + queryBuilder = fix.componentInstance.queryBuilder; + })); + + describe('Basic', () => { + it('Should render empty Query Builder properly.', fakeAsync(() => { + tick(100); + fix.detectChanges(); + const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER}`))[0].nativeElement; + expect(queryBuilderElement).toBeDefined(); + expect(queryBuilderElement.children.length).toEqual(1); + + const queryTreeElement = queryBuilderElement.children[0]; + expect(queryTreeElement.classList.contains(QueryBuilderSelectors.QUERY_BUILDER_TREE)).toBe(true); + + expect(queryBuilder.expressionTree).toBeUndefined(); + + expect(queryTreeElement.children.length).toEqual(3); + const bodyElement = queryTreeElement.children[0]; + expect(bodyElement.classList.contains(QueryBuilderSelectors.QUERY_BUILDER_BODY)).toBe(true); + expect(bodyElement.children.length).toEqual(1); + + QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, false); + QueryBuilderFunctions.verifyQueryEditModeExpressionInputValues(fix, '', ''); + + // Select 'Products' entity + QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 0); + tick(100); + fix.detectChanges(); + + QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, true); + QueryBuilderFunctions.verifyQueryEditModeExpressionInputValues(fix, 'Products', 'Id, ProductName, OrderId, Released'); + })); + + it('Should render Query Builder with initially set expression tree properly.', fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + + const queryTreeElement: HTMLElement = fix.debugElement.queryAll(By.css(QueryBuilderSelectors.QUERY_BUILDER_TREE))[0].nativeElement; + const bodyElement = queryTreeElement.children[0]; + expect(bodyElement.classList.contains(QueryBuilderSelectors.QUERY_BUILDER_BODY)).toBe(true); + expect(bodyElement.children.length).toEqual(2); + + // Verify the operator line of the root group is an 'And' line. + QueryBuilderFunctions.verifyOperatorLine(QueryBuilderFunctions.getQueryBuilderTreeRootGroupOperatorLine(fix) as HTMLElement, 'and'); + // all inputs should be displayed correctly + const selectFromContainer = bodyElement.children[0]; + expect(selectFromContainer.classList.contains('igx-filter-tree__inputs')).toBe(true); + expect(selectFromContainer.children[0].children[1].tagName).toEqual('IGX-SELECT'); + expect(selectFromContainer.children[1].children[1].tagName).toEqual('IGX-COMBO'); + const queryTreeExpressionContainer = bodyElement.children[1].children[1]; + expect(queryTreeExpressionContainer.classList.contains('igx-filter-tree')).toBe(true); + expect(queryTreeExpressionContainer.children[1].classList.contains('igx-filter-tree__expressions')).toBe(true); + + const selectEntity = QueryBuilderFunctions.getQueryBuilderEntitySelect(fix, 0); + expect(selectEntity.children[0].classList.contains('igx-input-group--disabled')).toBe(false); + + const fieldsCombo = QueryBuilderFunctions.getQueryBuilderFieldsCombo(fix, 0); + expect(fieldsCombo.children[0].classList.contains('igx-input-group--disabled')).toBe(false); + + const expressionItems = queryTreeExpressionContainer.children[1].children[1].querySelectorAll(':scope > .igx-filter-tree__expression-item'); + expect(expressionItems.length).toEqual(queryBuilder.expressionTree.filteringOperands.length); + // entity select should have proper value + expect(queryBuilder.queryTree.selectedEntity.name).toEqual(queryBuilder.expressionTree.entity); + // fields input should have proper value + expect(queryBuilder.queryTree.selectedReturnFields.length).toEqual(4); + // nested queries should be collapsed + const nestedQueryTrees = queryTreeExpressionContainer.querySelectorAll(QueryBuilderSelectors.QUERY_BUILDER_TREE); + for (let i = 0; i < nestedQueryTrees.length; i++) { + expect(nestedQueryTrees[i].checkVisibility()).toBe(false); + } + // adding buttons should be enabled + const buttons = QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtons(fix, 0); + for (const button of buttons) { + ControlsFunction.verifyButtonIsDisabled(button as HTMLElement, false); + } + })); - group = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement; - QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 4, 8); - expect(queryBuilder.expressionTreeChange.emit).toHaveBeenCalled(); - })); + it('Should render combo for main entity return fields and select for nested entity return field.', fakeAsync(() => { + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); - it(`Should add a new 'And' group to existing group by using add buttons.`, fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - - spyOn(queryBuilder.expressionTreeChange, 'emit').and.callThrough(); - - // Verify group's children count before adding a new child. - let group = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement; - QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 3, 6); - - // Change root group to 'Or' group - QueryBuilderFunctions.clickQueryBuilderGroupContextMenu(fix, 0); - tick(100); - fix.detectChanges(); - - QueryBuilderFunctions.clickContextMenuItem(fix, 0); - tick(100); - fix.detectChanges(); - - // Add new 'And' group. - const buttonsContainer = Array.from(group.querySelectorAll('.igx-filter-tree__buttons'))[1]; - const buttons = Array.from(buttonsContainer.querySelectorAll('button')); - (buttons[1] as HTMLElement).click(); - tick(); - fix.detectChanges(); - - // Newly added condition should be empty - QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, false, false, false); - QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, '', '', ''); - - // Populate edit inputs. - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'OrderName' column. - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. - const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, 'a'); - tick(100); - fix.detectChanges(); - // Commit the populated expression. - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); - fix.detectChanges(); - - // Verify the operator line of the new group is an 'And' line. - QueryBuilderFunctions.verifyOperatorLine(QueryBuilderFunctions.getQueryBuilderTreeGroupOperatorLine(fix, [0]) as HTMLElement, 'and'); - - group = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement; - QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 4, 8); - expect(queryBuilder.expressionTreeChange.emit).toHaveBeenCalled(); - })); + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); // Select 'OrderId' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 10); // Select 'In' operator. - it(`Should remove a condition from an existing group by using the 'close' icon of the respective chip.`, fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); + const mainEntityContainer = QueryBuilderFunctions.getQueryBuilderEditModeContainer(fix, true, 0); + const nestedEntityContainer = QueryBuilderFunctions.getQueryBuilderEditModeContainer(fix, true, 1); - spyOn(queryBuilder.expressionTreeChange, 'emit').and.callThrough(); + expect(mainEntityContainer.children[1].children[1].tagName).toBe('IGX-COMBO'); + expect(nestedEntityContainer.children[1].children[1].tagName).toBe('IGX-SELECT'); + })); - // Verify tree layout before deleting chips. - QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 3, 6); + it('Should return proper fields collection without additional props.', fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); - // Delete a chip and verify layout. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChipRemoveIcon(fix, [0]); - tick(100); - fix.detectChanges(); + queryBuilder.entities[0].fields.forEach(field => { + expect(field.filters).toBeUndefined(); + expect(field.pipeArgs).toBeUndefined(); + }); + })); - QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 2, 2); - expect(queryBuilder.expressionTreeChange.emit).toHaveBeenCalled(); + it('Should not throw error when entities are empty and expressionTree is set.', fakeAsync(() => { + expect(() => { + fix = TestBed.createComponent(IgxQueryBuilderInvalidSampleTestComponent); + fix.detectChanges(); + }).not.toThrow(); + })); + }); - // Delete a chip and verify layout. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChipRemoveIcon(fix, [1]); - tick(100); - flush(); - fix.detectChanges(); - QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 1, 1); + describe('Interactions', () => { + it('Should correctly initialize a newly added \'And\' group.', fakeAsync(() => { + QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1); // Select 'Orders' entity + tick(100); + fix.detectChanges(); - // Verify remaining chip's content. - QueryBuilderFunctions.verifyExpressionChipContent(fix, [0], 'OrderId', 'Greater Than', '3'); + // Click the initial 'Add Condition' button. + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); + tick(100); + fix.detectChanges(); - // Delete the last chip and verify that the group is deleted as well. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChipRemoveIcon(fix, [0]); - tick(100); - flush(); - fix.detectChanges(); + // Verify there is a new root group, which is empty. + QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 0, 0); - QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 0, 0); - })); + // Verify the operator line of the root group is an 'And' line. + QueryBuilderFunctions.verifyOperatorLine(QueryBuilderFunctions.getQueryBuilderTreeRootGroupOperatorLine(fix) as HTMLElement, 'and'); + + // Verify the enabled/disabled state of each input of the expression in edit mode. + QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, true, true, false, false, false); + + // Verify the edit inputs are empty. + QueryBuilderFunctions.verifyQueryEditModeExpressionInputValues(fix, 'Orders', 'OrderId, OrderName, OrderDate, Delivered', '', '', ''); + + // Verify adding buttons are not displayed + expect(QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtonsContainer(fix, 0)).toBe(undefined); + })); + + it(`Should discard newly added group when clicking on the 'cancel' button of its initial condition.`, fakeAsync(() => { + vi.spyOn(queryBuilder.expressionTreeChange, 'emit'); + expect(queryBuilder.expressionTreeChange.emit).toHaveBeenCalledTimes(0); + + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); + + expect(queryBuilder.expressionTreeChange.emit).toHaveBeenCalledTimes(1); + + // Verify there is a new root group, which is empty. + const group = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix); + expect(group).not.toBeNull('There is no root group.'); + + // Click on the 'cancel' button + const closeButton = QueryBuilderFunctions.getQueryBuilderExpressionCloseButton(fix); + UIInteractions.simulateClickEvent(closeButton); + tick(100); + fix.detectChanges(); + + // Verify there is a new root group, which is empty. + QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 0, 0); + })); + + it('Should add a new condition to existing group by using add buttons.', fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + + vi.spyOn(queryBuilder.expressionTreeChange, 'emit'); + + // Verify group's children count before adding a new child. + let group = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement; + QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 3, 6); + + + // Add new 'expression'. + const buttonsContainer = Array.from(group.querySelectorAll('.igx-filter-tree__buttons'))[1]; + const buttons = Array.from(buttonsContainer.querySelectorAll('button')); + (buttons[0] as HTMLElement).click(); + tick(); + fix.detectChanges(); + + // Newly added condition should be empty + QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, false, false, false); + QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, '', '', ''); + + // Populate edit inputs. + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'OrderName' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + UIInteractions.clickAndSendInputElementValue(input, 'a'); + tick(100); + fix.detectChanges(); + // Commit the populated expression. + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); + fix.detectChanges(); + + group = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement; + QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 4, 7); + expect(queryBuilder.expressionTreeChange.emit).toHaveBeenCalled(); + })); + + it(`Should add a new 'Or' group to existing group by using add buttons.`, fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + + vi.spyOn(queryBuilder.expressionTreeChange, 'emit'); + + // Verify group's children count before adding a new child. + let group = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement; + QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 3, 6); + + // Add new 'Or' group. + const buttonsContainer = Array.from(group.querySelectorAll('.igx-filter-tree__buttons'))[1]; + const buttons = Array.from(buttonsContainer.querySelectorAll('button')); + (buttons[1] as HTMLElement).click(); + tick(); + fix.detectChanges(); + + // Newly added condition should be empty + QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, false, false, false); + QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, '', '', ''); + + // Verify adding buttons are not displayed + expect(QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtonsContainer(fix, 0)).toBe(undefined); + + // Populate edit inputs. + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'OrderName' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + UIInteractions.clickAndSendInputElementValue(input, 'a'); + tick(100); + fix.detectChanges(); + // Commit the populated expression. + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); + fix.detectChanges(); + + // Verify the operator line of the new group is an 'And' line. + QueryBuilderFunctions.verifyOperatorLine(QueryBuilderFunctions.getQueryBuilderTreeGroupOperatorLine(fix, [0]) as HTMLElement, 'or'); + + // adding buttons should be enabled + const addingButtons = QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtons(fix, 0); + expect(addingButtons.length).toBe(2); + for (const button of addingButtons) { + ControlsFunction.verifyButtonIsDisabled(button as HTMLElement, false); + } - it('Should be able to add and define a new group through initial adding button.', fakeAsync(() => { - expect(fix.componentInstance.queryBuilder.expressionTree).toBeUndefined(); - // Select an entity - // TO DO: refactor the methods when entity and fields drop-downs are in the correct overlay - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); - - // Verify the enabled/disabled state of each input of the expression in edit mode. - expect(fix.componentInstance.queryBuilder.expressionTree).toBeDefined(); - QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, true, false, false, false, false); - - // Select fields - QueryBuilderFunctions.selectFieldsInEditModeExpression(fix, [2, 3]) - tick(100); - fix.detectChanges(); - QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, true); - - // Click the initial 'Add Condition' button. - QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix); - tick(100); - fix.detectChanges(); - - //Select Column - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); - QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, true, true, true, true, false); - - //Select Operator - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); - QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, true, true, true, true, false); - - //Type Value - const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, 'a'); - tick(100); - fix.detectChanges(); - QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, true, true, true, true, true); - - // Verify all inputs values - QueryBuilderFunctions.verifyQueryEditModeExpressionInputValues(fix, 'Products', 'Id, ProductName, Released', 'ProductName', 'Contains', 'a'); - - //Commit the group - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); - tick(100); - fix.detectChanges(); - - //Verify that expressionTree is correct - const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); - expect(exprTree).toBe(`{ + group = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement; + QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 4, 8); + expect(queryBuilder.expressionTreeChange.emit).toHaveBeenCalled(); + })); + + it(`Should add a new 'And' group to existing group by using add buttons.`, fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + + vi.spyOn(queryBuilder.expressionTreeChange, 'emit'); + + // Verify group's children count before adding a new child. + let group = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement; + QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 3, 6); + + // Change root group to 'Or' group + QueryBuilderFunctions.clickQueryBuilderGroupContextMenu(fix, 0); + tick(100); + fix.detectChanges(); + + QueryBuilderFunctions.clickContextMenuItem(fix, 0); + tick(100); + fix.detectChanges(); + + // Add new 'And' group. + const buttonsContainer = Array.from(group.querySelectorAll('.igx-filter-tree__buttons'))[1]; + const buttons = Array.from(buttonsContainer.querySelectorAll('button')); + (buttons[1] as HTMLElement).click(); + tick(); + fix.detectChanges(); + + // Newly added condition should be empty + QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, false, false, false); + QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, '', '', ''); + + // Populate edit inputs. + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'OrderName' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + UIInteractions.clickAndSendInputElementValue(input, 'a'); + tick(100); + fix.detectChanges(); + // Commit the populated expression. + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); + fix.detectChanges(); + + // Verify the operator line of the new group is an 'And' line. + QueryBuilderFunctions.verifyOperatorLine(QueryBuilderFunctions.getQueryBuilderTreeGroupOperatorLine(fix, [0]) as HTMLElement, 'and'); + + group = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement; + QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 4, 8); + expect(queryBuilder.expressionTreeChange.emit).toHaveBeenCalled(); + })); + + it(`Should remove a condition from an existing group by using the 'close' icon of the respective chip.`, fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + + vi.spyOn(queryBuilder.expressionTreeChange, 'emit'); + + // Verify tree layout before deleting chips. + QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 3, 6); + + // Delete a chip and verify layout. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChipRemoveIcon(fix, [0]); + tick(100); + fix.detectChanges(); + + QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 2, 2); + expect(queryBuilder.expressionTreeChange.emit).toHaveBeenCalled(); + + // Delete a chip and verify layout. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChipRemoveIcon(fix, [1]); + tick(100); + flush(); + fix.detectChanges(); + QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 1, 1); + + // Verify remaining chip's content. + QueryBuilderFunctions.verifyExpressionChipContent(fix, [0], 'OrderId', 'Greater Than', '3'); + + // Delete the last chip and verify that the group is deleted as well. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChipRemoveIcon(fix, [0]); + tick(100); + flush(); + fix.detectChanges(); + + QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 0, 0); + })); + + it('Should be able to add and define a new group through initial adding button.', fakeAsync(() => { + expect(fix.componentInstance.queryBuilder.expressionTree).toBeUndefined(); + // Select an entity + // TO DO: refactor the methods when entity and fields drop-downs are in the correct overlay + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); + + // Verify the enabled/disabled state of each input of the expression in edit mode. + expect(fix.componentInstance.queryBuilder.expressionTree).toBeDefined(); + QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, true, false, false, false, false); + + // Select fields + QueryBuilderFunctions.selectFieldsInEditModeExpression(fix, [2, 3]); + tick(100); + fix.detectChanges(); + QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, true); + + // Click the initial 'Add Condition' button. + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix); + tick(100); + fix.detectChanges(); + + //Select Column + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); + QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, true, true, true, true, false); + + //Select Operator + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); + QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, true, true, true, true, false); + + //Type Value + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + UIInteractions.clickAndSendInputElementValue(input, 'a'); + tick(100); + fix.detectChanges(); + QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, true, true, true, true, true); + + // Verify all inputs values + QueryBuilderFunctions.verifyQueryEditModeExpressionInputValues(fix, 'Products', 'Id, ProductName, Released', 'ProductName', 'Contains', 'a'); + + //Commit the group + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); + tick(100); + fix.detectChanges(); + + //Verify that expressionTree is correct + const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); + expect(exprTree).toBe(`{ "filteringOperands": [ { "fieldName": "ProductName", @@ -435,188 +437,189 @@ describe('IgxQueryBuilder', () => { "Released" ] }`); - })); - - it('Value input should be disabled for unary operator.', fakeAsync(() => { - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); - - //Select Column - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 3); - QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, true, true, true, false, true); - - //Select Operator - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); - QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, true, true, true, false, true); - })); - - it('Fields dropdown should contain proper fields based on the entity.', fakeAsync(() => { - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); - - // Open fields dropdown and verify the items. - QueryBuilderFunctions.clickQueryBuilderFieldsCombo(fix); - fix.detectChanges(); - - // TO DO: refactor when overlay issue is fixed - const outlet = fix.debugElement.queryAll(By.css(`.igx-drop-down__list-scroll`))[1].nativeElement; - const dropdownItems = Array.from(outlet.querySelectorAll('.igx-drop-down__item'));; - expect(dropdownItems.length).toBe(5); - expect((dropdownItems[0] as HTMLElement).innerText).toBe('Select All'); - expect((dropdownItems[1] as HTMLElement).innerText).toBe('Id'); - expect((dropdownItems[2] as HTMLElement).innerText).toBe('ProductName'); - expect((dropdownItems[3] as HTMLElement).innerText).toBe('OrderId'); - expect((dropdownItems[4] as HTMLElement).innerText).toBe('Released'); - })); - - it('ReturnFields should be properly calculated on entity change.', fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - queryBuilder.showEntityChangeDialog = false; - fix.detectChanges(); - - // Verify the returnFields - let exprTreeReturnFields = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree.returnFields); - expect(exprTreeReturnFields).toBe(`["*"]`); - - // Change the selected return fields - QueryBuilderFunctions.selectFieldsInEditModeExpression(fix, [1]); - tick(100); - fix.detectChanges(); - - // Verify the returnFields - exprTreeReturnFields = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree.returnFields); - expect(exprTreeReturnFields).toBe(`["OrderId"]`); - - // Change the entity - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); - - // Verify the returnFields - exprTreeReturnFields = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree.returnFields); - expect(exprTreeReturnFields).toBe(`["*"]`); - })); - - it('ReturnFields should be properly calculated on selectAll click.', fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - queryBuilder.showEntityChangeDialog = false; - fix.detectChanges(); - - // Click selectAll button in order to deselect all fields - QueryBuilderFunctions.selectFieldsInEditModeExpression(fix, [0]); - tick(100); - fix.detectChanges(); - - // Verify the returnFields - let exprTreeReturnFields = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree.returnFields); - expect(exprTreeReturnFields).toBe(`[]`); - - // Click selectAll button in order to select all fields - QueryBuilderFunctions.selectFieldsInEditModeExpression(fix, [0]); - tick(100); - fix.detectChanges(); - - // Verify the returnFields - exprTreeReturnFields = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree.returnFields); - expect(exprTreeReturnFields).toBe(`["*"]`); - })); - - it('Column dropdown should contain proper fields based on the entity.', fakeAsync(() => { - const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}`))[0].nativeElement; - - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); - - // Open columns dropdown and verify the items. - QueryBuilderFunctions.clickQueryBuilderColumnSelect(fix); - fix.detectChanges(); - const dropdownItems = QueryBuilderFunctions.getQueryBuilderSelectDropdownItems(queryBuilderElement); - expect(dropdownItems.length).toBe(4); - expect((dropdownItems[0] as HTMLElement).innerText).toBe('OrderId'); - expect((dropdownItems[1] as HTMLElement).innerText).toBe('OrderName'); - expect((dropdownItems[2] as HTMLElement).innerText).toBe('OrderDate'); - })); - - it('Operator dropdown should contain operators based on the column\'s datatype (\'string\' or \'number\' or \'date\').', fakeAsync(() => { - const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}`))[0].nativeElement; - - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); - - // Select 'string' type column ('OrderName'). - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); - // Open the operator dropdown and verify they are 'string' specific. - QueryBuilderFunctions.clickQueryBuilderOperatorSelect(fix); - fix.detectChanges(); - let dropdownValues: string[] = QueryBuilderFunctions.getQueryBuilderSelectDropdownItems(queryBuilderElement).map((x: any) => x.innerText); - let expectedValues = ['Contains', 'Does Not Contain', 'Starts With', 'Ends With', 'Equals', - 'Does Not Equal', 'Empty', 'Not Empty', 'Null', 'Not Null', 'In', 'Not In']; - expect(dropdownValues).toEqual(expectedValues); - - // Close current dropdown by a random select. - QueryBuilderFunctions.clickQueryBuilderSelectDropdownItem(queryBuilderElement, 0); - tick(); - fix.detectChanges(); - - // Select 'number' type column ('OrderId'). - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); - // Open the operator dropdown and verify they are 'number' specific. - QueryBuilderFunctions.clickQueryBuilderOperatorSelect(fix); - fix.detectChanges(); - dropdownValues = QueryBuilderFunctions.getQueryBuilderSelectDropdownItems(queryBuilderElement).map((x: any) => x.innerText); - expectedValues = ['Equals', 'Does Not Equal', 'Greater Than', 'Less Than', 'Greater Than Or Equal To', - 'Less Than Or Equal To', 'Empty', 'Not Empty', 'Null', 'Not Null', 'In', 'Not In']; - expect(dropdownValues).toEqual(expectedValues); - - // Close current dropdown by a random select. - QueryBuilderFunctions.clickQueryBuilderSelectDropdownItem(queryBuilderElement, 0); - tick(); - fix.detectChanges(); - - // Select 'date' type column ('OrderDate'). - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 2); - // Open the operator dropdown and verify they are 'date' specific. - QueryBuilderFunctions.clickQueryBuilderOperatorSelect(fix); - fix.detectChanges(); - dropdownValues = QueryBuilderFunctions.getQueryBuilderSelectDropdownItems(queryBuilderElement).map((x: any) => x.innerText); - expectedValues = ['Equals', 'Does Not Equal', 'Before', 'After', 'Today', 'Yesterday', - 'This Month', 'Last Month', 'Next Month', 'This Year', 'Last Year', - 'Next Year', 'Empty', 'Not Empty', 'Null', 'Not Null', 'In', 'Not In']; - expect(dropdownValues).toEqual(expectedValues); - })); - - it('Operator dropdown should contain operators based on the column\'s datatype (\'boolean\').', fakeAsync(() => { - const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}`))[0].nativeElement; - - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); - - // Select 'boolean' type column ('Released'). - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 3); - // Open the operator dropdown and verify they are 'boolean' specific. - QueryBuilderFunctions.clickQueryBuilderOperatorSelect(fix); - fix.detectChanges(); - const dropdownValues: string[] = QueryBuilderFunctions.getQueryBuilderSelectDropdownItems(queryBuilderElement).map((x: any) => x.innerText); - const expectedValues = ['All', 'True', 'False', 'Empty', 'Not Empty', 'Null', 'Not Null', 'In', 'Not In']; - expect(dropdownValues).toEqual(expectedValues); - })); - - it('Should correctly apply a \'string\' column condition through UI.', fakeAsync(() => { - // Verify there is no expression. - expect(queryBuilder.expressionTree).toBeUndefined(); - - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); - - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 2); // Select 'Starts With' operator. - const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); - // Verify value input placeholder - expect(input.placeholder).toEqual('Value'); - // Type Value - UIInteractions.clickAndSendInputElementValue(input, 'a'); - tick(100); - fix.detectChanges(); - - // Commit the populated expression. - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); - fix.detectChanges(); - - //Verify that expressionTree is correct - const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); - expect(exprTree).toBe(`{ + })); + + it('Value input should be disabled for unary operator.', fakeAsync(() => { + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); + + //Select Column + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 3); + QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, true, true, true, false, true); + + //Select Operator + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); + QueryBuilderFunctions.verifyEditModeQueryExpressionInputStates(fix, true, true, true, true, false, true); + })); + + it('Fields dropdown should contain proper fields based on the entity.', fakeAsync(() => { + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); + + // Open fields dropdown and verify the items. + QueryBuilderFunctions.clickQueryBuilderFieldsCombo(fix); + fix.detectChanges(); + + // TO DO: refactor when overlay issue is fixed + const outlet = fix.debugElement.queryAll(By.css(`.igx-drop-down__list-scroll`))[1].nativeElement; + const dropdownItems = Array.from(outlet.querySelectorAll('.igx-drop-down__item')); + ; + expect(dropdownItems.length).toBe(5); + expect((dropdownItems[0] as HTMLElement).innerText).toBe('Select All'); + expect((dropdownItems[1] as HTMLElement).innerText).toBe('Id'); + expect((dropdownItems[2] as HTMLElement).innerText).toBe('ProductName'); + expect((dropdownItems[3] as HTMLElement).innerText).toBe('OrderId'); + expect((dropdownItems[4] as HTMLElement).innerText).toBe('Released'); + })); + + it('ReturnFields should be properly calculated on entity change.', fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + queryBuilder.showEntityChangeDialog = false; + fix.detectChanges(); + + // Verify the returnFields + let exprTreeReturnFields = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree.returnFields); + expect(exprTreeReturnFields).toBe(`["*"]`); + + // Change the selected return fields + QueryBuilderFunctions.selectFieldsInEditModeExpression(fix, [1]); + tick(100); + fix.detectChanges(); + + // Verify the returnFields + exprTreeReturnFields = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree.returnFields); + expect(exprTreeReturnFields).toBe(`["OrderId"]`); + + // Change the entity + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); + + // Verify the returnFields + exprTreeReturnFields = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree.returnFields); + expect(exprTreeReturnFields).toBe(`["*"]`); + })); + + it('ReturnFields should be properly calculated on selectAll click.', fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + queryBuilder.showEntityChangeDialog = false; + fix.detectChanges(); + + // Click selectAll button in order to deselect all fields + QueryBuilderFunctions.selectFieldsInEditModeExpression(fix, [0]); + tick(100); + fix.detectChanges(); + + // Verify the returnFields + let exprTreeReturnFields = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree.returnFields); + expect(exprTreeReturnFields).toBe(`[]`); + + // Click selectAll button in order to select all fields + QueryBuilderFunctions.selectFieldsInEditModeExpression(fix, [0]); + tick(100); + fix.detectChanges(); + + // Verify the returnFields + exprTreeReturnFields = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree.returnFields); + expect(exprTreeReturnFields).toBe(`["*"]`); + })); + + it('Column dropdown should contain proper fields based on the entity.', fakeAsync(() => { + const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}`))[0].nativeElement; + + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); + + // Open columns dropdown and verify the items. + QueryBuilderFunctions.clickQueryBuilderColumnSelect(fix); + fix.detectChanges(); + const dropdownItems = QueryBuilderFunctions.getQueryBuilderSelectDropdownItems(queryBuilderElement); + expect(dropdownItems.length).toBe(4); + expect((dropdownItems[0] as HTMLElement).innerText).toBe('OrderId'); + expect((dropdownItems[1] as HTMLElement).innerText).toBe('OrderName'); + expect((dropdownItems[2] as HTMLElement).innerText).toBe('OrderDate'); + })); + + it('Operator dropdown should contain operators based on the column\'s datatype (\'string\' or \'number\' or \'date\').', fakeAsync(() => { + const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}`))[0].nativeElement; + + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); + + // Select 'string' type column ('OrderName'). + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); + // Open the operator dropdown and verify they are 'string' specific. + QueryBuilderFunctions.clickQueryBuilderOperatorSelect(fix); + fix.detectChanges(); + let dropdownValues: string[] = QueryBuilderFunctions.getQueryBuilderSelectDropdownItems(queryBuilderElement).map((x: any) => x.innerText); + let expectedValues = ['Contains', 'Does Not Contain', 'Starts With', 'Ends With', 'Equals', + 'Does Not Equal', 'Empty', 'Not Empty', 'Null', 'Not Null', 'In', 'Not In']; + expect(dropdownValues).toEqual(expectedValues); + + // Close current dropdown by a random select. + QueryBuilderFunctions.clickQueryBuilderSelectDropdownItem(queryBuilderElement, 0); + tick(); + fix.detectChanges(); + + // Select 'number' type column ('OrderId'). + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); + // Open the operator dropdown and verify they are 'number' specific. + QueryBuilderFunctions.clickQueryBuilderOperatorSelect(fix); + fix.detectChanges(); + dropdownValues = QueryBuilderFunctions.getQueryBuilderSelectDropdownItems(queryBuilderElement).map((x: any) => x.innerText); + expectedValues = ['Equals', 'Does Not Equal', 'Greater Than', 'Less Than', 'Greater Than Or Equal To', + 'Less Than Or Equal To', 'Empty', 'Not Empty', 'Null', 'Not Null', 'In', 'Not In']; + expect(dropdownValues).toEqual(expectedValues); + + // Close current dropdown by a random select. + QueryBuilderFunctions.clickQueryBuilderSelectDropdownItem(queryBuilderElement, 0); + tick(); + fix.detectChanges(); + + // Select 'date' type column ('OrderDate'). + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 2); + // Open the operator dropdown and verify they are 'date' specific. + QueryBuilderFunctions.clickQueryBuilderOperatorSelect(fix); + fix.detectChanges(); + dropdownValues = QueryBuilderFunctions.getQueryBuilderSelectDropdownItems(queryBuilderElement).map((x: any) => x.innerText); + expectedValues = ['Equals', 'Does Not Equal', 'Before', 'After', 'Today', 'Yesterday', + 'This Month', 'Last Month', 'Next Month', 'This Year', 'Last Year', + 'Next Year', 'Empty', 'Not Empty', 'Null', 'Not Null', 'In', 'Not In']; + expect(dropdownValues).toEqual(expectedValues); + })); + + it('Operator dropdown should contain operators based on the column\'s datatype (\'boolean\').', fakeAsync(() => { + const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}`))[0].nativeElement; + + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); + + // Select 'boolean' type column ('Released'). + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 3); + // Open the operator dropdown and verify they are 'boolean' specific. + QueryBuilderFunctions.clickQueryBuilderOperatorSelect(fix); + fix.detectChanges(); + const dropdownValues: string[] = QueryBuilderFunctions.getQueryBuilderSelectDropdownItems(queryBuilderElement).map((x: any) => x.innerText); + const expectedValues = ['All', 'True', 'False', 'Empty', 'Not Empty', 'Null', 'Not Null', 'In', 'Not In']; + expect(dropdownValues).toEqual(expectedValues); + })); + + it('Should correctly apply a \'string\' column condition through UI.', fakeAsync(() => { + // Verify there is no expression. + expect(queryBuilder.expressionTree).toBeUndefined(); + + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); + + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'ProductName' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 2); // Select 'Starts With' operator. + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + // Verify value input placeholder + expect(input.placeholder).toEqual('Value'); + // Type Value + UIInteractions.clickAndSendInputElementValue(input, 'a'); + tick(100); + fix.detectChanges(); + + // Commit the populated expression. + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); + fix.detectChanges(); + + //Verify that expressionTree is correct + const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); + expect(exprTree).toBe(`{ "filteringOperands": [ { "fieldName": "ProductName", @@ -640,28 +643,28 @@ describe('IgxQueryBuilder', () => { "Released" ] }`); - })); - - it('Should correctly apply a \'Greater Than\' with \'number\' column condition through UI.', fakeAsync(() => { - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); - - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); // Select 'Id' column. - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 2); // Select 'Greater Than' operator - const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); - // Verify value input placeholder - expect(input.placeholder).toEqual('Value'); - // Type Value - UIInteractions.clickAndSendInputElementValue(input, '5'); - tick(100); - fix.detectChanges(); - - // Commit the populated expression. - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); - fix.detectChanges(); - - //Verify that expressionTree is correct - const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); - expect(exprTree).toBe(`{ + })); + + it('Should correctly apply a \'Greater Than\' with \'number\' column condition through UI.', fakeAsync(() => { + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); + + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); // Select 'Id' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 2); // Select 'Greater Than' operator + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + // Verify value input placeholder + expect(input.placeholder).toEqual('Value'); + // Type Value + UIInteractions.clickAndSendInputElementValue(input, '5'); + tick(100); + fix.detectChanges(); + + // Commit the populated expression. + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); + fix.detectChanges(); + + //Verify that expressionTree is correct + const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); + expect(exprTree).toBe(`{ "filteringOperands": [ { "fieldName": "Id", @@ -685,26 +688,26 @@ describe('IgxQueryBuilder', () => { "Released" ] }`); - })); - - it('Should correctly apply a \'Equals\' with \'number\' column condition through UI.', fakeAsync(() => { - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); - - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); // Select 'Id' column. - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Equals' operator - //Type Value - const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, '5'); - tick(100); - fix.detectChanges(); - - // Commit the populated expression. - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); - fix.detectChanges(); - - //Verify that expressionTree is correct - const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); - expect(exprTree).toBe(`{ + })); + + it('Should correctly apply a \'Equals\' with \'number\' column condition through UI.', fakeAsync(() => { + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); + + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); // Select 'Id' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Equals' operator + //Type Value + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + UIInteractions.clickAndSendInputElementValue(input, '5'); + tick(100); + fix.detectChanges(); + + // Commit the populated expression. + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); + fix.detectChanges(); + + //Verify that expressionTree is correct + const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); + expect(exprTree).toBe(`{ "filteringOperands": [ { "fieldName": "Id", @@ -728,25 +731,25 @@ describe('IgxQueryBuilder', () => { "Released" ] }`); - })); + })); - it('Should correctly apply a \'boolean\' column condition through UI.', fakeAsync(() => { - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 3); // Select 'Released' column. - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 1); // Select 'True' operator. + it('Should correctly apply a \'boolean\' column condition through UI.', fakeAsync(() => { + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 3); // Select 'Released' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 1); // Select 'True' operator. - // Verify value input placeholder - const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); - // Verify value input placeholder - expect(input.placeholder).toEqual('Value'); + // Verify value input placeholder + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + // Verify value input placeholder + expect(input.placeholder).toEqual('Value'); - // Commit the populated expression. - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); - fix.detectChanges(); + // Commit the populated expression. + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); + fix.detectChanges(); - //Verify that expressionTree is correct - const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); - expect(exprTree).toBe(`{ + //Verify that expressionTree is correct + const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); + expect(exprTree).toBe(`{ "filteringOperands": [ { "fieldName": "Released", @@ -770,27 +773,27 @@ describe('IgxQueryBuilder', () => { "Released" ] }`); - })); + })); - it('Should correctly apply a \'date\' column condition through UI with unary operator.', fakeAsync(() => { - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); + it('Should correctly apply a \'date\' column condition through UI with unary operator.', fakeAsync(() => { + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 2); // Select 'OrderDate' column. - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 9); // Select 'This Year' operator. + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 2); // Select 'OrderDate' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 9); // Select 'This Year' operator. - // Verify value input placeholder - const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); - // Verify value input placeholder - expect(input.placeholder).toEqual(queryBuilder.resourceStrings.igx_query_builder_date_placeholder); + // Verify value input placeholder + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + // Verify value input placeholder + expect(input.placeholder).toEqual(queryBuilder.resourceStrings.igx_query_builder_date_placeholder); - QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, false, true); // Third input should be disabled for unary operators. - // Commit the populated expression. - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); - fix.detectChanges(); + QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, false, true); // Third input should be disabled for unary operators. + // Commit the populated expression. + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); + fix.detectChanges(); - //Verify that expressionTree is correct - const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); - expect(exprTree).toBe(`{ + //Verify that expressionTree is correct + const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); + expect(exprTree).toBe(`{ "filteringOperands": [ { "fieldName": "OrderDate", @@ -814,63 +817,63 @@ describe('IgxQueryBuilder', () => { "Delivered" ] }`); - })); + })); - it('Should correctly apply a \'date\' column condition through UI with value from calendar.', fakeAsync(() => { - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); + it('Should correctly apply a \'date\' column condition through UI with value from calendar.', fakeAsync(() => { + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 2); // Select 'OrderDate' column. - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Equals' operator. - QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, true, false); - const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix, true) as HTMLElement; - input.click(); - fix.detectChanges(); + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 2); // Select 'OrderDate' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Equals' operator. + QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, true, false); + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix, true) as HTMLElement; + input.click(); + fix.detectChanges(); - // Click on 'today' item in calendar. - const calendar = QueryBuilderFunctions.getQueryBuilderCalendar(fix); - const todayItem = calendar.querySelector('.igx-days-view__date--current'); - todayItem.firstChild.click(); - tick(100); - fix.detectChanges(); + // Click on 'today' item in calendar. + const calendar = QueryBuilderFunctions.getQueryBuilderCalendar(fix); + const todayItem = calendar.querySelector('.igx-days-view__date--current'); + todayItem.firstChild.click(); + tick(100); + fix.detectChanges(); - QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, true, true); + QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, true, true); - flush(); - })); + flush(); + })); - it('Should correctly apply an \'in\' column condition through UI.', fakeAsync(() => { - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); + it('Should correctly apply an \'in\' column condition through UI.', fakeAsync(() => { + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); // Select 'OrderId' column. - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 10); // Select 'In' operator. + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); // Select 'OrderId' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 10); // Select 'In' operator. - // Verify operator icon - const operatorSelectDebugElement = fix.debugElement.queryAll(By.directive(IgxSelectComponent))[2]; - const inputDebugElement = operatorSelectDebugElement.query(By.directive(IgxInputGroupComponent)); - const iconDebugElem = inputDebugElement.query(By.directive(IgxIconComponent)); - expect(iconDebugElem.componentInstance.name).toEqual('in'); + // Verify operator icon + const operatorSelectDebugElement = fix.debugElement.queryAll(By.directive(IgxSelectComponent))[2]; + const inputDebugElement = operatorSelectDebugElement.query(By.directive(IgxInputGroupComponent)); + const iconDebugElem = inputDebugElement.query(By.directive(IgxIconComponent)); + expect(iconDebugElem.componentInstance.name).toEqual('in'); - const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); - // Verify value input placeholder - expect(input.placeholder).toEqual('Sub-query results'); + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + // Verify value input placeholder + expect(input.placeholder).toEqual('Sub-query results'); - // Verify inputs states - QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, false, false); + // Verify inputs states + QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, false, false); - // Should render empty query builder tree - const queryTreeElement = fix.debugElement.queryAll(By.css(QueryBuilderSelectors.QUERY_BUILDER_TREE))[0] - const nestedTree = queryTreeElement.query(By.css(QueryBuilderSelectors.QUERY_BUILDER_TREE)); - expect(nestedTree).toBeDefined(); + // Should render empty query builder tree + const queryTreeElement = fix.debugElement.queryAll(By.css(QueryBuilderSelectors.QUERY_BUILDER_TREE))[0]; + const nestedTree = queryTreeElement.query(By.css(QueryBuilderSelectors.QUERY_BUILDER_TREE)); + expect(nestedTree).toBeDefined(); - QueryBuilderFunctions.addAndValidateChildGroup(fix, 1); + QueryBuilderFunctions.addAndValidateChildGroup(fix, 1); - QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, false, true); // Parent commit button should be enabled - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); - fix.detectChanges(); + QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, false, true); // Parent commit button should be enabled + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); + fix.detectChanges(); - //Verify that expressionTree is correct - const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); - expect(exprTree).toBe(`{ + //Verify that expressionTree is correct + const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); + expect(exprTree).toBe(`{ "filteringOperands": [ { "fieldName": "OrderId", @@ -915,41 +918,41 @@ describe('IgxQueryBuilder', () => { "Delivered" ] }`); - })); + })); - it('Should correctly apply a \'not-in\' column condition through UI.', fakeAsync(() => { - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); + it('Should correctly apply a \'not-in\' column condition through UI.', fakeAsync(() => { + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); // Select 'OrderId' column. - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 11); // Select 'Not-In' operator. + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); // Select 'OrderId' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 11); // Select 'Not-In' operator. - // Verify operator icon - const operatorSelectDebugElement = fix.debugElement.queryAll(By.directive(IgxSelectComponent))[2]; - const inputDebugElement = operatorSelectDebugElement.query(By.directive(IgxInputGroupComponent)); - const iconDebugElem = inputDebugElement.query(By.directive(IgxIconComponent)); - expect(iconDebugElem.componentInstance.name).toEqual('not-in'); + // Verify operator icon + const operatorSelectDebugElement = fix.debugElement.queryAll(By.directive(IgxSelectComponent))[2]; + const inputDebugElement = operatorSelectDebugElement.query(By.directive(IgxInputGroupComponent)); + const iconDebugElem = inputDebugElement.query(By.directive(IgxIconComponent)); + expect(iconDebugElem.componentInstance.name).toEqual('not-in'); - const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); - // Verify value input placeholder - expect(input.placeholder).toEqual('Sub-query results'); + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + // Verify value input placeholder + expect(input.placeholder).toEqual('Sub-query results'); - // Verify inputs states - QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, false, false); + // Verify inputs states + QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, false, false); - // Should render empty query builder tree - const queryTreeElement = fix.debugElement.queryAll(By.css(QueryBuilderSelectors.QUERY_BUILDER_TREE))[0] - const nestedTree = queryTreeElement.query(By.css(QueryBuilderSelectors.QUERY_BUILDER_TREE)); - expect(nestedTree).toBeDefined(); + // Should render empty query builder tree + const queryTreeElement = fix.debugElement.queryAll(By.css(QueryBuilderSelectors.QUERY_BUILDER_TREE))[0]; + const nestedTree = queryTreeElement.query(By.css(QueryBuilderSelectors.QUERY_BUILDER_TREE)); + expect(nestedTree).toBeDefined(); - QueryBuilderFunctions.addAndValidateChildGroup(fix, 1); + QueryBuilderFunctions.addAndValidateChildGroup(fix, 1); - QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, false, true); // Parent commit button should be enabled - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); - fix.detectChanges(); + QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, false, true); // Parent commit button should be enabled + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); + fix.detectChanges(); - //Verify that expressionTree is correct - const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); - expect(exprTree).toBe(`{ + //Verify that expressionTree is correct + const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); + expect(exprTree).toBe(`{ "filteringOperands": [ { "fieldName": "OrderId", @@ -994,931 +997,935 @@ describe('IgxQueryBuilder', () => { "Delivered" ] }`); - })); - - it('Should disable value fields when isNestedQuery condition is selected', fakeAsync(() => { - //Run test for all data type fields of the Order entity - for (let i = 0; i <= 3; i++) { - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); - - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, i); // Select 'OrderId','OrderName','OrderDate','Delivered' column. - - let InConditionIndex; - switch (i) { - case 0: - case 1: InConditionIndex = 10; break;// for string and number - case 2: InConditionIndex = 16; break; //for date - case 3: InConditionIndex = 7; break; // for boolean - } - - //Verify 'In' disables value input and renders empty sub query - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, InConditionIndex); // Select 'In' operator. - QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, false, false); - let nestedTree = fix.debugElement.query(By.css(QueryBuilderSelectors.QUERY_BUILDER_TREE)); - expect(nestedTree).toBeDefined(); - - //Verify 'NotIn' disables value input and renders empty sub query - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, InConditionIndex + 1); // Select 'NotIn' operator. - QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, false, false); - nestedTree = fix.debugElement.query(By.css(QueryBuilderSelectors.QUERY_BUILDER_TREE)); - expect(nestedTree).toBeDefined(); - - const closeBtn = QueryBuilderFunctions.getQueryBuilderExpressionCloseButton(fix); - closeBtn.click(); - fix.detectChanges(); - } - })); - - it('Should correctly focus the search value input when editing the filtering expression', fakeAsync(() => { - //Create dateTime filtering expression - const tree = new FilteringExpressionsTree(FilteringLogic.And, null, 'Orders', ['OrderId']); - tree.filteringOperands.push({ - fieldName: 'OrderDate', - searchVal: new Date('2024-09-17T21:00:00.000Z'), - conditionName: 'equals', - condition: IgxDateFilteringOperand.instance().condition('equals') - }); - - queryBuilder.expressionTree = tree; - fix.detectChanges(); - - // Click the edit icon to enter edit mode of the expression. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); - tick(200); - fix.detectChanges(); - - //Check for the active element - const searchValueInput = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); - expect(document.activeElement).toBe(searchValueInput, 'The input should be the active element.'); - })); - - it('Should display add button when hovering a chip.', fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - - // Verify actions container is not visible. (This container contains the 'add' button.) - expect(QueryBuilderFunctions.getQueryBuilderTreeExpressionActionsContainer(fix, [0])) - .toBeNull('actions container is visible'); - - // Hover the first chip and verify actions container is visible. - UIInteractions.hoverElement(QueryBuilderFunctions.getQueryBuilderTreeItem(fix, [0]) as HTMLElement); - tick(50); - fix.detectChanges(); - expect(QueryBuilderFunctions.getQueryBuilderTreeExpressionActionsContainer(fix, [0])) - .not.toBeNull('actions container is not visible'); - - // Unhover the first chip and verify actions container is not visible. - UIInteractions.unhoverElement(QueryBuilderFunctions.getQueryBuilderTreeItem(fix, [0]) as HTMLElement); - tick(50); - fix.detectChanges(); - expect(QueryBuilderFunctions.getQueryBuilderTreeExpressionActionsContainer(fix, [0])) - .toBeNull('actions container is visible'); - })); - - it('Should have disabled adding buttons when an expression is in edit mode.', fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - - // Verify adding buttons are enabled - let buttons = QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtons(fix, 0); - for (const button of buttons) { - ControlsFunction.verifyButtonIsDisabled(button as HTMLElement, false); - } - - // Enter edit mode - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); - tick(50); - fix.detectChanges(); - - // Verify adding buttons are not displayed - expect(QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtonsContainer(fix, 0)).toBe(undefined); - - // Exit edit mode - const closeButton = QueryBuilderFunctions.getQueryBuilderExpressionCloseButton(fix); - UIInteractions.simulateClickEvent(closeButton); - tick(100); - fix.detectChanges(); - - // Verify adding buttons are enabled - buttons = QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtons(fix, 0); - for (const button of buttons) { - ControlsFunction.verifyButtonIsDisabled(button as HTMLElement, false); - } - })); - - it('Clicking a condition should put it in edit mode.', fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - - // Click the existing chip to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); - tick(50); - fix.detectChanges(); - // Verify inputs values - QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, 'OrderId', 'Greater Than', '3'); - // Edit the operator - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Equals' operator. - // Commit the change - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); - fix.detectChanges(); - // Verify the chip - QueryBuilderFunctions.verifyExpressionChipContent(fix, [1], 'OrderId', 'Equals', '3'); - - // Verify that the nested query is not expanded - expect(fix.debugElement.query(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}--level-1`)).nativeElement.checkVisibility()).toBeFalse(); - - // Click the nested query chip to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); - tick(50); - fix.detectChanges(); - // Verify the query is expanded - expect(fix.debugElement.query(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}--level-1`)).nativeElement.checkVisibility()).toBeTrue(); - // Click a chip in the nested query three to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0], 1); - tick(50); - fix.detectChanges(); - // Verify inputs values - QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, 'ProductName', 'Contains', 'a', 1); - // Edit the operator - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 2, 1); // Select 'Starts With' operator. - // Commit the change - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix, 1); - fix.detectChanges(); - // Verify the chip - QueryBuilderFunctions.verifyExpressionChipContent(fix, [0], 'ProductName', 'Starts With', 'a', 1); - })); - - it('Should switch edit mode on click on chip on the same level.', fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); - tick(50); - fix.detectChanges(); - - // Click the existing chip to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0], 1); - tick(50); - fix.detectChanges(); - // Verify inputs values - QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, 'ProductName', 'Contains', 'a', 1); - - // Click the existing chip to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0], 1); - tick(50); - fix.detectChanges(); - // Verify inputs values - QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, 'Released', 'True', '', 1); - QueryBuilderFunctions.verifyExpressionChipContent(fix, [0], 'ProductName', 'Contains', 'a', 1); - })); - - it('Should exit edit mode on add, change group buttons, entity and fields select click.', fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - - // Click chip to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); - tick(50); - fix.detectChanges(); - - // Hover exprssion and click add button - UIInteractions.hoverElement(QueryBuilderFunctions.getQueryBuilderTreeItem(fix, [0]) as HTMLElement); - tick(50); - fix.detectChanges(); - (QueryBuilderFunctions.getQueryBuilderTreeExpressionIcon(fix, [0], 'add') as HTMLElement).click(); - tick(50); - fix.detectChanges(); - - expect(queryBuilder.queryTree.hasEditedExpression).toBeFalse(); - - // Click chip to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); - tick(50); - fix.detectChanges(); - - // Click change group button - QueryBuilderFunctions.clickQueryBuilderGroupContextMenu(fix, 0); - tick(100); - fix.detectChanges(); - - expect(queryBuilder.queryTree.hasEditedExpression).toBeFalse(); - - // Click chip to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); - tick(50); - fix.detectChanges(); - - // Click fields select - QueryBuilderFunctions.clickQueryBuilderFieldsCombo(fix); - fix.detectChanges(); - - expect(queryBuilder.queryTree.hasEditedExpression).toBeFalse(); - - // Click chip to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); - tick(50); - fix.detectChanges(); - - // Click entity select - QueryBuilderFunctions.clickQueryBuilderEntitySelect(fix); - fix.detectChanges(); - - expect(queryBuilder.queryTree.hasEditedExpression).toBeFalse(); - })); - - it('Should show add expression button when there is an expression in add mode.', fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - - // Hover expression and click add button - UIInteractions.hoverElement(QueryBuilderFunctions.getQueryBuilderTreeItem(fix, [0]) as HTMLElement); - tick(50); - fix.detectChanges(); - (QueryBuilderFunctions.getQueryBuilderTreeExpressionIcon(fix, [0], 'add') as HTMLElement).click(); - tick(50); - fix.detectChanges(); - - // Click 'add condition' option - QueryBuilderFunctions.clickQueryBuilderTreeAddOption(fix, 0); - - // Hover the first chip and verify actions container is visible. - UIInteractions.hoverElement(QueryBuilderFunctions.getQueryBuilderTreeItem(fix, [0]) as HTMLElement); - tick(50); - fix.detectChanges(); - expect(QueryBuilderFunctions.getQueryBuilderTreeExpressionActionsContainer(fix, [0])) - .not.toBeNull('actions container is not visible'); - - // Hover the second chip and verify actions container is visible. - UIInteractions.hoverElement(QueryBuilderFunctions.getQueryBuilderTreeItem(fix, [1]) as HTMLElement); - tick(50); - fix.detectChanges(); - expect(QueryBuilderFunctions.getQueryBuilderTreeExpressionActionsContainer(fix, [1])) - .not.toBeNull('actions container is not visible'); - })); - - it('Should display an alert dialog when the entity is changed and showEntityChangeDialog is true.', fakeAsync(() => { - const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER}`))[0].nativeElement; - const queryTreeElement = queryBuilderElement.querySelector(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}`); - const dialog = queryTreeElement.querySelector('igx-dialog'); - const dialogOutlet = document.querySelector('.igx-dialog__window'); - expect(dialog).toBeDefined(); - - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); - - // Alert dialog should not be opened if there is no previous selection - expect(dialog.checkVisibility()).toBeFalse(); - - // Select entity - QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1); - tick(100); - fix.detectChanges(); - - // Alert dialog should be opened - expect(dialog.checkVisibility()).toBeTrue(); - - // Show again checkbox should be unchecked - const checkbox = dialogOutlet.querySelector('igx-checkbox'); - expect(checkbox).toBeDefined(); - expect(checkbox).not.toHaveClass('igx-checkbox--checked'); - expect(queryBuilder.showEntityChangeDialog).toBeTrue(); - - // Close dialog - const cancelButton = Array.from(dialogOutlet.querySelectorAll('button'))[0]; - cancelButton.click(); - tick(100); - fix.detectChanges(); - - // Select entity - QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1); - tick(100); - fix.detectChanges(); - - // Alert dialog should NOT be opened - expect(dialog.checkVisibility()).toBeTrue(); - })); - - it('Should not display an alert dialog when the entity changed once showEntityChangeDialog is disabled.', fakeAsync(() => { - const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER}`))[0].nativeElement; - const queryTreeElement = queryBuilderElement.querySelector(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}`); - const dialog = queryTreeElement.querySelector('igx-dialog'); - const dialogOutlet = document.querySelector('.igx-dialog__window'); - expect(dialog).toBeDefined(); - - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); - - // Alert dialog should not be opened if there is no previous selection - expect(dialog.checkVisibility()).toBeFalse(); - - // Select entity - QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1); - tick(100); - fix.detectChanges(); - - // Alert dialog should be opened - expect(dialog.checkVisibility()).toBeTrue(); - - // Check show again checkbox - const checkbox = dialogOutlet.querySelector('igx-checkbox') as HTMLElement; - expect(checkbox).toBeDefined(); - - checkbox.click(); - tick(100); - fix.detectChanges(); - expect(checkbox).toHaveClass('igx-checkbox--checked'); - expect(queryBuilder.showEntityChangeDialog).toBeFalse(); - - // Close dialog - const cancelButton = Array.from(dialogOutlet.querySelectorAll('button'))[0]; - cancelButton.click(); - tick(100); - fix.detectChanges(); - - // Select entity - QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1); - tick(100); - fix.detectChanges(); - - // Alert dialog should NOT be opened - expect(dialog.checkVisibility()).toBeFalse(); - })); - - it('Initially should not display an alert dialog when the entity is changed if hideEntityChangeDialog is disabled through API.', fakeAsync(() => { - queryBuilder.showEntityChangeDialog = false; - const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER}`))[0].nativeElement; - const queryTreeElement = queryBuilderElement.querySelector(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}`); - const dialog = queryTreeElement.querySelector('igx-dialog'); - expect(dialog).toBeDefined(); - - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); - - // Alert dialog should not be opened if there is no previous selection - expect(dialog.checkVisibility()).toBeFalse(); - - // Select entity - QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1); - tick(100); - fix.detectChanges(); - - // Alert dialog should NOT be opened - expect(dialog.checkVisibility()).toBeFalse(); - })); - - it('Should reset all inputs when the entity is changed.', fakeAsync(() => { - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); - - //Select Column - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); - - //Select Operator - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); - - //Type Value - const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, '1'); - tick(100); - fix.detectChanges(); - - // Verify all inputs values - QueryBuilderFunctions.verifyQueryEditModeExpressionInputValues(fix, 'Products', 'Id, ProductName, OrderId, Released', 'Id', 'Equals', '1'); - - // Commit the change - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); - - // Change the selected entity - QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1); - tick(100); - fix.detectChanges(); - - // Confirm the change - const dialogOutlet: HTMLElement = fix.debugElement.queryAll(By.css(`.igx-dialog`))[0].nativeElement; - const confirmButton = Array.from(dialogOutlet.querySelectorAll('button'))[1]; - expect(confirmButton.innerText).toEqual('Confirm'); - confirmButton.click(); - fix.detectChanges(); - - QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); - tick(100); - fix.detectChanges(); - - // Verify all inputs - QueryBuilderFunctions.verifyQueryEditModeExpressionInputValues(fix, 'Orders', 'OrderId, OrderName, OrderDate, Delivered', '', '', ''); - })); - - it('Should NOT reset all inputs when the entity is not changed.', fakeAsync(() => { - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); - - //Select Column - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); - - //Select Operator - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); - - //Type Value - const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, '1'); - tick(100); - fix.detectChanges(); - - // Verify all inputs values - QueryBuilderFunctions.verifyQueryEditModeExpressionInputValues(fix, 'Products', 'Id, ProductName, OrderId, Released', 'Id', 'Equals', '1'); - - // Commit the change - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); - - // Change the selected entity - QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1); - tick(100); - fix.detectChanges(); - - // Decline the change - const dialogOutlet: HTMLElement = fix.debugElement.queryAll(By.css(`.igx-dialog`))[0].nativeElement; - const cancelButton = Array.from(dialogOutlet.querySelectorAll('button'))[0]; - expect(cancelButton.innerText).toEqual('Cancel'); - cancelButton.click(); - tick(100); - fix.detectChanges(); - - // Verify all inputs - QueryBuilderFunctions.verifyQueryEditModeExpressionInputValues(fix, 'Products', 'Id, ProductName, OrderId, Released'); - QueryBuilderFunctions.verifyExpressionChipContent(fix, [0], 'Id', 'Equals', '1'); - })); - - it(`"commit" button should be enabled/disabled properly when editing an expression.`, fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - tick(100); - fix.detectChanges(); - - // Click the 'OrderId' chip to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); - tick(50); - fix.detectChanges(); - - // Verify "commit" button is enabled - let commitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); - ControlsFunction.verifyButtonIsDisabled(commitBtn as HTMLElement, false); - // Delete the value - let input = QueryBuilderFunctions.getQueryBuilderValueInput(fix, false).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, ''); - tick(100); - fix.detectChanges(); - // Verify "commit" button is disabled - commitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); - ControlsFunction.verifyButtonIsDisabled(commitBtn as HTMLElement); - // Enter some value - input = QueryBuilderFunctions.getQueryBuilderValueInput(fix, false).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, '5'); - tick(100); - fix.detectChanges(); - // Verify "commit" button is enabled - commitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); - ControlsFunction.verifyButtonIsDisabled(commitBtn as HTMLElement, false); - })); - - it(`Parent "commit" button should be enabled if a child condition is edited.`, fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - tick(100); - fix.detectChanges(); - - // Click the parent chip 'Products' to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); - tick(50); - fix.detectChanges(); - - // Click the child chip 'Released' to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1], 1); - tick(50); - fix.detectChanges(); - - // Change the 'Released' operator - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 2, 1); // Select 'False' operator. - - // Verify both parent and child commit buttons are enabled - let parentCommitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); - let childCommitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix, 1); - - ControlsFunction.verifyButtonIsDisabled(parentCommitBtn as HTMLElement, false); - ControlsFunction.verifyButtonIsDisabled(childCommitBtn as HTMLElement, false); - - // Commit the change - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix, 1); - - // Click the child chip 'ProductName' to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0], 1); - tick(50); - fix.detectChanges(); - - // Change the 'ProductName' column to 'Id' - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0, 1); - - // Verify input values - QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, 'Id', 'Equals', '', 1); - - // Verify parent and child commit buttons are disabled - parentCommitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); - childCommitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix, 1); - - ControlsFunction.verifyButtonIsDisabled(parentCommitBtn as HTMLElement, false); - ControlsFunction.verifyButtonIsDisabled(childCommitBtn as HTMLElement); - - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0, 1); - //Type Value - const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix, false, 1).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, '1'); - tick(100); - fix.detectChanges(); - - // Commit the child - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix, 1); - tick(50); - fix.detectChanges(); - - // Verify parent is enabled - parentCommitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); - ControlsFunction.verifyButtonIsDisabled(parentCommitBtn as HTMLElement, false); - })); - - it(`Clicking parent "commit" button should properly exit edit mode of inner query.`, fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - tick(100); - fix.detectChanges(); - - // Click the parent chip 'Products' to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); - tick(50); - fix.detectChanges(); - - // Click the child chip 'Released' to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1], 1); - tick(50); - fix.detectChanges(); - - // Change the 'Released' operator - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 2, 1); // Select 'False' operator. - - // Commit the change through the parent - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); - tick(50); - fix.detectChanges(); - - // Verify the changes in the child query are commited - let exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree.filteringOperands[0]); - expect(exprTree).toBe(`{"fieldName":"OrderId","condition":{"name":"inQuery","isUnary":false,"isNestedQuery":true,"iconName":"in"},"conditionName":"inQuery","searchVal":null,"searchTree":{"filteringOperands":[{"fieldName":"ProductName","condition":{"name":"contains","isUnary":false,"iconName":"filter_contains"},"conditionName":"contains","searchVal":"a"},{"fieldName":"Released","condition":{"name":"false","isUnary":true,"iconName":"filter_false"},"conditionName":"false","searchVal":null,"searchTree":null}],"operator":0,"entity":"Products","returnFields":["Id"]}}`); - // Enter edit mode again - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); - tick(50); - fix.detectChanges(); - - // Click the child chip 'ProductName' to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0], 1); - tick(50); - fix.detectChanges(); - - // Change the 'ProductName' column to 'Id' - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0, 1); - - // Verify input values - QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, 'Id', 'Equals', '', 1); - - // Verify parent and child commit buttons are disabled - const parentCommitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); - const childCommitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix, 1); - - ControlsFunction.verifyButtonIsDisabled(parentCommitBtn as HTMLElement, false); - ControlsFunction.verifyButtonIsDisabled(childCommitBtn as HTMLElement); - - // Commit the parent - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); - tick(50); - fix.detectChanges(); - - // Verify the changes in the child query are discarded - exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree.filteringOperands[0]); - expect(exprTree).toBe(`{"fieldName":"OrderId","condition":{"name":"inQuery","isUnary":false,"isNestedQuery":true,"iconName":"in"},"conditionName":"inQuery","searchVal":null,"searchTree":{"filteringOperands":[{"fieldName":"ProductName","condition":{"name":"contains","isUnary":false,"iconName":"filter_contains"},"conditionName":"contains","searchVal":"a"},{"fieldName":"Released","condition":{"name":"false","isUnary":true,"iconName":"filter_false"},"conditionName":"false","searchVal":null,"searchTree":null}],"operator":0,"entity":"Products","returnFields":["Id"]}}`); - })); - - it('Should collapse nested query when it is committed.', fakeAsync(() => { - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); - - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); // Select 'OrderId' column. - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 10); // Select 'In' operator. - - QueryBuilderFunctions.addAndValidateChildGroup(fix, 1); - - // Verify that the nested query is expanded - expect(fix.debugElement.query(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}--level-1`)).nativeElement.checkVisibility()).toBeTrue(); - - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); - tick(100); - fix.detectChanges(); - - // Verify that the nested query is collapsed - expect(fix.debugElement.query(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}--level-1`)).nativeElement.checkVisibility()).toBeFalse(); - })); - - it(`Should discard the changes in the fields if 'close' button of nested query condition is clicked.`, fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - tick(100); - fix.detectChanges(); - // Verify parent chip expression - QueryBuilderFunctions.verifyExpressionChipContent(fix, [0], 'OrderId', 'In', 'Products / Id'); - - // Click the parent chip 'Products' to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); - tick(50); - fix.detectChanges(); - - // Select 'Product Name' fields - QueryBuilderFunctions.selectFieldsInEditModeExpression(fix, [1, 2], 1); - const closeBtn = QueryBuilderFunctions.getQueryBuilderExpressionCloseButton(fix); - closeBtn.click(); - tick(50); - fix.detectChanges(); - // Verify parent chip expression is not changed - QueryBuilderFunctions.verifyExpressionChipContent(fix, [0], 'OrderId', 'In', 'Products / Id'); - })); - - it('Should be able to open edit mode on click, close the edited condition on "close" button click and not commit it.', fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - tick(100); - fix.detectChanges(); - - //Enter edit mode - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); - tick(200); - fix.detectChanges(); - - const closeBtn = QueryBuilderFunctions.getQueryBuilderExpressionCloseButton(fix); - - // Verify the enabled/disabled state of each input of the expression in edit mode. - QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, true, true); - - // Verify the edit inputs values. - QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, 'OrderId', 'Greater Than', '3'); - - //edit condition fields - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'OrderName' column. - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. - const value = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(value, '5'); - tick(200); - fix.detectChanges(); - - //cancel edit - closeBtn.click(); - tick(); - fix.detectChanges(); - - //Verify changes are reverted - QueryBuilderFunctions.verifyExpressionChipContent(fix, [1], 'OrderId', 'Greater Than', '3'); - })); - - it(`Should focus edited expression chip after click on the 'commit'/'discard' button.`, fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - tick(100); - fix.detectChanges(); - - // Click the 'OrderId' chip to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); - tick(100); - fix.detectChanges(); - - // Click on the 'commit' button - const commitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); - commitBtn.click(); - fix.detectChanges(); - tick(100); - fix.detectChanges(); - // Verify focused chip - QueryBuilderFunctions.verifyFocusedChip('OrderId', 'Greater Than', '3'); - - // Click the 'OrderId' chip to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); - tick(100); - fix.detectChanges(); - - // Click on the 'discard' button - const closeBtn = QueryBuilderFunctions.getQueryBuilderExpressionCloseButton(fix); - closeBtn.click(); - fix.detectChanges(); - tick(100); - fix.detectChanges(); - // Verify focused chip - QueryBuilderFunctions.verifyFocusedChip('OrderId', 'Greater Than', '3'); - })); - - it(`Should focus proper expression chip after switching edit mode and click on the 'commit'/'discard' button.`, fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - tick(100); - fix.detectChanges(); - - // Click the 'OrderDate' chip to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [2]); - tick(100); - fix.detectChanges(); - - // Click the 'OrderId' chip to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); - tick(100); - fix.detectChanges(); - - // Click on the 'commit' button - const commitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); - commitBtn.click(); - fix.detectChanges(); - tick(100); - fix.detectChanges(); - // Verify focused chip - QueryBuilderFunctions.verifyFocusedChip('OrderId', 'Greater Than', '3'); - })); - - it('Should focus added through group add buttons expression chip if it is commited.', fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - tick(100); - fix.detectChanges(); - - const group = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement; - - // Add new 'expression'. - const buttonsContainer = Array.from(group.querySelectorAll('.igx-filter-tree__buttons'))[1]; - const buttons = Array.from(buttonsContainer.querySelectorAll('button')); - (buttons[0] as HTMLElement).click(); - tick(); - fix.detectChanges(); - - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 3); // Select 'Delivered' column. - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 1); // Select 'True' operator. - tick(100); - fix.detectChanges(); - - // Click on the 'commit' button - const commitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); - commitBtn.click(); - fix.detectChanges(); - tick(300); - fix.detectChanges(); - - // Verify focused chip - QueryBuilderFunctions.verifyFocusedChip('Delivered', 'True'); - })); - - it('Should NOT focus an expression chip if added expression is discarded.', fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - tick(100); - fix.detectChanges(); - - const group = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement; - - // Add new 'expression'. - const buttonsContainer = Array.from(group.querySelectorAll('.igx-filter-tree__buttons'))[1]; - const buttons = Array.from(buttonsContainer.querySelectorAll('button')); - (buttons[0] as HTMLElement).click(); - tick(); - fix.detectChanges(); - - // Click on the 'close' button - const closeBtn = QueryBuilderFunctions.getQueryBuilderExpressionCloseButton(fix); - closeBtn.click(); - fix.detectChanges(); - tick(300); - fix.detectChanges(); - - // Verify chip is not focused - expect(document.activeElement.tagName).toEqual('BODY'); - })); - - it('Should not make bug where existing inner query is leaking to a newly created one.', fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - tick(100); - fix.detectChanges(); - - const group = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement; - - // Add new 'expression'. - const buttonsContainer = Array.from(group.querySelectorAll('.igx-filter-tree__buttons'))[1]; - const buttons = Array.from(buttonsContainer.querySelectorAll('button')); - (buttons[0] as HTMLElement).click(); - tick(); - fix.detectChanges(); - - // Add condition with 'in' operator to open inner query - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); // Select 'OrderName' column. - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 10); // Select 'Contains' operator. - tick(100); - fix.detectChanges(); - - //New empty inner query should be displayed - const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER}`))[0].nativeElement; - const bodyElement = queryBuilderElement.children[0].children[0]; - const actionArea = bodyElement.children[0].querySelector('.igx-query-builder__root-actions'); - expect(actionArea).toBeNull(); - expect(bodyElement.children[1].children[1].children[1].children[1].children[6].children[1]).toHaveClass(QueryBuilderSelectors.QUERY_BUILDER_TREE); - expect(bodyElement.children[1].children[1].children[1].children[1].children[6].children[1].children.length).toEqual(3); - const tree = bodyElement.children[1].children[1].children[1].children[1].children[6].children[1].querySelector('.igx-filter-tree__expression'); - expect(tree).toBeNull(); - })); - - it('canCommit should return the correct validity state of currently edited condition.', fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - - // Click the existing chip to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); - tick(50); - fix.detectChanges(); - expect(queryBuilder.canCommit()).toBeTrue(); - - // Verify the Query Builder validity state while editing a condition. - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); - expect(queryBuilder.canCommit()).toBeFalse(); - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); - expect(queryBuilder.canCommit()).toBeFalse(); - const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, 'a'); - tick(100); - fix.detectChanges(); - expect(queryBuilder.canCommit()).toBeTrue(); - })); - - it('canCommit should return the correct validity state of currently added condition.', fakeAsync(() => { - // Verify the Query Builder validity state while adding a condition. - QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1); // Select 'Orders' entity - tick(100); - fix.detectChanges(); - expect(queryBuilder.canCommit()).withContext('Entity selected').toBeTrue(); - - // Click the 'Add condition' button. - QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); - tick(100); - fix.detectChanges(); - expect(queryBuilder.canCommit()).withContext('Add condition clicked').toBeTrue(); - - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); - expect(queryBuilder.canCommit()).withContext('Column selected').toBeFalse(); - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); - expect(queryBuilder.canCommit()).withContext('Operator contains selected').toBeFalse(); - const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, 'a'); - tick(100); - fix.detectChanges(); - expect(queryBuilder.canCommit()).withContext('Search value filled').toBeTrue(); - - // Click on the 'cancel' button - const closeButton = QueryBuilderFunctions.getQueryBuilderExpressionCloseButton(fix); - UIInteractions.simulateClickEvent(closeButton); - tick(100); - fix.detectChanges(); - expect(queryBuilder.canCommit()).withContext('Entity remains selected').toBeTrue(); - - // Verify the Query Builder validity state for UNARY condition. - QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); - tick(100); - fix.detectChanges(); - expect(queryBuilder.canCommit()).withContext('Add condition clicked again').toBeTrue(); - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 3); - expect(queryBuilder.canCommit()).withContext('Column selected again').toBeTrue(); - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 1); - expect(queryBuilder.canCommit()).withContext('Unary operator selected').toBeTrue(); - })); - - it('Should be able to commit nested query without where condition.', fakeAsync(() => { - QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); - - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); // Select 'OrderId' column. - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 10); // Select 'In' operator. - - let commitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); - ControlsFunction.verifyButtonIsDisabled(commitBtn as HTMLElement, true); - - // Enter values in the nested query - QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 0, 1); // Select 'Products' entity - tick(100); - fix.detectChanges(); + })); + + it('Should disable value fields when isNestedQuery condition is selected', fakeAsync(() => { + //Run test for all data type fields of the Order entity + for (let i = 0; i <= 3; i++) { + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); + + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, i); // Select 'OrderId','OrderName','OrderDate','Delivered' column. + + let InConditionIndex; + switch (i) { + case 0: + case 1: + InConditionIndex = 10; + break; // for string and number + case 2: + InConditionIndex = 16; + break; //for date + case 3: + InConditionIndex = 7; + break; // for boolean + } + + //Verify 'In' disables value input and renders empty sub query + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, InConditionIndex); // Select 'In' operator. + QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, false, false); + let nestedTree = fix.debugElement.query(By.css(QueryBuilderSelectors.QUERY_BUILDER_TREE)); + expect(nestedTree).toBeDefined(); + + //Verify 'NotIn' disables value input and renders empty sub query + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, InConditionIndex + 1); // Select 'NotIn' operator. + QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, false, false); + nestedTree = fix.debugElement.query(By.css(QueryBuilderSelectors.QUERY_BUILDER_TREE)); + expect(nestedTree).toBeDefined(); + + const closeBtn = QueryBuilderFunctions.getQueryBuilderExpressionCloseButton(fix); + closeBtn.click(); + fix.detectChanges(); + } + })); + + it('Should correctly focus the search value input when editing the filtering expression', fakeAsync(() => { + //Create dateTime filtering expression + const tree = new FilteringExpressionsTree(FilteringLogic.And, null, 'Orders', ['OrderId']); + tree.filteringOperands.push({ + fieldName: 'OrderDate', + searchVal: new Date('2024-09-17T21:00:00.000Z'), + conditionName: 'equals', + condition: IgxDateFilteringOperand.instance().condition('equals') + }); + + queryBuilder.expressionTree = tree; + fix.detectChanges(); + + // Click the edit icon to enter edit mode of the expression. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); + tick(200); + fix.detectChanges(); + + //Check for the active element + const searchValueInput = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + expect(document.activeElement, 'The input should be the active element.').toBe(searchValueInput); + })); + + it('Should display add button when hovering a chip.', fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + + // Verify actions container is not visible. (This container contains the 'add' button.) + expect(QueryBuilderFunctions.getQueryBuilderTreeExpressionActionsContainer(fix, [0]), 'actions container is visible').toBeNull(); + + // Hover the first chip and verify actions container is visible. + UIInteractions.hoverElement(QueryBuilderFunctions.getQueryBuilderTreeItem(fix, [0]) as HTMLElement); + tick(50); + fix.detectChanges(); + expect(QueryBuilderFunctions.getQueryBuilderTreeExpressionActionsContainer(fix, [0])) + .not.toBeNull('actions container is not visible'); + + // Unhover the first chip and verify actions container is not visible. + UIInteractions.unhoverElement(QueryBuilderFunctions.getQueryBuilderTreeItem(fix, [0]) as HTMLElement); + tick(50); + fix.detectChanges(); + expect(QueryBuilderFunctions.getQueryBuilderTreeExpressionActionsContainer(fix, [0]), 'actions container is visible').toBeNull(); + })); + + it('Should have disabled adding buttons when an expression is in edit mode.', fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + + // Verify adding buttons are enabled + let buttons = QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtons(fix, 0); + for (const button of buttons) { + ControlsFunction.verifyButtonIsDisabled(button as HTMLElement, false); + } - // Change return field from preselected 'OrderId' to 'Id' - QueryBuilderFunctions.selectFieldsInEditModeExpression(fix, [0], 1); - tick(100); - fix.detectChanges(); + // Enter edit mode + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); + tick(50); + fix.detectChanges(); - commitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); - ControlsFunction.verifyButtonIsDisabled(commitBtn as HTMLElement, false); + // Verify adding buttons are not displayed + expect(QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtonsContainer(fix, 0)).toBe(undefined); - QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, false, true); // Parent commit button should be enabled - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); - fix.detectChanges(); + // Exit edit mode + const closeButton = QueryBuilderFunctions.getQueryBuilderExpressionCloseButton(fix); + UIInteractions.simulateClickEvent(closeButton); + tick(100); + fix.detectChanges(); - //Verify that expressionTree is correct - const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); - expect(exprTree).toBe(`{ + // Verify adding buttons are enabled + buttons = QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtons(fix, 0); + for (const button of buttons) { + ControlsFunction.verifyButtonIsDisabled(button as HTMLElement, false); + } + })); + + it('Clicking a condition should put it in edit mode.', fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + + // Click the existing chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); + tick(50); + fix.detectChanges(); + // Verify inputs values + QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, 'OrderId', 'Greater Than', '3'); + // Edit the operator + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Equals' operator. + // Commit the change + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); + fix.detectChanges(); + // Verify the chip + QueryBuilderFunctions.verifyExpressionChipContent(fix, [1], 'OrderId', 'Equals', '3'); + + // Verify that the nested query is not expanded + expect(fix.debugElement.query(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}--level-1`)).nativeElement.checkVisibility()).toBe(false); + + // Click the nested query chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); + tick(50); + fix.detectChanges(); + // Verify the query is expanded + expect(fix.debugElement.query(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}--level-1`)).nativeElement.checkVisibility()).toBe(true); + // Click a chip in the nested query three to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0], 1); + tick(50); + fix.detectChanges(); + // Verify inputs values + QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, 'ProductName', 'Contains', 'a', 1); + // Edit the operator + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 2, 1); // Select 'Starts With' operator. + // Commit the change + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix, 1); + fix.detectChanges(); + // Verify the chip + QueryBuilderFunctions.verifyExpressionChipContent(fix, [0], 'ProductName', 'Starts With', 'a', 1); + })); + + it('Should switch edit mode on click on chip on the same level.', fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); + tick(50); + fix.detectChanges(); + + // Click the existing chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0], 1); + tick(50); + fix.detectChanges(); + // Verify inputs values + QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, 'ProductName', 'Contains', 'a', 1); + + // Click the existing chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0], 1); + tick(50); + fix.detectChanges(); + // Verify inputs values + QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, 'Released', 'True', '', 1); + QueryBuilderFunctions.verifyExpressionChipContent(fix, [0], 'ProductName', 'Contains', 'a', 1); + })); + + it('Should exit edit mode on add, change group buttons, entity and fields select click.', fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + + // Click chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); + tick(50); + fix.detectChanges(); + + // Hover exprssion and click add button + UIInteractions.hoverElement(QueryBuilderFunctions.getQueryBuilderTreeItem(fix, [0]) as HTMLElement); + tick(50); + fix.detectChanges(); + (QueryBuilderFunctions.getQueryBuilderTreeExpressionIcon(fix, [0], 'add') as HTMLElement).click(); + tick(50); + fix.detectChanges(); + + expect(queryBuilder.queryTree.hasEditedExpression).toBe(false); + + // Click chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); + tick(50); + fix.detectChanges(); + + // Click change group button + QueryBuilderFunctions.clickQueryBuilderGroupContextMenu(fix, 0); + tick(100); + fix.detectChanges(); + + expect(queryBuilder.queryTree.hasEditedExpression).toBe(false); + + // Click chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); + tick(50); + fix.detectChanges(); + + // Click fields select + QueryBuilderFunctions.clickQueryBuilderFieldsCombo(fix); + fix.detectChanges(); + + expect(queryBuilder.queryTree.hasEditedExpression).toBe(false); + + // Click chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); + tick(50); + fix.detectChanges(); + + // Click entity select + QueryBuilderFunctions.clickQueryBuilderEntitySelect(fix); + fix.detectChanges(); + + expect(queryBuilder.queryTree.hasEditedExpression).toBe(false); + })); + + it('Should show add expression button when there is an expression in add mode.', fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + + // Hover expression and click add button + UIInteractions.hoverElement(QueryBuilderFunctions.getQueryBuilderTreeItem(fix, [0]) as HTMLElement); + tick(50); + fix.detectChanges(); + (QueryBuilderFunctions.getQueryBuilderTreeExpressionIcon(fix, [0], 'add') as HTMLElement).click(); + tick(50); + fix.detectChanges(); + + // Click 'add condition' option + QueryBuilderFunctions.clickQueryBuilderTreeAddOption(fix, 0); + + // Hover the first chip and verify actions container is visible. + UIInteractions.hoverElement(QueryBuilderFunctions.getQueryBuilderTreeItem(fix, [0]) as HTMLElement); + tick(50); + fix.detectChanges(); + expect(QueryBuilderFunctions.getQueryBuilderTreeExpressionActionsContainer(fix, [0])) + .not.toBeNull('actions container is not visible'); + + // Hover the second chip and verify actions container is visible. + UIInteractions.hoverElement(QueryBuilderFunctions.getQueryBuilderTreeItem(fix, [1]) as HTMLElement); + tick(50); + fix.detectChanges(); + expect(QueryBuilderFunctions.getQueryBuilderTreeExpressionActionsContainer(fix, [1])) + .not.toBeNull('actions container is not visible'); + })); + + it('Should display an alert dialog when the entity is changed and showEntityChangeDialog is true.', fakeAsync(() => { + const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER}`))[0].nativeElement; + const queryTreeElement = queryBuilderElement.querySelector(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}`); + const dialog = queryTreeElement.querySelector('igx-dialog'); + const dialogOutlet = document.querySelector('.igx-dialog__window'); + expect(dialog).toBeDefined(); + + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); + + // Alert dialog should not be opened if there is no previous selection + expect(dialog.checkVisibility()).toBe(false); + + // Select entity + QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1); + tick(100); + fix.detectChanges(); + + // Alert dialog should be opened + expect(dialog.checkVisibility()).toBe(true); + + // Show again checkbox should be unchecked + const checkbox = dialogOutlet.querySelector('igx-checkbox'); + expect(checkbox).toBeDefined(); + expect(checkbox.classList.contains('igx-checkbox--checked')).toBe(false); + expect(queryBuilder.showEntityChangeDialog).toBe(true); + + // Close dialog + const cancelButton = Array.from(dialogOutlet.querySelectorAll('button'))[0]; + cancelButton.click(); + tick(100); + fix.detectChanges(); + + // Select entity + QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1); + tick(100); + fix.detectChanges(); + + // Alert dialog should NOT be opened + expect(dialog.checkVisibility()).toBe(true); + })); + + it('Should not display an alert dialog when the entity changed once showEntityChangeDialog is disabled.', fakeAsync(() => { + const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER}`))[0].nativeElement; + const queryTreeElement = queryBuilderElement.querySelector(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}`); + const dialog = queryTreeElement.querySelector('igx-dialog'); + const dialogOutlet = document.querySelector('.igx-dialog__window'); + expect(dialog).toBeDefined(); + + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); + + // Alert dialog should not be opened if there is no previous selection + expect(dialog.checkVisibility()).toBe(false); + + // Select entity + QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1); + tick(100); + fix.detectChanges(); + + // Alert dialog should be opened + expect(dialog.checkVisibility()).toBe(true); + + // Check show again checkbox + const checkbox = dialogOutlet.querySelector('igx-checkbox') as HTMLElement; + expect(checkbox).toBeDefined(); + + checkbox.click(); + tick(100); + fix.detectChanges(); + expect(checkbox.classList.contains('igx-checkbox--checked')).toBe(true); + expect(queryBuilder.showEntityChangeDialog).toBe(false); + + // Close dialog + const cancelButton = Array.from(dialogOutlet.querySelectorAll('button'))[0]; + cancelButton.click(); + tick(100); + fix.detectChanges(); + + // Select entity + QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1); + tick(100); + fix.detectChanges(); + + // Alert dialog should NOT be opened + expect(dialog.checkVisibility()).toBe(false); + })); + + it('Initially should not display an alert dialog when the entity is changed if hideEntityChangeDialog is disabled through API.', fakeAsync(() => { + queryBuilder.showEntityChangeDialog = false; + const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER}`))[0].nativeElement; + const queryTreeElement = queryBuilderElement.querySelector(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}`); + const dialog = queryTreeElement.querySelector('igx-dialog'); + expect(dialog).toBeDefined(); + + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); + + // Alert dialog should not be opened if there is no previous selection + expect(dialog.checkVisibility()).toBe(false); + + // Select entity + QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1); + tick(100); + fix.detectChanges(); + + // Alert dialog should NOT be opened + expect(dialog.checkVisibility()).toBe(false); + })); + + it('Should reset all inputs when the entity is changed.', fakeAsync(() => { + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); + + //Select Column + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); + + //Select Operator + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); + + //Type Value + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + UIInteractions.clickAndSendInputElementValue(input, '1'); + tick(100); + fix.detectChanges(); + + // Verify all inputs values + QueryBuilderFunctions.verifyQueryEditModeExpressionInputValues(fix, 'Products', 'Id, ProductName, OrderId, Released', 'Id', 'Equals', '1'); + + // Commit the change + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); + + // Change the selected entity + QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1); + tick(100); + fix.detectChanges(); + + // Confirm the change + const dialogOutlet: HTMLElement = fix.debugElement.queryAll(By.css(`.igx-dialog`))[0].nativeElement; + const confirmButton = Array.from(dialogOutlet.querySelectorAll('button'))[1]; + expect(confirmButton.innerText).toEqual('Confirm'); + confirmButton.click(); + fix.detectChanges(); + + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); + tick(100); + fix.detectChanges(); + + // Verify all inputs + QueryBuilderFunctions.verifyQueryEditModeExpressionInputValues(fix, 'Orders', 'OrderId, OrderName, OrderDate, Delivered', '', '', ''); + })); + + it('Should NOT reset all inputs when the entity is not changed.', fakeAsync(() => { + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 0); + + //Select Column + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); + + //Select Operator + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); + + //Type Value + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + UIInteractions.clickAndSendInputElementValue(input, '1'); + tick(100); + fix.detectChanges(); + + // Verify all inputs values + QueryBuilderFunctions.verifyQueryEditModeExpressionInputValues(fix, 'Products', 'Id, ProductName, OrderId, Released', 'Id', 'Equals', '1'); + + // Commit the change + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); + + // Change the selected entity + QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1); + tick(100); + fix.detectChanges(); + + // Decline the change + const dialogOutlet: HTMLElement = fix.debugElement.queryAll(By.css(`.igx-dialog`))[0].nativeElement; + const cancelButton = Array.from(dialogOutlet.querySelectorAll('button'))[0]; + expect(cancelButton.innerText).toEqual('Cancel'); + cancelButton.click(); + tick(100); + fix.detectChanges(); + + // Verify all inputs + QueryBuilderFunctions.verifyQueryEditModeExpressionInputValues(fix, 'Products', 'Id, ProductName, OrderId, Released'); + QueryBuilderFunctions.verifyExpressionChipContent(fix, [0], 'Id', 'Equals', '1'); + })); + + it(`"commit" button should be enabled/disabled properly when editing an expression.`, fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + tick(100); + fix.detectChanges(); + + // Click the 'OrderId' chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); + tick(50); + fix.detectChanges(); + + // Verify "commit" button is enabled + let commitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); + ControlsFunction.verifyButtonIsDisabled(commitBtn as HTMLElement, false); + // Delete the value + let input = QueryBuilderFunctions.getQueryBuilderValueInput(fix, false).querySelector('input'); + UIInteractions.clickAndSendInputElementValue(input, ''); + tick(100); + fix.detectChanges(); + // Verify "commit" button is disabled + commitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); + ControlsFunction.verifyButtonIsDisabled(commitBtn as HTMLElement); + // Enter some value + input = QueryBuilderFunctions.getQueryBuilderValueInput(fix, false).querySelector('input'); + UIInteractions.clickAndSendInputElementValue(input, '5'); + tick(100); + fix.detectChanges(); + // Verify "commit" button is enabled + commitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); + ControlsFunction.verifyButtonIsDisabled(commitBtn as HTMLElement, false); + })); + + it(`Parent "commit" button should be enabled if a child condition is edited.`, fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + tick(100); + fix.detectChanges(); + + // Click the parent chip 'Products' to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); + tick(50); + fix.detectChanges(); + + // Click the child chip 'Released' to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1], 1); + tick(50); + fix.detectChanges(); + + // Change the 'Released' operator + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 2, 1); // Select 'False' operator. + + // Verify both parent and child commit buttons are enabled + let parentCommitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); + let childCommitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix, 1); + + ControlsFunction.verifyButtonIsDisabled(parentCommitBtn as HTMLElement, false); + ControlsFunction.verifyButtonIsDisabled(childCommitBtn as HTMLElement, false); + + // Commit the change + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix, 1); + + // Click the child chip 'ProductName' to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0], 1); + tick(50); + fix.detectChanges(); + + // Change the 'ProductName' column to 'Id' + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0, 1); + + // Verify input values + QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, 'Id', 'Equals', '', 1); + + // Verify parent and child commit buttons are disabled + parentCommitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); + childCommitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix, 1); + + ControlsFunction.verifyButtonIsDisabled(parentCommitBtn as HTMLElement, false); + ControlsFunction.verifyButtonIsDisabled(childCommitBtn as HTMLElement); + + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0, 1); + //Type Value + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix, false, 1).querySelector('input'); + UIInteractions.clickAndSendInputElementValue(input, '1'); + tick(100); + fix.detectChanges(); + + // Commit the child + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix, 1); + tick(50); + fix.detectChanges(); + + // Verify parent is enabled + parentCommitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); + ControlsFunction.verifyButtonIsDisabled(parentCommitBtn as HTMLElement, false); + })); + + it(`Clicking parent "commit" button should properly exit edit mode of inner query.`, fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + tick(100); + fix.detectChanges(); + + // Click the parent chip 'Products' to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); + tick(50); + fix.detectChanges(); + + // Click the child chip 'Released' to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1], 1); + tick(50); + fix.detectChanges(); + + // Change the 'Released' operator + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 2, 1); // Select 'False' operator. + + // Commit the change through the parent + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); + tick(50); + fix.detectChanges(); + + // Verify the changes in the child query are commited + let exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree.filteringOperands[0]); + expect(exprTree).toBe(`{"fieldName":"OrderId","condition":{"name":"inQuery","isUnary":false,"isNestedQuery":true,"iconName":"in"},"conditionName":"inQuery","searchVal":null,"searchTree":{"filteringOperands":[{"fieldName":"ProductName","condition":{"name":"contains","isUnary":false,"iconName":"filter_contains"},"conditionName":"contains","searchVal":"a"},{"fieldName":"Released","condition":{"name":"false","isUnary":true,"iconName":"filter_false"},"conditionName":"false","searchVal":null,"searchTree":null}],"operator":0,"entity":"Products","returnFields":["Id"]}}`); + // Enter edit mode again + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); + tick(50); + fix.detectChanges(); + + // Click the child chip 'ProductName' to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0], 1); + tick(50); + fix.detectChanges(); + + // Change the 'ProductName' column to 'Id' + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0, 1); + + // Verify input values + QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, 'Id', 'Equals', '', 1); + + // Verify parent and child commit buttons are disabled + const parentCommitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); + const childCommitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix, 1); + + ControlsFunction.verifyButtonIsDisabled(parentCommitBtn as HTMLElement, false); + ControlsFunction.verifyButtonIsDisabled(childCommitBtn as HTMLElement); + + // Commit the parent + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); + tick(50); + fix.detectChanges(); + + // Verify the changes in the child query are discarded + exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree.filteringOperands[0]); + expect(exprTree).toBe(`{"fieldName":"OrderId","condition":{"name":"inQuery","isUnary":false,"isNestedQuery":true,"iconName":"in"},"conditionName":"inQuery","searchVal":null,"searchTree":{"filteringOperands":[{"fieldName":"ProductName","condition":{"name":"contains","isUnary":false,"iconName":"filter_contains"},"conditionName":"contains","searchVal":"a"},{"fieldName":"Released","condition":{"name":"false","isUnary":true,"iconName":"filter_false"},"conditionName":"false","searchVal":null,"searchTree":null}],"operator":0,"entity":"Products","returnFields":["Id"]}}`); + })); + + it('Should collapse nested query when it is committed.', fakeAsync(() => { + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); + + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); // Select 'OrderId' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 10); // Select 'In' operator. + + QueryBuilderFunctions.addAndValidateChildGroup(fix, 1); + + // Verify that the nested query is expanded + expect(fix.debugElement.query(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}--level-1`)).nativeElement.checkVisibility()).toBe(true); + + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); + tick(100); + fix.detectChanges(); + + // Verify that the nested query is collapsed + expect(fix.debugElement.query(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}--level-1`)).nativeElement.checkVisibility()).toBe(false); + })); + + it(`Should discard the changes in the fields if 'close' button of nested query condition is clicked.`, fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + tick(100); + fix.detectChanges(); + // Verify parent chip expression + QueryBuilderFunctions.verifyExpressionChipContent(fix, [0], 'OrderId', 'In', 'Products / Id'); + + // Click the parent chip 'Products' to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); + tick(50); + fix.detectChanges(); + + // Select 'Product Name' fields + QueryBuilderFunctions.selectFieldsInEditModeExpression(fix, [1, 2], 1); + const closeBtn = QueryBuilderFunctions.getQueryBuilderExpressionCloseButton(fix); + closeBtn.click(); + tick(50); + fix.detectChanges(); + // Verify parent chip expression is not changed + QueryBuilderFunctions.verifyExpressionChipContent(fix, [0], 'OrderId', 'In', 'Products / Id'); + })); + + it('Should be able to open edit mode on click, close the edited condition on "close" button click and not commit it.', fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + tick(100); + fix.detectChanges(); + + //Enter edit mode + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); + tick(200); + fix.detectChanges(); + + const closeBtn = QueryBuilderFunctions.getQueryBuilderExpressionCloseButton(fix); + + // Verify the enabled/disabled state of each input of the expression in edit mode. + QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, true, true); + + // Verify the edit inputs values. + QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, 'OrderId', 'Greater Than', '3'); + + //edit condition fields + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); // Select 'OrderName' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); // Select 'Contains' operator. + const value = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + UIInteractions.clickAndSendInputElementValue(value, '5'); + tick(200); + fix.detectChanges(); + + //cancel edit + closeBtn.click(); + tick(); + fix.detectChanges(); + + //Verify changes are reverted + QueryBuilderFunctions.verifyExpressionChipContent(fix, [1], 'OrderId', 'Greater Than', '3'); + })); + + it(`Should focus edited expression chip after click on the 'commit'/'discard' button.`, fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + tick(100); + fix.detectChanges(); + + // Click the 'OrderId' chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); + tick(100); + fix.detectChanges(); + + // Click on the 'commit' button + const commitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); + commitBtn.click(); + fix.detectChanges(); + tick(100); + fix.detectChanges(); + // Verify focused chip + QueryBuilderFunctions.verifyFocusedChip('OrderId', 'Greater Than', '3'); + + // Click the 'OrderId' chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); + tick(100); + fix.detectChanges(); + + // Click on the 'discard' button + const closeBtn = QueryBuilderFunctions.getQueryBuilderExpressionCloseButton(fix); + closeBtn.click(); + fix.detectChanges(); + tick(100); + fix.detectChanges(); + // Verify focused chip + QueryBuilderFunctions.verifyFocusedChip('OrderId', 'Greater Than', '3'); + })); + + it(`Should focus proper expression chip after switching edit mode and click on the 'commit'/'discard' button.`, fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + tick(100); + fix.detectChanges(); + + // Click the 'OrderDate' chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [2]); + tick(100); + fix.detectChanges(); + + // Click the 'OrderId' chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); + tick(100); + fix.detectChanges(); + + // Click on the 'commit' button + const commitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); + commitBtn.click(); + fix.detectChanges(); + tick(100); + fix.detectChanges(); + // Verify focused chip + QueryBuilderFunctions.verifyFocusedChip('OrderId', 'Greater Than', '3'); + })); + + it('Should focus added through group add buttons expression chip if it is commited.', fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + tick(100); + fix.detectChanges(); + + const group = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement; + + // Add new 'expression'. + const buttonsContainer = Array.from(group.querySelectorAll('.igx-filter-tree__buttons'))[1]; + const buttons = Array.from(buttonsContainer.querySelectorAll('button')); + (buttons[0] as HTMLElement).click(); + tick(); + fix.detectChanges(); + + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 3); // Select 'Delivered' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 1); // Select 'True' operator. + tick(100); + fix.detectChanges(); + + // Click on the 'commit' button + const commitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); + commitBtn.click(); + fix.detectChanges(); + tick(300); + fix.detectChanges(); + + // Verify focused chip + QueryBuilderFunctions.verifyFocusedChip('Delivered', 'True'); + })); + + it('Should NOT focus an expression chip if added expression is discarded.', fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + tick(100); + fix.detectChanges(); + + const group = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement; + + // Add new 'expression'. + const buttonsContainer = Array.from(group.querySelectorAll('.igx-filter-tree__buttons'))[1]; + const buttons = Array.from(buttonsContainer.querySelectorAll('button')); + (buttons[0] as HTMLElement).click(); + tick(); + fix.detectChanges(); + + // Click on the 'close' button + const closeBtn = QueryBuilderFunctions.getQueryBuilderExpressionCloseButton(fix); + closeBtn.click(); + fix.detectChanges(); + tick(300); + fix.detectChanges(); + + // Verify chip is not focused + expect(document.activeElement.tagName).toEqual('BODY'); + })); + + it('Should not make bug where existing inner query is leaking to a newly created one.', fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + tick(100); + fix.detectChanges(); + + const group = QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement; + + // Add new 'expression'. + const buttonsContainer = Array.from(group.querySelectorAll('.igx-filter-tree__buttons'))[1]; + const buttons = Array.from(buttonsContainer.querySelectorAll('button')); + (buttons[0] as HTMLElement).click(); + tick(); + fix.detectChanges(); + + // Add condition with 'in' operator to open inner query + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); // Select 'OrderName' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 10); // Select 'Contains' operator. + tick(100); + fix.detectChanges(); + + //New empty inner query should be displayed + const queryBuilderElement: HTMLElement = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER}`))[0].nativeElement; + const bodyElement = queryBuilderElement.children[0].children[0]; + const actionArea = bodyElement.children[0].querySelector('.igx-query-builder__root-actions'); + expect(actionArea).toBeNull(); + expect(bodyElement.children[1].children[1].children[1].children[1].children[6].children[1].classList.contains(QueryBuilderSelectors.QUERY_BUILDER_TREE)).toBe(true); + expect(bodyElement.children[1].children[1].children[1].children[1].children[6].children[1].children.length).toEqual(3); + const tree = bodyElement.children[1].children[1].children[1].children[1].children[6].children[1].querySelector('.igx-filter-tree__expression'); + expect(tree).toBeNull(); + })); + + it('canCommit should return the correct validity state of currently edited condition.', fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + + // Click the existing chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); + tick(50); + fix.detectChanges(); + expect(queryBuilder.canCommit()).toBe(true); + + // Verify the Query Builder validity state while editing a condition. + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); + expect(queryBuilder.canCommit()).toBe(false); + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); + expect(queryBuilder.canCommit()).toBe(false); + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + UIInteractions.clickAndSendInputElementValue(input, 'a'); + tick(100); + fix.detectChanges(); + expect(queryBuilder.canCommit()).toBe(true); + })); + + it('canCommit should return the correct validity state of currently added condition.', fakeAsync(() => { + // Verify the Query Builder validity state while adding a condition. + QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1); // Select 'Orders' entity + tick(100); + fix.detectChanges(); + expect(queryBuilder.canCommit(), 'Entity selected').toBe(true); + + // Click the 'Add condition' button. + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); + tick(100); + fix.detectChanges(); + expect(queryBuilder.canCommit(), 'Add condition clicked').toBe(true); + + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); + expect(queryBuilder.canCommit(), 'Column selected').toBe(false); + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); + expect(queryBuilder.canCommit(), 'Operator contains selected').toBe(false); + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + UIInteractions.clickAndSendInputElementValue(input, 'a'); + tick(100); + fix.detectChanges(); + expect(queryBuilder.canCommit(), 'Search value filled').toBe(true); + + // Click on the 'cancel' button + const closeButton = QueryBuilderFunctions.getQueryBuilderExpressionCloseButton(fix); + UIInteractions.simulateClickEvent(closeButton); + tick(100); + fix.detectChanges(); + expect(queryBuilder.canCommit(), 'Entity remains selected').toBe(true); + + // Verify the Query Builder validity state for UNARY condition. + QueryBuilderFunctions.clickQueryBuilderInitialAddConditionBtn(fix, 0); + tick(100); + fix.detectChanges(); + expect(queryBuilder.canCommit(), 'Add condition clicked again').toBe(true); + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 3); + expect(queryBuilder.canCommit(), 'Column selected again').toBe(true); + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 1); + expect(queryBuilder.canCommit(), 'Unary operator selected').toBe(true); + })); + + it('Should be able to commit nested query without where condition.', fakeAsync(() => { + QueryBuilderFunctions.selectEntityAndClickInitialAddCondition(fix, 1); + + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0); // Select 'OrderId' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 10); // Select 'In' operator. + + let commitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); + ControlsFunction.verifyButtonIsDisabled(commitBtn as HTMLElement, true); + + // Enter values in the nested query + QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 0, 1); // Select 'Products' entity + tick(100); + fix.detectChanges(); + + // Change return field from preselected 'OrderId' to 'Id' + QueryBuilderFunctions.selectFieldsInEditModeExpression(fix, [0], 1); + tick(100); + fix.detectChanges(); + + commitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); + ControlsFunction.verifyButtonIsDisabled(commitBtn as HTMLElement, false); + + QueryBuilderFunctions.verifyEditModeExpressionInputStates(fix, true, true, false, true); // Parent commit button should be enabled + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fix); + fix.detectChanges(); + + //Verify that expressionTree is correct + const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); + expect(exprTree).toBe(`{ "filteringOperands": [ { "fieldName": "OrderId", @@ -1950,425 +1957,425 @@ describe('IgxQueryBuilder', () => { "Delivered" ] }`); - })); - - it(`Should be able to enter edit mode from condition in an inner query.`, fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); - tick(100); - fix.detectChanges(); - - // Click the child chip 'Released' to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1], 1); - tick(50); - fix.detectChanges(); + })); + + it(`Should be able to enter edit mode from condition in an inner query.`, fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); - // Verify both parent and child commit buttons are enabled - const parentCommitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); - const childCommitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix, 1); - - ControlsFunction.verifyButtonIsDisabled(parentCommitBtn as HTMLElement, false); - ControlsFunction.verifyButtonIsDisabled(childCommitBtn as HTMLElement, false); - - // Verify inputs values on both levels - QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, 'OrderId', 'In', '', 0); - QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, 'Released', 'True', '', 1); - })); - - it(`Should be able to switch group condition and ungroup from group context menu.`, fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTreeWithSubGroup(); - fix.detectChanges(); - - // Verify there is one subgroup - expect(queryBuilder.expressionTree.filteringOperands.filter(o => o instanceof FilteringExpressionsTree).length).toBe(1); - - // Verify the operator of the subgroup is an 'And' line. - QueryBuilderFunctions.verifyOperatorLine(QueryBuilderFunctions.getQueryBuilderTreeRootGroupOperatorLine(fix) as HTMLElement, 'and'); - QueryBuilderFunctions.verifyOperatorLine(QueryBuilderFunctions.getQueryBuilderTreeGroupOperatorLine(fix, [0]) as HTMLElement, 'or'); - - // Click the 'OR' subgroup button - QueryBuilderFunctions.clickQueryBuilderGroupContextMenu(fix, 2); - tick(100); - fix.detectChanges(); - - // Click the 'Switch to AND' drop down item - QueryBuilderFunctions.clickContextMenuItem(fix, 0); - tick(100); - fix.detectChanges(); - - // Verify the operator of the subgroup is an 'And' line. - QueryBuilderFunctions.verifyOperatorLine(QueryBuilderFunctions.getQueryBuilderTreeGroupOperatorLine(fix, [0]) as HTMLElement, 'and'); - - // Click the 'AND' subgroup button - QueryBuilderFunctions.clickQueryBuilderGroupContextMenu(fix, 2); - tick(100); - fix.detectChanges(); - - // Click the 'Ungroup' drop down item - QueryBuilderFunctions.clickContextMenuItem(fix, 1); - tick(100); - fix.detectChanges(); - - // Verify there are no subgroups anymore - expect(queryBuilder.expressionTree.filteringOperands.filter(o => o instanceof FilteringExpressionsTree).length).toBe(0); - })); - - it('Should disable changing a selected entity when "disableEntityChange"=true', () => { - queryBuilder.disableEntityChange = true; - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTreeWithSubGroup(); - fix.detectChanges(); - - const selectEntity = QueryBuilderFunctions.getQueryBuilderEntitySelect(fix, 0); - expect(selectEntity.children[0].classList.contains('igx-input-group--disabled')).toBeTrue(); + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); + tick(100); + fix.detectChanges(); + + // Click the child chip 'Released' to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1], 1); + tick(50); + fix.detectChanges(); + + // Verify both parent and child commit buttons are enabled + const parentCommitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix); + const childCommitBtn = QueryBuilderFunctions.getQueryBuilderExpressionCommitButton(fix, 1); + + ControlsFunction.verifyButtonIsDisabled(parentCommitBtn as HTMLElement, false); + ControlsFunction.verifyButtonIsDisabled(childCommitBtn as HTMLElement, false); + + // Verify inputs values on both levels + QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, 'OrderId', 'In', '', 0); + QueryBuilderFunctions.verifyEditModeExpressionInputValues(fix, 'Released', 'True', '', 1); + })); + + it(`Should be able to switch group condition and ungroup from group context menu.`, fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTreeWithSubGroup(); + fix.detectChanges(); + + // Verify there is one subgroup + expect(queryBuilder.expressionTree.filteringOperands.filter(o => o instanceof FilteringExpressionsTree).length).toBe(1); + + // Verify the operator of the subgroup is an 'And' line. + QueryBuilderFunctions.verifyOperatorLine(QueryBuilderFunctions.getQueryBuilderTreeRootGroupOperatorLine(fix) as HTMLElement, 'and'); + QueryBuilderFunctions.verifyOperatorLine(QueryBuilderFunctions.getQueryBuilderTreeGroupOperatorLine(fix, [0]) as HTMLElement, 'or'); + + // Click the 'OR' subgroup button + QueryBuilderFunctions.clickQueryBuilderGroupContextMenu(fix, 2); + tick(100); + fix.detectChanges(); + + // Click the 'Switch to AND' drop down item + QueryBuilderFunctions.clickContextMenuItem(fix, 0); + tick(100); + fix.detectChanges(); + + // Verify the operator of the subgroup is an 'And' line. + QueryBuilderFunctions.verifyOperatorLine(QueryBuilderFunctions.getQueryBuilderTreeGroupOperatorLine(fix, [0]) as HTMLElement, 'and'); + + // Click the 'AND' subgroup button + QueryBuilderFunctions.clickQueryBuilderGroupContextMenu(fix, 2); + tick(100); + fix.detectChanges(); + + // Click the 'Ungroup' drop down item + QueryBuilderFunctions.clickContextMenuItem(fix, 1); + tick(100); + fix.detectChanges(); + + // Verify there are no subgroups anymore + expect(queryBuilder.expressionTree.filteringOperands.filter(o => o instanceof FilteringExpressionsTree).length).toBe(0); + })); + + it('Should disable changing a selected entity when "disableEntityChange"=true', () => { + queryBuilder.disableEntityChange = true; + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTreeWithSubGroup(); + fix.detectChanges(); + + const selectEntity = QueryBuilderFunctions.getQueryBuilderEntitySelect(fix, 0); + expect(selectEntity.children[0].classList.contains('igx-input-group--disabled')).toBe(true); + }); + + it('Should disable changing a selected entity when "disableEntityChange"=true only after initial selection', fakeAsync(() => { + queryBuilder.disableEntityChange = true; + fix.detectChanges(); + + const selectEntity = QueryBuilderFunctions.getQueryBuilderEntitySelect(fix, 0); + expect(selectEntity.children[0].classList.contains('igx-input-group--disabled')).toBe(false); + QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 0, 0); + + expect(selectEntity.children[0].classList.contains('igx-input-group--disabled')).toBe(true); + })); + + it('Should disable changing the selected fields when "disableReturnFieldsChange"=true', () => { + queryBuilder.disableReturnFieldsChange = true; + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTreeWithSubGroup(); + fix.detectChanges(); + + const fieldsCombo = QueryBuilderFunctions.getQueryBuilderFieldsCombo(fix, 0); + expect(fieldsCombo.children[0].classList.contains('igx-input-group--disabled')).toBe(true); + }); + + it(`Should show 'Ungroup' as disabled in root group context menu.`, fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTreeWithSubGroup(); + fix.detectChanges(); + + // Click the 'AND' root group button + QueryBuilderFunctions.clickQueryBuilderGroupContextMenu(fix, 0); + tick(100); + fix.detectChanges(); + + // Verify 'Ungroup' is disabled + QueryBuilderFunctions.verifyContextMenuItemDisabled(fix, 1, true); + + // Click the 'OR' subgroup button + QueryBuilderFunctions.clickQueryBuilderGroupContextMenu(fix, 2); + tick(100); + fix.detectChanges(); + + // Verify 'Ungroup' is enabled + QueryBuilderFunctions.verifyContextMenuItemDisabled(fix, 1, false); + })); }); - it('Should disable changing a selected entity when "disableEntityChange"=true only after initial selection', fakeAsync(() => { - queryBuilder.disableEntityChange = true; - fix.detectChanges(); - - const selectEntity = QueryBuilderFunctions.getQueryBuilderEntitySelect(fix, 0); - expect(selectEntity.children[0].classList.contains('igx-input-group--disabled')).toBeFalse(); - QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 0, 0); - - expect(selectEntity.children[0].classList.contains('igx-input-group--disabled')).toBeTrue(); - })); - - it('Should disable changing the selected fields when "disableReturnFieldsChange"=true', () => { - queryBuilder.disableReturnFieldsChange = true; - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTreeWithSubGroup(); - fix.detectChanges(); + describe('API', () => { + beforeEach(fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + + vi.spyOn(queryBuilder.expressionTreeChange, 'emit'); + })); + + it(`Should commit the changes in a valid edited condition when the 'commit' method is called.`, fakeAsync(() => { + // Click the existing chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); + tick(50); + fix.detectChanges(); + + // Change the current condition + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); + expect(queryBuilder.canCommit()).toBe(false); + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); + expect(queryBuilder.canCommit()).toBe(false); + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + UIInteractions.clickAndSendInputElementValue(input, 'a'); + tick(100); + fix.detectChanges(); + + // Apply the changes + queryBuilder.commit(); + tick(100); + fix.detectChanges(); + + // Verify expression is commited + QueryBuilderFunctions.verifyExpressionChipContent(fix, [1], 'OrderName', 'Contains', 'a'); + + // Verify event is not fired + expect(queryBuilder.expressionTreeChange.emit).toHaveBeenCalledTimes(0); + })); + + it(`Should discard the changes in a valid edited condition when the 'discard' method is called.`, fakeAsync(() => { + // Click the existing chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); + tick(50); + fix.detectChanges(); + + // Change the current condition + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); + expect(queryBuilder.canCommit()).toBe(false); + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); + expect(queryBuilder.canCommit()).toBe(false); + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); + UIInteractions.clickAndSendInputElementValue(input, 'a'); + tick(100); + fix.detectChanges(); + + // Discard the changes + queryBuilder.discard(); + tick(100); + fix.detectChanges(); + + // Verify expression is not commited + QueryBuilderFunctions.verifyExpressionChipContent(fix, [1], 'OrderId', 'Greater Than', '3'); + + // Verify event is not fired + expect(queryBuilder.expressionTreeChange.emit).toHaveBeenCalledTimes(0); + })); + + it('Should properly commit/discard changes in nested query.', fakeAsync(() => { + // Click the existing chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); + tick(50); + fix.detectChanges(); + expect(queryBuilder.canCommit()).toBe(true); + + // Start editing expression in the nested query + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1], 1); + tick(50); + fix.detectChanges(); + expect(queryBuilder.canCommit()).toBe(true); + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0, 1); + expect(queryBuilder.canCommit()).toBe(false); + + // Discard the changes + queryBuilder.discard(); + tick(100); + fix.detectChanges(); + + // Verify the nested query is collapsed + expect(fix.debugElement.query(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}--level-1`)).nativeElement.checkVisibility()).toBe(false); + + // Click the existing chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); + tick(50); + fix.detectChanges(); + + // Start editing expression in the nested query + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0], 1); + tick(50); + fix.detectChanges(); + expect(queryBuilder.canCommit()).toBe(true); + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0, 1); + expect(queryBuilder.canCommit()).toBe(false); + QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0, 1); + expect(queryBuilder.canCommit()).toBe(false); + const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix, false, 1).querySelector('input'); + UIInteractions.clickAndSendInputElementValue(input, '1'); + tick(100); + fix.detectChanges(); + expect(queryBuilder.canCommit()).toBe(true); + + // Apply the changes + queryBuilder.commit(); + tick(100); + fix.detectChanges(); + + // Verify the nested query is collapsed + expect(fix.debugElement.query(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}--level-1`)).nativeElement.checkVisibility()).toBe(false); + + // Expand the nested query by putting it in edit mode + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); + tick(50); + fix.detectChanges(); + + // Verify edited expressions + QueryBuilderFunctions.verifyExpressionChipContent(fix, [0], 'Id', 'Equals', '1', 1); + QueryBuilderFunctions.verifyExpressionChipContent(fix, [1], 'Released', 'True', undefined, 1); + + // close chip + queryBuilder.discard(); + tick(100); + fix.detectChanges(); + + // Click the existing chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); + tick(50); + fix.detectChanges(); + + QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1, 1); + tick(100); + fix.detectChanges(); + + // Confirm the change + const dialogOutlet: HTMLElement = fix.debugElement.queryAll(By.css(`.igx-dialog`))[0].nativeElement; + const confirmButton = Array.from(dialogOutlet.querySelectorAll('button'))[1]; + expect(confirmButton.innerText).toEqual('Confirm'); + confirmButton.click(); + tick(100); + fix.detectChanges(); + + // Discard the changes + queryBuilder.discard(); + tick(100); + fix.detectChanges(); + + // Expand the nested query by putting it in edit mode + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); + tick(50); + fix.detectChanges(); + + // Verify edited expressions + QueryBuilderFunctions.verifyExpressionChipContent(fix, [0], 'Id', 'Equals', '1', 1); + QueryBuilderFunctions.verifyExpressionChipContent(fix, [1], 'Released', 'True', undefined, 1); + })); + + it('Should NOT throw errors when an invalid condition is committed through API.', fakeAsync(() => { + vi.spyOn(console, 'error'); + // Click the existing chip to enter edit mode. + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [2]); + tick(50); + fix.detectChanges(); + + // Change the current condition + QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); + expect(queryBuilder.canCommit()).toBe(false); + + let errMessage = ''; + // Apply the changes + try { + queryBuilder.commit(); + tick(100); + fix.detectChanges(); + } catch (err) { + errMessage = err.message; + } - const fieldsCombo = QueryBuilderFunctions.getQueryBuilderFieldsCombo(fix, 0); - expect(fieldsCombo.children[0].classList.contains('igx-input-group--disabled')).toBeTrue(); + expect(errMessage).toBe("Expression tree can't be committed in the current state. Use `canCommit` method to check if the current state is valid."); + })); }); - it(`Should show 'Ungroup' as disabled in root group context menu.`, fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTreeWithSubGroup(); - fix.detectChanges(); - - // Click the 'AND' root group button - QueryBuilderFunctions.clickQueryBuilderGroupContextMenu(fix, 0); - tick(100); - fix.detectChanges(); - - // Verify 'Ungroup' is disabled - QueryBuilderFunctions.verifyContextMenuItemDisabled(fix, 1, true); - - // Click the 'OR' subgroup button - QueryBuilderFunctions.clickQueryBuilderGroupContextMenu(fix, 2); - tick(100); - fix.detectChanges(); - - // Verify 'Ungroup' is enabled - QueryBuilderFunctions.verifyContextMenuItemDisabled(fix, 1, false); - })); - }); - - describe('API', () => { - beforeEach(fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - - spyOn(queryBuilder.expressionTreeChange, 'emit').and.callThrough(); - })); - - it(`Should commit the changes in a valid edited condition when the 'commit' method is called.`, fakeAsync(() => { - // Click the existing chip to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); - tick(50); - fix.detectChanges(); - - // Change the current condition - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); - expect(queryBuilder.canCommit()).toBeFalse(); - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); - expect(queryBuilder.canCommit()).toBeFalse(); - const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, 'a'); - tick(100); - fix.detectChanges(); - - // Apply the changes - queryBuilder.commit(); - tick(100); - fix.detectChanges(); - - // Verify expression is commited - QueryBuilderFunctions.verifyExpressionChipContent(fix, [1], 'OrderName', 'Contains', 'a'); - - // Verify event is not fired - expect(queryBuilder.expressionTreeChange.emit).toHaveBeenCalledTimes(0); - })); + describe('Keyboard navigation', () => { + it('Should navigate with Tab/Shift+Tab through entity and fields inputs, chips, their respective drop & delete icons and operator drop-down button', fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); - it(`Should discard the changes in a valid edited condition when the 'discard' method is called.`, fakeAsync(() => { - // Click the existing chip to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1]); - tick(50); - fix.detectChanges(); - - // Change the current condition - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); - expect(queryBuilder.canCommit()).toBeFalse(); - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0); - expect(queryBuilder.canCommit()).toBeFalse(); - const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, 'a'); - tick(100); - fix.detectChanges(); - - // Discard the changes - queryBuilder.discard(); - tick(100); - fix.detectChanges(); - - // Verify expression is not commited - QueryBuilderFunctions.verifyExpressionChipContent(fix, [1], 'OrderId', 'Greater Than', '3'); - - // Verify event is not fired - expect(queryBuilder.expressionTreeChange.emit).toHaveBeenCalledTimes(0); - })); + QueryBuilderFunctions.verifyQueryBuilderTabbableElements(fix); + })); - it('Should properly commit/discard changes in nested query.', fakeAsync(() => { - // Click the existing chip to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); - tick(50); - fix.detectChanges(); - expect(queryBuilder.canCommit()).toBeTrue(); - - // Start editing expression in the nested query - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [1], 1); - tick(50); - fix.detectChanges(); - expect(queryBuilder.canCommit()).toBeTrue(); - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0, 1); - expect(queryBuilder.canCommit()).toBeFalse(); - - // Discard the changes - queryBuilder.discard(); - tick(100); - fix.detectChanges(); - - // Verify the nested query is collapsed - expect(fix.debugElement.query(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}--level-1`)).nativeElement.checkVisibility()).toBeFalse(); - - // Click the existing chip to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); - tick(50); - fix.detectChanges(); - - // Start editing expression in the nested query - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0], 1); - tick(50); - fix.detectChanges(); - expect(queryBuilder.canCommit()).toBeTrue(); - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 0, 1); - expect(queryBuilder.canCommit()).toBeFalse(); - QueryBuilderFunctions.selectOperatorInEditModeExpression(fix, 0, 1); - expect(queryBuilder.canCommit()).toBeFalse(); - const input = QueryBuilderFunctions.getQueryBuilderValueInput(fix, false, 1).querySelector('input'); - UIInteractions.clickAndSendInputElementValue(input, '1'); - tick(100); - fix.detectChanges(); - expect(queryBuilder.canCommit()).toBeTrue(); - - // Apply the changes - queryBuilder.commit(); - tick(100); - fix.detectChanges(); - - // Verify the nested query is collapsed - expect(fix.debugElement.query(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_TREE}--level-1`)).nativeElement.checkVisibility()).toBeFalse(); - - // Expand the nested query by putting it in edit mode - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); - tick(50); - fix.detectChanges(); - - // Verify edited expressions - QueryBuilderFunctions.verifyExpressionChipContent(fix, [0], 'Id', 'Equals', '1', 1); - QueryBuilderFunctions.verifyExpressionChipContent(fix, [1], 'Released', 'True', undefined, 1); - - // close chip - queryBuilder.discard(); - tick(100); - fix.detectChanges(); - - // Click the existing chip to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); - tick(50); - fix.detectChanges(); - - QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1, 1); - tick(100); - fix.detectChanges(); - - // Confirm the change - const dialogOutlet: HTMLElement = fix.debugElement.queryAll(By.css(`.igx-dialog`))[0].nativeElement; - const confirmButton = Array.from(dialogOutlet.querySelectorAll('button'))[1]; - expect(confirmButton.innerText).toEqual('Confirm'); - confirmButton.click(); - tick(100); - fix.detectChanges(); - - // Discard the changes - queryBuilder.discard(); - tick(100); - fix.detectChanges(); - - // Expand the nested query by putting it in edit mode - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [0]); - tick(50); - fix.detectChanges(); - - // Verify edited expressions - QueryBuilderFunctions.verifyExpressionChipContent(fix, [0], 'Id', 'Equals', '1', 1); - QueryBuilderFunctions.verifyExpressionChipContent(fix, [1], 'Released', 'True', undefined, 1); - })); + it('Should navigate with Tab/Shift+Tab through chips" "edit", "cancel" buttons, fields of a condition in edit mode.', fakeAsync(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); - it('Should NOT throw errors when an invalid condition is committed through API.', fakeAsync(() => { - spyOn(console, 'error'); - // Click the existing chip to enter edit mode. - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fix, [2]); - tick(50); - fix.detectChanges(); - - // Change the current condition - QueryBuilderFunctions.selectColumnInEditModeExpression(fix, 1); - expect(queryBuilder.canCommit()).toBeFalse(); - - let errMessage = ''; - // Apply the changes - try { - queryBuilder.commit(); - tick(100); - fix.detectChanges(); - } catch (err) { - errMessage = err.message; - } + const chip = fix.debugElement.queryAll(By.directive(IgxChipComponent))[0]; - expect(errMessage).toBe("Expression tree can't be committed in the current state. Use `canCommit` method to check if the current state is valid."); - })); - }); + QueryBuilderFunctions.hitKeyUponElementAndDetectChanges(fix, ' ', chip.nativeElement, 200); - describe('Keyboard navigation', () => { - it('Should navigate with Tab/Shift+Tab through entity and fields inputs, chips, their respective drop & delete icons and operator drop-down button', fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); + // const chipActions = fix.debugElement.query(By.css('.igx-filter-tree__expression-actions')); + // QueryBuilderFunctions.verifyTabbableChipActions(chipActions); - QueryBuilderFunctions.verifyQueryBuilderTabbableElements(fix); - })); - - it('Should navigate with Tab/Shift+Tab through chips" "edit", "cancel" buttons, fields of a condition in edit mode.', fakeAsync(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - - const chip = fix.debugElement.queryAll(By.directive(IgxChipComponent))[0]; + // // Open Edit mode and check condition line elements + // QueryBuilderFunctions.hitKeyUponElementAndDetectChanges(fix, ' ', chipActions.children[0].nativeElement, 200); - QueryBuilderFunctions.hitKeyUponElementAndDetectChanges(fix, ' ', chip.nativeElement, 200); + const editLine = fix.debugElement.queryAll(By.css('.igx-filter-tree__inputs'))[1]; + QueryBuilderFunctions.verifyTabbableConditionEditLineElements(editLine); - // const chipActions = fix.debugElement.query(By.css('.igx-filter-tree__expression-actions')); - // QueryBuilderFunctions.verifyTabbableChipActions(chipActions); + const editDialog = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_BODY}`))[1]; + QueryBuilderFunctions.verifyTabbableInConditionDialogElements(editDialog); + })); - // // Open Edit mode and check condition line elements - // QueryBuilderFunctions.hitKeyUponElementAndDetectChanges(fix, ' ', chipActions.children[0].nativeElement, 200); - - const editLine = fix.debugElement.queryAll(By.css('.igx-filter-tree__inputs'))[1]; - QueryBuilderFunctions.verifyTabbableConditionEditLineElements(editLine); - - const editDialog = fix.debugElement.queryAll(By.css(`.${QueryBuilderSelectors.QUERY_BUILDER_BODY}`))[1]; - QueryBuilderFunctions.verifyTabbableInConditionDialogElements(editDialog); - })); + it('Should start editing a condition when pressing \'Enter\' on its respective chip.', fakeAsync(() => { + //!Both Enter and Space should work + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); - it('Should start editing a condition when pressing \'Enter\' on its respective chip.', fakeAsync(() => { - //!Both Enter and Space should work - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); + const chip = fix.debugElement.queryAll(By.directive(IgxChipComponent))[0]; - const chip = fix.debugElement.queryAll(By.directive(IgxChipComponent))[0]; + QueryBuilderFunctions.hitKeyUponElementAndDetectChanges(fix, ' ', chip.nativeElement, 200); - QueryBuilderFunctions.hitKeyUponElementAndDetectChanges(fix, ' ', chip.nativeElement, 200); + let editLine = fix.debugElement.queryAll(By.css('.igx-filter-tree__inputs'))[1]; + QueryBuilderFunctions.verifyTabbableConditionEditLineElements(editLine); - let editLine = fix.debugElement.queryAll(By.css('.igx-filter-tree__inputs'))[1]; - QueryBuilderFunctions.verifyTabbableConditionEditLineElements(editLine); + // Discard the changes + queryBuilder.discard(); + tick(100); + fix.detectChanges(); - // Discard the changes - queryBuilder.discard(); - tick(100); - fix.detectChanges(); + QueryBuilderFunctions.hitKeyUponElementAndDetectChanges(fix, 'Enter', chip.nativeElement, 200); - QueryBuilderFunctions.hitKeyUponElementAndDetectChanges(fix, 'Enter', chip.nativeElement, 200); + editLine = fix.debugElement.queryAll(By.css('.igx-filter-tree__inputs'))[1]; + QueryBuilderFunctions.verifyTabbableConditionEditLineElements(editLine); + })); - editLine = fix.debugElement.queryAll(By.css('.igx-filter-tree__inputs'))[1]; - QueryBuilderFunctions.verifyTabbableConditionEditLineElements(editLine); - })); + it('Should remove a chip in when pressing \'Enter\' on its \'remove\' icon.', fakeAsync(() => { + //!Both Enter and Space should work + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); - it('Should remove a chip in when pressing \'Enter\' on its \'remove\' icon.', fakeAsync(() => { - //!Both Enter and Space should work - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - - // Verify there are three chip expressions. - QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 3, 6); - - // Press 'Enter' on the remove icon of the second chip. - const chip = QueryBuilderFunctions.getQueryBuilderTreeExpressionChip(fix, [1]); - const removeIcon = ControlsFunction.getChipRemoveButton(chip as HTMLElement); - QueryBuilderFunctions.hitKeyUponElementAndDetectChanges(fix, 'Enter', removeIcon); - QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 2, 5); - - // Press 'Space' on the remove icon of the second chip. - const chip2 = QueryBuilderFunctions.getQueryBuilderTreeExpressionChip(fix, [0]); - const removeIcon2 = ControlsFunction.getChipRemoveButton(chip2 as HTMLElement); - QueryBuilderFunctions.hitKeyUponElementAndDetectChanges(fix, ' ', removeIcon2); - QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 1, 1); - })); - }); + // Verify there are three chip expressions. + QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 3, 6); - describe('Templates', () => { - let fixture: ComponentFixture; - beforeEach(fakeAsync(() => { - fixture = TestBed.createComponent(IgxQueryBuilderCustomTemplateSampleTestComponent); - fixture.detectChanges(); - queryBuilder = fixture.componentInstance.queryBuilder; - })); + // Press 'Enter' on the remove icon of the second chip. + const chip = QueryBuilderFunctions.getQueryBuilderTreeExpressionChip(fix, [1]); + const removeIcon = ControlsFunction.getChipRemoveButton(chip as HTMLElement); + QueryBuilderFunctions.hitKeyUponElementAndDetectChanges(fix, 'Enter', removeIcon); + QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 2, 5); - it('Should render custom header properly.', () => { - expect(QueryBuilderFunctions.getQueryBuilderHeaderText(fixture)).toBe('Custom Title'); + // Press 'Space' on the remove icon of the second chip. + const chip2 = QueryBuilderFunctions.getQueryBuilderTreeExpressionChip(fix, [0]); + const removeIcon2 = ControlsFunction.getChipRemoveButton(chip2 as HTMLElement); + QueryBuilderFunctions.hitKeyUponElementAndDetectChanges(fix, ' ', removeIcon2); + QueryBuilderFunctions.verifyRootAndSubGroupExpressionsCount(fix, 1, 1); + })); }); - it('Should render custom input template properly.', fakeAsync(() => { - //Enter edit mode - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fixture, [0]); - tick(200); - fixture.detectChanges(); - - const editModeContainer = QueryBuilderFunctions.getQueryBuilderEditModeContainer(fixture, false); - const input = editModeContainer.querySelector('input.custom-class') as HTMLInputElement; - const selectedField = editModeContainer.querySelector('p.selectedField') as HTMLInputElement; - const selectedCondition = editModeContainer.querySelector('p.selectedCondition') as HTMLInputElement; - - expect(input).toBeDefined(); - expect(input.value).toBe('3'); - expect(selectedField).toBeDefined(); - expect(selectedField.innerText).toBe('OrderId'); - expect(selectedCondition).toBeDefined(); - expect(selectedCondition.innerText).toBe('greaterThan'); - - //Edit input value - UIInteractions.clickAndSendInputElementValue(input, '5'); - tick(100); - fixture.detectChanges(); - - // Commit the populated expression. - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fixture); - tick(100); - fixture.detectChanges(); - - //Verify that expressionTree is correct - const exprTree = JSON.stringify(fixture.componentInstance.queryBuilder.expressionTree, null, 2); - expect(exprTree).toBe(`{ + describe('Templates', () => { + let fixture: ComponentFixture; + beforeEach(fakeAsync(() => { + fixture = TestBed.createComponent(IgxQueryBuilderCustomTemplateSampleTestComponent); + fixture.detectChanges(); + queryBuilder = fixture.componentInstance.queryBuilder; + })); + + it('Should render custom header properly.', () => { + expect(QueryBuilderFunctions.getQueryBuilderHeaderText(fixture)).toBe('Custom Title'); + }); + + it('Should render custom input template properly.', fakeAsync(() => { + //Enter edit mode + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fixture, [0]); + tick(200); + fixture.detectChanges(); + + const editModeContainer = QueryBuilderFunctions.getQueryBuilderEditModeContainer(fixture, false); + const input = editModeContainer.querySelector('input.custom-class') as HTMLInputElement; + const selectedField = editModeContainer.querySelector('p.selectedField') as HTMLInputElement; + const selectedCondition = editModeContainer.querySelector('p.selectedCondition') as HTMLInputElement; + + expect(input).toBeDefined(); + expect(input.value).toBe('3'); + expect(selectedField).toBeDefined(); + expect(selectedField.innerText).toBe('OrderId'); + expect(selectedCondition).toBeDefined(); + expect(selectedCondition.innerText).toBe('greaterThan'); + + //Edit input value + UIInteractions.clickAndSendInputElementValue(input, '5'); + tick(100); + fixture.detectChanges(); + + // Commit the populated expression. + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fixture); + tick(100); + fixture.detectChanges(); + + //Verify that expressionTree is correct + const exprTree = JSON.stringify(fixture.componentInstance.queryBuilder.expressionTree, null, 2); + expect(exprTree).toBe(`{ "filteringOperands": [ { "fieldName": "OrderId", @@ -2392,385 +2399,385 @@ describe('IgxQueryBuilder', () => { "Delivered" ] }`); - })); - - it('Should apply field formatter properly.', fakeAsync(() => { - // Add new expression - const btn = QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtons(fixture, 0)[0] as HTMLElement; - btn.click(); - fixture.detectChanges(); - - // Populate edit inputs. - QueryBuilderFunctions.selectColumnInEditModeExpression(fixture, 0); // Select 'OrderId' column. - QueryBuilderFunctions.selectOperatorInEditModeExpression(fixture, 0); // Select 'Equals' operator. - - // Verify combo template is displayed - let editModeContainer = Array.from(QueryBuilderFunctions.getQueryBuilderExpressionsContainer(fixture).querySelectorAll('.igx-filter-tree__inputs'))[1]; - let combo = editModeContainer.querySelector('.igx-combo'); - expect(combo).toBeDefined(); - - // Open the combo - (combo.querySelector('igx-input-group') as HTMLElement).click(); - tick(); - fixture.detectChanges(); - // Select item - const outlet = Array.from(document.querySelectorAll(`.igx-drop-down__list-scroll`)) - .filter(item => (item as HTMLElement).checkVisibility())[0] as HTMLElement; - - const comboItem = outlet.querySelectorAll(`.igx-drop-down__item`)[0] as HTMLElement; - comboItem.click(); - tick(); - fixture.detectChanges(); - - // Commit the expression - QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fixture); - fixture.detectChanges(); - // Verify chips - QueryBuilderFunctions.verifyExpressionChipContent(fixture, [0], 'OrderId', 'Greater Than', '3'); - QueryBuilderFunctions.verifyExpressionChipContent(fixture, [1], 'OrderId', 'Equals', '0'); - - // Enter edit mode - QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fixture, [1]); - tick(50); - fixture.detectChanges(); - // Verify inputs values - editModeContainer = Array.from(QueryBuilderFunctions.getQueryBuilderExpressionsContainer(fixture).querySelectorAll('.igx-filter-tree__inputs'))[1]; - const selects = Array.from(editModeContainer.querySelectorAll('igx-select')); - combo = editModeContainer.querySelector('.igx-combo'); - expect(selects[0].querySelector('input').value).toBe('OrderId'); - expect(selects[1].querySelector('input').value).toBe('Equals'); - expect(combo.querySelector('input').value).toBe('A'); - })); - }); - - describe('Localization', () => { - it('Should correctly change resource strings for Query Builder.', fakeAsync(() => { - queryBuilder.resourceStrings = Object.assign({}, queryBuilder.resourceStrings, { - igx_query_builder_filter_operator_and: 'My and', - igx_query_builder_filter_operator_or: 'My or', - igx_query_builder_and_label: 'My and', - igx_query_builder_or_label: 'My or', - igx_query_builder_switch_group: 'My switch to {0}', - igx_query_builder_add_condition_root: 'My condition', - igx_query_builder_add_group_root: 'My group', - igx_query_builder_ungroup: 'My ungroup', - igx_query_builder_dialog_title: 'My Confirmation', - igx_query_builder_dialog_message: 'My changing entity message', - igx_query_builder_dialog_checkbox_text: 'My do not show this dialog again', - igx_query_builder_dialog_cancel: 'My Cancel', - igx_query_builder_dialog_confirm: 'My Confirm', - igx_query_builder_drop_ghost_text: 'My Drop here to insert' - }); - fix.detectChanges(); - - // Select 'Orders' entity - QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1); - tick(100); - fix.detectChanges(); - - expect((QueryBuilderFunctions.getQueryBuilderInitialAddConditionBtn(fix, 0) as HTMLElement).querySelector('span').innerText) - .toBe('My condition'); - - // Click the 'My and' group button - QueryBuilderFunctions.clickQueryBuilderGroupContextMenu(fix); - tick(100); - fix.detectChanges(); - - expect((QueryBuilderFunctions.getQueryBuilderGroupContextMenuDropDownItems(fix)[0]).querySelector('span').innerText) - .toBe('My switch to MY OR'); - expect((QueryBuilderFunctions.getQueryBuilderGroupContextMenuDropDownItems(fix)[1]).querySelector('span').innerText) - .toBe('My ungroup'); - - // Show changing entity alert dialog - QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 0); - tick(100); - fix.detectChanges(); - const dialogOutlet = document.querySelector('.igx-dialog__window'); - expect(dialogOutlet).toBeDefined(); - - expect(dialogOutlet.querySelector('.igx-dialog__window-title').textContent.trim()).toBe('My Confirmation'); - expect(dialogOutlet.querySelector('.igx-query-builder-dialog').children[0].textContent.trim()).toBe('My changing entity message'); - expect(dialogOutlet.querySelector('.igx-query-builder-dialog').children[1].textContent.trim()).toBe('My do not show this dialog again'); - expect(dialogOutlet.querySelector('.igx-dialog__window-actions').children[0].textContent.trim()).toBe('My Cancel'); - expect(dialogOutlet.querySelector('.igx-dialog__window-actions').children[1].textContent.trim()).toBe('My Confirm'); - - //Drag ghost text check - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - fix.detectChanges(); - const draggedChip = fix.debugElement.queryAll(By.directive(IgxChipComponent))[3].componentInstance; - UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 10, 10, false); - const dropGhost = QueryBuilderFunctions.getDropGhost(fix) as HTMLElement; - expect(draggedChip.dragDirective.ghostElement).toBeTruthy(); - expect(dropGhost).toBeDefined(); - expect(dropGhost.innerText).toBe('My Drop here to insert'); - })); - }); - - describe('Drag and drop', () => { - const ROW_HEIGHT = 40; - const DROP_CONDITION_HERE = "Drop here to insert"; - let chipComponents = []; - beforeEach(() => { - queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTreeWithSubGroup(); - fix.detectChanges(); - - chipComponents = fix.debugElement.queryAll(By.directive(IgxChipComponent)); - }); - - it('Should render ghost when mouse drag operation starts.', () => { - const draggedChip = chipComponents[1].componentInstance; - - UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 100, 10, false); - const dropGhost = QueryBuilderFunctions.getDropGhost(fix) as HTMLElement; - - expect(draggedChip.dragDirective.ghostElement).toBeTruthy(); - expect(dropGhost).toBeDefined(); - expect(dropGhost.innerText).toBe(DROP_CONDITION_HERE); + })); + + it('Should apply field formatter properly.', fakeAsync(() => { + // Add new expression + const btn = QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtons(fixture, 0)[0] as HTMLElement; + btn.click(); + fixture.detectChanges(); + + // Populate edit inputs. + QueryBuilderFunctions.selectColumnInEditModeExpression(fixture, 0); // Select 'OrderId' column. + QueryBuilderFunctions.selectOperatorInEditModeExpression(fixture, 0); // Select 'Equals' operator. + + // Verify combo template is displayed + let editModeContainer = Array.from(QueryBuilderFunctions.getQueryBuilderExpressionsContainer(fixture).querySelectorAll('.igx-filter-tree__inputs'))[1]; + let combo = editModeContainer.querySelector('.igx-combo'); + expect(combo).toBeDefined(); + + // Open the combo + (combo.querySelector('igx-input-group') as HTMLElement).click(); + tick(); + fixture.detectChanges(); + // Select item + const outlet = Array.from(document.querySelectorAll(`.igx-drop-down__list-scroll`)) + .filter(item => (item as HTMLElement).checkVisibility())[0] as HTMLElement; + + const comboItem = outlet.querySelectorAll(`.igx-drop-down__item`)[0] as HTMLElement; + comboItem.click(); + tick(); + fixture.detectChanges(); + + // Commit the expression + QueryBuilderFunctions.clickQueryBuilderExpressionCommitButton(fixture); + fixture.detectChanges(); + // Verify chips + QueryBuilderFunctions.verifyExpressionChipContent(fixture, [0], 'OrderId', 'Greater Than', '3'); + QueryBuilderFunctions.verifyExpressionChipContent(fixture, [1], 'OrderId', 'Equals', '0'); + + // Enter edit mode + QueryBuilderFunctions.clickQueryBuilderTreeExpressionChip(fixture, [1]); + tick(50); + fixture.detectChanges(); + // Verify inputs values + editModeContainer = Array.from(QueryBuilderFunctions.getQueryBuilderExpressionsContainer(fixture).querySelectorAll('.igx-filter-tree__inputs'))[1]; + const selects = Array.from(editModeContainer.querySelectorAll('igx-select')); + combo = editModeContainer.querySelector('.igx-combo'); + expect(selects[0].querySelector('input').value).toBe('OrderId'); + expect(selects[1].querySelector('input').value).toBe('Equals'); + expect(combo.querySelector('input').value).toBe('A'); + })); }); - it('Should collapse the condition when mouse drag operation starts.', () => { - const secondChip = chipComponents[1].componentInstance; - - UIInteractions.moveDragDirective(fix, secondChip.dragDirective, 100, 10, false); - expect(chipComponents[1].nativeElement.getBoundingClientRect().height).toBe(0); - }); - - it('Should render drop ghost properly when mouse dragged down on the left.', fakeAsync(() => { - const draggedChip = chipComponents[1].componentInstance; - QueryBuilderFunctions.verifyGhostPositionOnMouseDrag(fix, draggedChip, 100, 75, true); - })); - - it('Should render drop ghost properly when mouse dragged up on the left.', fakeAsync(() => { - const draggedChip = chipComponents[1].componentInstance; - QueryBuilderFunctions.verifyGhostPositionOnMouseDrag(fix, draggedChip, 100, 75 + 350, false); - })); - - it('Should render drop ghost properly when mouse dragged down on the right.', fakeAsync(() => { - const draggedChip = chipComponents[1].componentInstance; - QueryBuilderFunctions.verifyGhostPositionOnMouseDrag(fix, draggedChip, 500, 75, true); - })); - - it('Should render drop ghost properly when mouse dragged up on the right.', fakeAsync(() => { - const draggedChip = chipComponents[1].componentInstance; - QueryBuilderFunctions.verifyGhostPositionOnMouseDrag(fix, draggedChip, 500, 75 + 350, false); - })); - - it('Should position drop ghost below the target condition on dragging down.', () => { - const draggedChip = chipComponents[0].componentInstance; - const draggedChipCenter = QueryBuilderFunctions.getElementCenter(draggedChip.chipArea.nativeElement); - const dragDir = draggedChip.dragDirective; - - //pickup chip - dragDir.onPointerDown({ pointerId: 1, pageX: draggedChipCenter.X, pageY: draggedChipCenter.Y }); - fix.detectChanges(); - - //trigger ghost - QueryBuilderFunctions.dragMove(dragDir, draggedChipCenter.X, draggedChipCenter.Y + 10); - fix.detectChanges(); - - const dropGhost = QueryBuilderFunctions.getDropGhost(fix); - - expect(dropGhost).not.toBe(null); - const dropGhostBounds = dropGhost.getBoundingClientRect(); - const targetChipBounds = chipComponents[1].nativeElement.getBoundingClientRect(); - expect(dropGhostBounds.x).toBe(targetChipBounds.x); - expect(dropGhostBounds.y).toBeCloseTo(targetChipBounds.y + ROW_HEIGHT); - }); - - it('Should position drop ghost above the target condition on dragging up.', fakeAsync(() => { - const draggedChip = chipComponents[1].componentInstance; - const draggedChipCenter = QueryBuilderFunctions.getElementCenter(draggedChip.chipArea.nativeElement); - const dragDir = draggedChip.dragDirective; - - //pickup chip - dragDir.onPointerDown({ pointerId: 1, pageX: draggedChipCenter.X, pageY: draggedChipCenter.Y }); - fix.detectChanges(); - - //trigger ghost - QueryBuilderFunctions.dragMove(dragDir, draggedChipCenter.X, draggedChipCenter.Y - 30); - tick(50); - fix.detectChanges(); - - const dropGhost = QueryBuilderFunctions.getDropGhost(fix); - - expect(dropGhost).not.toBe(null); - const dropGhostBounds = dropGhost.getBoundingClientRect(); - const targetChipBounds = chipComponents[0].nativeElement.getBoundingClientRect(); - expect(dropGhostBounds.x).toBe(targetChipBounds.x); - expect(dropGhostBounds.y).toBeCloseTo(targetChipBounds.y + ROW_HEIGHT); - })); - - it('Should position drop ghost at the top inside the inner group when dragged over the first inner level condition.', () => { - const secondChip = chipComponents[0].componentInstance; - const secondChipElem = secondChip.chipArea.nativeElement; - - const dragDir = secondChip.dragDirective; - UIInteractions.moveDragDirective(fix, dragDir, 100, 4 * secondChipElem.offsetHeight, false); - - const dropGhostBounds = QueryBuilderFunctions.getDropGhostBounds(fix); - const targetChipBounds = chipComponents[4].nativeElement.getBoundingClientRect(); - expect(dropGhostBounds.x).toBe(targetChipBounds.x); - expect(dropGhostBounds.y).toBeCloseTo(targetChipBounds.y + ROW_HEIGHT); - }); - - it('Should position drop ghost outside the inner group aligned with the outer level conditions when the top inner level condition is dragged up.', () => { - const draggedChip = chipComponents[4].componentInstance; // "OrderName Ends With a" chip - const draggedChipCenter = QueryBuilderFunctions.getElementCenter(draggedChip.chipArea.nativeElement); - const dragDir = draggedChip.dragDirective; - - //pickup chip - dragDir.onPointerDown({ pointerId: 1, pageX: draggedChipCenter.X, pageY: draggedChipCenter.Y }); - fix.detectChanges(); - - //drag - QueryBuilderFunctions.dragMove(dragDir, draggedChipCenter.X, draggedChipCenter.Y - 2 * ROW_HEIGHT, false); - fix.detectChanges(); - - const dropGhostBounds = QueryBuilderFunctions.getDropGhostBounds(fix); - const targetChipBounds = chipComponents[1].nativeElement.getBoundingClientRect(); // "OrderId in Products/OrderId" chip - expect(dropGhostBounds.x).toBe(targetChipBounds.x); - expect(dropGhostBounds.y).toBeCloseTo(targetChipBounds.y + ROW_HEIGHT); - }); - - // TODO: Currently doesn't work as expected. The drop ghost is not shown on the first action. - xit('Should position drop ghost below the inner group aligned with the outer level conditions when the bottom inner level condition is dragged down.', () => { - const draggedChip = chipComponents[5].componentInstance; // "OrderDate Today" chip - const dragDir = draggedChip.dragDirective; - UIInteractions.moveDragDirective(fix, dragDir, -50, 10, false); - - const dropGhostBounds = QueryBuilderFunctions.getDropGhostBounds(fix); - const previousLevelChipBounds = chipComponents[1].nativeElement.getBoundingClientRect(); // "OrderId in Products/OrderId" chip - expect(dropGhostBounds.x).toBe(previousLevelChipBounds.x); - const innerGroupElement = QueryBuilderFunctions.getQueryBuilderTreeChildGroups(QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement)[0]; - const innerGroupBounds = innerGroupElement.getBoundingClientRect(); - expect(Math.abs(dropGhostBounds.top - innerGroupBounds.bottom)).toBeLessThan(20); - }); - - it('Should hide drop ghost on dragging the mouse far down outside the query builder.', () => { - const draggedChip = chipComponents[0].componentInstance; - const draggedChipElem = draggedChip.chipArea.nativeElement; - - UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 0, 10 * draggedChipElem.offsetHeight, false); - - const dropGhost = QueryBuilderFunctions.getDropGhost(fix); - expect(dropGhost).toBe(null); - expect(QueryBuilderFunctions.getVisibleChips(fix).length).toBe(3); + describe('Localization', () => { + it('Should correctly change resource strings for Query Builder.', fakeAsync(() => { + queryBuilder.resourceStrings = Object.assign({}, queryBuilder.resourceStrings, { + igx_query_builder_filter_operator_and: 'My and', + igx_query_builder_filter_operator_or: 'My or', + igx_query_builder_and_label: 'My and', + igx_query_builder_or_label: 'My or', + igx_query_builder_switch_group: 'My switch to {0}', + igx_query_builder_add_condition_root: 'My condition', + igx_query_builder_add_group_root: 'My group', + igx_query_builder_ungroup: 'My ungroup', + igx_query_builder_dialog_title: 'My Confirmation', + igx_query_builder_dialog_message: 'My changing entity message', + igx_query_builder_dialog_checkbox_text: 'My do not show this dialog again', + igx_query_builder_dialog_cancel: 'My Cancel', + igx_query_builder_dialog_confirm: 'My Confirm', + igx_query_builder_drop_ghost_text: 'My Drop here to insert' + }); + fix.detectChanges(); + + // Select 'Orders' entity + QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 1); + tick(100); + fix.detectChanges(); + + expect((QueryBuilderFunctions.getQueryBuilderInitialAddConditionBtn(fix, 0) as HTMLElement).querySelector('span').innerText) + .toBe('My condition'); + + // Click the 'My and' group button + QueryBuilderFunctions.clickQueryBuilderGroupContextMenu(fix); + tick(100); + fix.detectChanges(); + + expect((QueryBuilderFunctions.getQueryBuilderGroupContextMenuDropDownItems(fix)[0]).querySelector('span').innerText) + .toBe('My switch to MY OR'); + expect((QueryBuilderFunctions.getQueryBuilderGroupContextMenuDropDownItems(fix)[1]).querySelector('span').innerText) + .toBe('My ungroup'); + + // Show changing entity alert dialog + QueryBuilderFunctions.selectEntityInEditModeExpression(fix, 0); + tick(100); + fix.detectChanges(); + const dialogOutlet = document.querySelector('.igx-dialog__window'); + expect(dialogOutlet).toBeDefined(); + + expect(dialogOutlet.querySelector('.igx-dialog__window-title').textContent.trim()).toBe('My Confirmation'); + expect(dialogOutlet.querySelector('.igx-query-builder-dialog').children[0].textContent.trim()).toBe('My changing entity message'); + expect(dialogOutlet.querySelector('.igx-query-builder-dialog').children[1].textContent.trim()).toBe('My do not show this dialog again'); + expect(dialogOutlet.querySelector('.igx-dialog__window-actions').children[0].textContent.trim()).toBe('My Cancel'); + expect(dialogOutlet.querySelector('.igx-dialog__window-actions').children[1].textContent.trim()).toBe('My Confirm'); + + //Drag ghost text check + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + fix.detectChanges(); + const draggedChip = fix.debugElement.queryAll(By.directive(IgxChipComponent))[3].componentInstance; + UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 10, 10, false); + const dropGhost = QueryBuilderFunctions.getDropGhost(fix) as HTMLElement; + expect(draggedChip.dragDirective.ghostElement).toBeTruthy(); + expect(dropGhost).toBeDefined(); + expect(dropGhost.innerText).toBe('My Drop here to insert'); + })); }); - it('Should drop the condition above the target condition on dragging up.', fakeAsync(() => { - const secondChip = chipComponents[1].componentInstance; // "OrderId In Products/ OrderId" chip - - expect(QueryBuilderFunctions.getChipContent(chipComponents[0].nativeElement)).toBe("OrderName Equals foo"); - const draggedChipCenter = QueryBuilderFunctions.getElementCenter(secondChip.chipArea.nativeElement); - const dragDir = secondChip.dragDirective; + describe('Drag and drop', () => { + const ROW_HEIGHT = 40; + const DROP_CONDITION_HERE = "Drop here to insert"; + let chipComponents = []; + beforeEach(() => { + queryBuilder.expressionTree = QueryBuilderFunctions.generateExpressionTreeWithSubGroup(); + fix.detectChanges(); - //pickup chip - dragDir.onPointerDown({ pointerId: 1, pageX: draggedChipCenter.X, pageY: draggedChipCenter.Y }); - fix.detectChanges(); + chipComponents = fix.debugElement.queryAll(By.directive(IgxChipComponent)); + }); - //trigger ghost - QueryBuilderFunctions.dragMove(dragDir, draggedChipCenter.X + 50, draggedChipCenter.Y - 50); - fix.detectChanges(); + it('Should render ghost when mouse drag operation starts.', () => { + const draggedChip = chipComponents[1].componentInstance; - //drag - QueryBuilderFunctions.dragMove(dragDir, draggedChipCenter.X + 50, draggedChipCenter.Y - 50, true); - fix.detectChanges(); + UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 100, 10, false); + const dropGhost = QueryBuilderFunctions.getDropGhost(fix) as HTMLElement; - chipComponents = QueryBuilderFunctions.getVisibleChips(fix); - expect(QueryBuilderFunctions.getChipContent(chipComponents[0].nativeElement)).toBe("OrderId In Products / OrderId"); - expect(QueryBuilderFunctions.getChipContent(chipComponents[1].nativeElement)).toBe("OrderName Equals foo"); - })); - - it('Should drop the condition below the target condition on dragging down.', fakeAsync(() => { - const secondChip = chipComponents[0].componentInstance; // "OrderName Equals foo" chip - const secondChipElem = secondChip.nativeElement; - - expect(QueryBuilderFunctions.getChipContent(chipComponents[0].nativeElement)).toBe("OrderName Equals foo"); - - UIInteractions.moveDragDirective(fix, secondChip.dragDirective, 0, secondChipElem.offsetHeight, true); - tick(50); - fix.detectChanges(); - QueryBuilderFunctions.verifyFocusedChip('OrderName', 'Equals', 'foo'); - - chipComponents = QueryBuilderFunctions.getVisibleChips(fix); - expect(QueryBuilderFunctions.getChipContent(chipComponents[0].nativeElement)).toBe("OrderId In Products / OrderId"); - expect(QueryBuilderFunctions.getChipContent(chipComponents[1].nativeElement)).toBe("OrderName Equals foo"); - })); - - it('Should drop the condition inside the inner group when dropped over the group.', fakeAsync(() => { - const draggedChip = chipComponents[0].componentInstance; // "OrderName Equals foo" chip - const draggedChipElem = draggedChip.nativeElement; - - const dragDir = draggedChip.dragDirective; - UIInteractions.moveDragDirective(fix, dragDir, 50, 2 * draggedChipElem.offsetHeight + 25, true); - tick(50); - fix.detectChanges(); - QueryBuilderFunctions.verifyFocusedChip('OrderName', 'Equals', 'foo'); - - chipComponents = QueryBuilderFunctions.getVisibleChips(fix); - const droppedChipBounds = chipComponents[1].nativeElement.getBoundingClientRect(); - const targetChipBounds = chipComponents[2].nativeElement.getBoundingClientRect(); - expect(droppedChipBounds.x).toBe(targetChipBounds.x); - expect(droppedChipBounds.y).toBeCloseTo(targetChipBounds.y - ROW_HEIGHT); - - expect(QueryBuilderFunctions.getChipContent(chipComponents[0].nativeElement)).toBe("OrderId In Products / OrderId"); - expect(QueryBuilderFunctions.getChipContent(chipComponents[1].nativeElement)).toBe("OrderName Equals foo"); - })); - - it('Should drop the condition outside the inner group aligned with the outer level conditions when dropped above the inner group.', fakeAsync(() => { - const draggedChip = chipComponents[5].componentInstance; // "OrderDate Today" chip - const draggedChipElem = draggedChip.nativeElement; - - UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 0, -3.5 * draggedChipElem.offsetHeight, true); - tick(50); - fix.detectChanges(); - QueryBuilderFunctions.verifyFocusedChip('OrderDate', 'Today'); - - chipComponents = QueryBuilderFunctions.getVisibleChips(fix); - const droppedChipBounds = chipComponents[2].nativeElement.getBoundingClientRect(); - const targetChipBounds = chipComponents[1].nativeElement.getBoundingClientRect(); // "OrderId in Products/OrderId" chip - expect(droppedChipBounds.x).toBe(targetChipBounds.x); - expect(droppedChipBounds.y).toBeCloseTo(targetChipBounds.y + ROW_HEIGHT); - - expect(QueryBuilderFunctions.getChipContent(chipComponents[0].nativeElement)).toBe("OrderName Equals foo"); - expect(QueryBuilderFunctions.getChipContent(chipComponents[1].nativeElement)).toBe("OrderId In Products / OrderId"); - expect(QueryBuilderFunctions.getChipContent(chipComponents[2].nativeElement)).toBe("OrderDate Today"); - })); - - it('Should drop the condition at the last position of the root group when dropped above the buttons.', fakeAsync(() => { - const draggedChip = chipComponents[5].componentInstance; // "OrderDate Today" chip - const draggedChipCenter = QueryBuilderFunctions.getElementCenter(draggedChip.chipArea.nativeElement); - const dragDir = draggedChip.dragDirective; - - //pickup chip - dragDir.onPointerDown({ pointerId: 1, pageX: draggedChipCenter.X, pageY: draggedChipCenter.Y }); - fix.detectChanges(); - - //trigger ghost - QueryBuilderFunctions.dragMove(dragDir, draggedChipCenter.X + 10, draggedChipCenter.Y + 10); - fix.detectChanges(); - - spyOn(dragDir.ghostElement, 'dispatchEvent').and.callThrough(); - - const addConditionButton = QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtons(fix, 0)[0] as HTMLElement; - const addConditionButtonCenter = QueryBuilderFunctions.getElementCenter(addConditionButton); - - //move over +Condition - QueryBuilderFunctions.dragMove(dragDir, addConditionButtonCenter.X, addConditionButtonCenter.Y); - fix.detectChanges(); - - const dropGhost = QueryBuilderFunctions.getDropGhost(fix) as HTMLElement; - chipComponents = QueryBuilderFunctions.getVisibleChips(fix); - expect(QueryBuilderFunctions.getElementCenter(dropGhost).Y).toBeGreaterThan(QueryBuilderFunctions.getElementCenter(chipComponents[2].nativeElement).Y) - expect(QueryBuilderFunctions.getElementCenter(dropGhost).Y).toBeLessThan(QueryBuilderFunctions.getElementCenter(addConditionButton).Y) - - //drop condition - dragDir.onPointerUp({ pointerId: 1, pageX: addConditionButtonCenter.X, pageY: addConditionButtonCenter.Y }); - tick(20); - fix.detectChanges(); - - const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); - expect(exprTree).toBe(`{ + expect(draggedChip.dragDirective.ghostElement).toBeTruthy(); + expect(dropGhost).toBeDefined(); + expect(dropGhost.innerText).toBe(DROP_CONDITION_HERE); + }); + + it('Should collapse the condition when mouse drag operation starts.', () => { + const secondChip = chipComponents[1].componentInstance; + + UIInteractions.moveDragDirective(fix, secondChip.dragDirective, 100, 10, false); + expect(chipComponents[1].nativeElement.getBoundingClientRect().height).toBe(0); + }); + + it('Should render drop ghost properly when mouse dragged down on the left.', fakeAsync(() => { + const draggedChip = chipComponents[1].componentInstance; + QueryBuilderFunctions.verifyGhostPositionOnMouseDrag(fix, draggedChip, 100, 75, true); + })); + + it('Should render drop ghost properly when mouse dragged up on the left.', fakeAsync(() => { + const draggedChip = chipComponents[1].componentInstance; + QueryBuilderFunctions.verifyGhostPositionOnMouseDrag(fix, draggedChip, 100, 75 + 350, false); + })); + + it('Should render drop ghost properly when mouse dragged down on the right.', fakeAsync(() => { + const draggedChip = chipComponents[1].componentInstance; + QueryBuilderFunctions.verifyGhostPositionOnMouseDrag(fix, draggedChip, 500, 75, true); + })); + + it('Should render drop ghost properly when mouse dragged up on the right.', fakeAsync(() => { + const draggedChip = chipComponents[1].componentInstance; + QueryBuilderFunctions.verifyGhostPositionOnMouseDrag(fix, draggedChip, 500, 75 + 350, false); + })); + + it('Should position drop ghost below the target condition on dragging down.', () => { + const draggedChip = chipComponents[0].componentInstance; + const draggedChipCenter = QueryBuilderFunctions.getElementCenter(draggedChip.chipArea.nativeElement); + const dragDir = draggedChip.dragDirective; + + //pickup chip + dragDir.onPointerDown({ pointerId: 1, pageX: draggedChipCenter.X, pageY: draggedChipCenter.Y }); + fix.detectChanges(); + + //trigger ghost + QueryBuilderFunctions.dragMove(dragDir, draggedChipCenter.X, draggedChipCenter.Y + 10); + fix.detectChanges(); + + const dropGhost = QueryBuilderFunctions.getDropGhost(fix); + + expect(dropGhost).not.toBe(null); + const dropGhostBounds = dropGhost.getBoundingClientRect(); + const targetChipBounds = chipComponents[1].nativeElement.getBoundingClientRect(); + expect(dropGhostBounds.x).toBe(targetChipBounds.x); + expect(dropGhostBounds.y).toBeCloseTo(targetChipBounds.y + ROW_HEIGHT); + }); + + it('Should position drop ghost above the target condition on dragging up.', fakeAsync(() => { + const draggedChip = chipComponents[1].componentInstance; + const draggedChipCenter = QueryBuilderFunctions.getElementCenter(draggedChip.chipArea.nativeElement); + const dragDir = draggedChip.dragDirective; + + //pickup chip + dragDir.onPointerDown({ pointerId: 1, pageX: draggedChipCenter.X, pageY: draggedChipCenter.Y }); + fix.detectChanges(); + + //trigger ghost + QueryBuilderFunctions.dragMove(dragDir, draggedChipCenter.X, draggedChipCenter.Y - 30); + tick(50); + fix.detectChanges(); + + const dropGhost = QueryBuilderFunctions.getDropGhost(fix); + + expect(dropGhost).not.toBe(null); + const dropGhostBounds = dropGhost.getBoundingClientRect(); + const targetChipBounds = chipComponents[0].nativeElement.getBoundingClientRect(); + expect(dropGhostBounds.x).toBe(targetChipBounds.x); + expect(dropGhostBounds.y).toBeCloseTo(targetChipBounds.y + ROW_HEIGHT); + })); + + it('Should position drop ghost at the top inside the inner group when dragged over the first inner level condition.', () => { + const secondChip = chipComponents[0].componentInstance; + const secondChipElem = secondChip.chipArea.nativeElement; + + const dragDir = secondChip.dragDirective; + UIInteractions.moveDragDirective(fix, dragDir, 100, 4 * secondChipElem.offsetHeight, false); + + const dropGhostBounds = QueryBuilderFunctions.getDropGhostBounds(fix); + const targetChipBounds = chipComponents[4].nativeElement.getBoundingClientRect(); + expect(dropGhostBounds.x).toBe(targetChipBounds.x); + expect(dropGhostBounds.y).toBeCloseTo(targetChipBounds.y + ROW_HEIGHT); + }); + + it('Should position drop ghost outside the inner group aligned with the outer level conditions when the top inner level condition is dragged up.', () => { + const draggedChip = chipComponents[4].componentInstance; // "OrderName Ends With a" chip + const draggedChipCenter = QueryBuilderFunctions.getElementCenter(draggedChip.chipArea.nativeElement); + const dragDir = draggedChip.dragDirective; + + //pickup chip + dragDir.onPointerDown({ pointerId: 1, pageX: draggedChipCenter.X, pageY: draggedChipCenter.Y }); + fix.detectChanges(); + + //drag + QueryBuilderFunctions.dragMove(dragDir, draggedChipCenter.X, draggedChipCenter.Y - 2 * ROW_HEIGHT, false); + fix.detectChanges(); + + const dropGhostBounds = QueryBuilderFunctions.getDropGhostBounds(fix); + const targetChipBounds = chipComponents[1].nativeElement.getBoundingClientRect(); // "OrderId in Products/OrderId" chip + expect(dropGhostBounds.x).toBe(targetChipBounds.x); + expect(dropGhostBounds.y).toBeCloseTo(targetChipBounds.y + ROW_HEIGHT); + }); + + // TODO: Currently doesn't work as expected. The drop ghost is not shown on the first action. + it.skip('Should position drop ghost below the inner group aligned with the outer level conditions when the bottom inner level condition is dragged down.', () => { + const draggedChip = chipComponents[5].componentInstance; // "OrderDate Today" chip + const dragDir = draggedChip.dragDirective; + UIInteractions.moveDragDirective(fix, dragDir, -50, 10, false); + + const dropGhostBounds = QueryBuilderFunctions.getDropGhostBounds(fix); + const previousLevelChipBounds = chipComponents[1].nativeElement.getBoundingClientRect(); // "OrderId in Products/OrderId" chip + expect(dropGhostBounds.x).toBe(previousLevelChipBounds.x); + const innerGroupElement = QueryBuilderFunctions.getQueryBuilderTreeChildGroups(QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement)[0]; + const innerGroupBounds = innerGroupElement.getBoundingClientRect(); + expect(Math.abs(dropGhostBounds.top - innerGroupBounds.bottom)).toBeLessThan(20); + }); + + it('Should hide drop ghost on dragging the mouse far down outside the query builder.', () => { + const draggedChip = chipComponents[0].componentInstance; + const draggedChipElem = draggedChip.chipArea.nativeElement; + + UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 0, 10 * draggedChipElem.offsetHeight, false); + + const dropGhost = QueryBuilderFunctions.getDropGhost(fix); + expect(dropGhost).toBe(null); + expect(QueryBuilderFunctions.getVisibleChips(fix).length).toBe(3); + }); + + it('Should drop the condition above the target condition on dragging up.', fakeAsync(() => { + const secondChip = chipComponents[1].componentInstance; // "OrderId In Products/ OrderId" chip + + expect(QueryBuilderFunctions.getChipContent(chipComponents[0].nativeElement)).toBe("OrderName Equals foo"); + const draggedChipCenter = QueryBuilderFunctions.getElementCenter(secondChip.chipArea.nativeElement); + const dragDir = secondChip.dragDirective; + + //pickup chip + dragDir.onPointerDown({ pointerId: 1, pageX: draggedChipCenter.X, pageY: draggedChipCenter.Y }); + fix.detectChanges(); + + //trigger ghost + QueryBuilderFunctions.dragMove(dragDir, draggedChipCenter.X + 50, draggedChipCenter.Y - 50); + fix.detectChanges(); + + //drag + QueryBuilderFunctions.dragMove(dragDir, draggedChipCenter.X + 50, draggedChipCenter.Y - 50, true); + fix.detectChanges(); + + chipComponents = QueryBuilderFunctions.getVisibleChips(fix); + expect(QueryBuilderFunctions.getChipContent(chipComponents[0].nativeElement)).toBe("OrderId In Products / OrderId"); + expect(QueryBuilderFunctions.getChipContent(chipComponents[1].nativeElement)).toBe("OrderName Equals foo"); + })); + + it('Should drop the condition below the target condition on dragging down.', fakeAsync(() => { + const secondChip = chipComponents[0].componentInstance; // "OrderName Equals foo" chip + const secondChipElem = secondChip.nativeElement; + + expect(QueryBuilderFunctions.getChipContent(chipComponents[0].nativeElement)).toBe("OrderName Equals foo"); + + UIInteractions.moveDragDirective(fix, secondChip.dragDirective, 0, secondChipElem.offsetHeight, true); + tick(50); + fix.detectChanges(); + QueryBuilderFunctions.verifyFocusedChip('OrderName', 'Equals', 'foo'); + + chipComponents = QueryBuilderFunctions.getVisibleChips(fix); + expect(QueryBuilderFunctions.getChipContent(chipComponents[0].nativeElement)).toBe("OrderId In Products / OrderId"); + expect(QueryBuilderFunctions.getChipContent(chipComponents[1].nativeElement)).toBe("OrderName Equals foo"); + })); + + it('Should drop the condition inside the inner group when dropped over the group.', fakeAsync(() => { + const draggedChip = chipComponents[0].componentInstance; // "OrderName Equals foo" chip + const draggedChipElem = draggedChip.nativeElement; + + const dragDir = draggedChip.dragDirective; + UIInteractions.moveDragDirective(fix, dragDir, 50, 2 * draggedChipElem.offsetHeight + 25, true); + tick(50); + fix.detectChanges(); + QueryBuilderFunctions.verifyFocusedChip('OrderName', 'Equals', 'foo'); + + chipComponents = QueryBuilderFunctions.getVisibleChips(fix); + const droppedChipBounds = chipComponents[1].nativeElement.getBoundingClientRect(); + const targetChipBounds = chipComponents[2].nativeElement.getBoundingClientRect(); + expect(droppedChipBounds.x).toBe(targetChipBounds.x); + expect(droppedChipBounds.y).toBeCloseTo(targetChipBounds.y - ROW_HEIGHT); + + expect(QueryBuilderFunctions.getChipContent(chipComponents[0].nativeElement)).toBe("OrderId In Products / OrderId"); + expect(QueryBuilderFunctions.getChipContent(chipComponents[1].nativeElement)).toBe("OrderName Equals foo"); + })); + + it('Should drop the condition outside the inner group aligned with the outer level conditions when dropped above the inner group.', fakeAsync(() => { + const draggedChip = chipComponents[5].componentInstance; // "OrderDate Today" chip + const draggedChipElem = draggedChip.nativeElement; + + UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 0, -3.5 * draggedChipElem.offsetHeight, true); + tick(50); + fix.detectChanges(); + QueryBuilderFunctions.verifyFocusedChip('OrderDate', 'Today'); + + chipComponents = QueryBuilderFunctions.getVisibleChips(fix); + const droppedChipBounds = chipComponents[2].nativeElement.getBoundingClientRect(); + const targetChipBounds = chipComponents[1].nativeElement.getBoundingClientRect(); // "OrderId in Products/OrderId" chip + expect(droppedChipBounds.x).toBe(targetChipBounds.x); + expect(droppedChipBounds.y).toBeCloseTo(targetChipBounds.y + ROW_HEIGHT); + + expect(QueryBuilderFunctions.getChipContent(chipComponents[0].nativeElement)).toBe("OrderName Equals foo"); + expect(QueryBuilderFunctions.getChipContent(chipComponents[1].nativeElement)).toBe("OrderId In Products / OrderId"); + expect(QueryBuilderFunctions.getChipContent(chipComponents[2].nativeElement)).toBe("OrderDate Today"); + })); + + it('Should drop the condition at the last position of the root group when dropped above the buttons.', fakeAsync(() => { + const draggedChip = chipComponents[5].componentInstance; // "OrderDate Today" chip + const draggedChipCenter = QueryBuilderFunctions.getElementCenter(draggedChip.chipArea.nativeElement); + const dragDir = draggedChip.dragDirective; + + //pickup chip + dragDir.onPointerDown({ pointerId: 1, pageX: draggedChipCenter.X, pageY: draggedChipCenter.Y }); + fix.detectChanges(); + + //trigger ghost + QueryBuilderFunctions.dragMove(dragDir, draggedChipCenter.X + 10, draggedChipCenter.Y + 10); + fix.detectChanges(); + + vi.spyOn(dragDir.ghostElement, 'dispatchEvent'); + + const addConditionButton = QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtons(fix, 0)[0] as HTMLElement; + const addConditionButtonCenter = QueryBuilderFunctions.getElementCenter(addConditionButton); + + //move over +Condition + QueryBuilderFunctions.dragMove(dragDir, addConditionButtonCenter.X, addConditionButtonCenter.Y); + fix.detectChanges(); + + const dropGhost = QueryBuilderFunctions.getDropGhost(fix) as HTMLElement; + chipComponents = QueryBuilderFunctions.getVisibleChips(fix); + expect(QueryBuilderFunctions.getElementCenter(dropGhost).Y).toBeGreaterThan(QueryBuilderFunctions.getElementCenter(chipComponents[2].nativeElement).Y); + expect(QueryBuilderFunctions.getElementCenter(dropGhost).Y).toBeLessThan(QueryBuilderFunctions.getElementCenter(addConditionButton).Y); + + //drop condition + dragDir.onPointerUp({ pointerId: 1, pageX: addConditionButtonCenter.X, pageY: addConditionButtonCenter.Y }); + tick(20); + fix.detectChanges(); + + const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); + expect(exprTree).toBe(`{ "filteringOperands": [ { "fieldName": "OrderName", @@ -2856,272 +2863,272 @@ describe('IgxQueryBuilder', () => { "*" ] }`); - })); - - it('Should remove the inner group when the last condition is dragged out.', fakeAsync(() => { - const draggedChip = chipComponents[5].componentInstance; // "OrderDate Today" chip - const heightOffset = draggedChip.nativeElement.offsetHeight; + })); - UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 0, -4 * heightOffset, true); - tick(50); - fix.detectChanges(); - QueryBuilderFunctions.verifyFocusedChip('OrderDate', 'Today'); + it('Should remove the inner group when the last condition is dragged out.', fakeAsync(() => { + const draggedChip = chipComponents[5].componentInstance; // "OrderDate Today" chip + const heightOffset = draggedChip.nativeElement.offsetHeight; - UIInteractions.moveDragDirective(fix, chipComponents[4].componentInstance.dragDirective, 0, -4 * heightOffset, true); - tick(50); - fix.detectChanges(); - QueryBuilderFunctions.verifyFocusedChip('OrderName', 'Ends With', 'a'); - - chipComponents = QueryBuilderFunctions.getVisibleChips(fix); - - const firstChipBounds = chipComponents[0].nativeElement.getBoundingClientRect(); - const droppedChipBounds = chipComponents[3].nativeElement.getBoundingClientRect(); - expect(QueryBuilderFunctions.getQueryBuilderTreeChildGroups(QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement).length).toBe(0); - expect(droppedChipBounds.x).toBeCloseTo(firstChipBounds.x); - expect(chipComponents.length).toBe(4); - })); - - it('Should drop the condition above the currently edited condition on dragging up.', fakeAsync(() => { - chipComponents = QueryBuilderFunctions.getVisibleChips(fix); - const draggedChip = chipComponents[3].componentInstance; // "OrderDate Today" chip - const draggedChipElem = draggedChip.nativeElement; - - chipComponents[2].nativeElement.click(); - - UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 0, -2.5 * draggedChipElem.offsetHeight, true); - tick(50); - fix.detectChanges(); - QueryBuilderFunctions.verifyFocusedChip('OrderDate', 'Today'); - - chipComponents = QueryBuilderFunctions.getVisibleChips(fix); - expect(QueryBuilderFunctions.getChipContent(chipComponents[2].nativeElement)).toBe("OrderDate Today"); - })); - - it('Should be able to drag a top-level condition while a sub-query is expanded.', () => { - chipComponents[1].nativeElement.click(); - - const draggedChip = chipComponents[0].componentInstance; - const draggedChipElem = draggedChip.nativeElement; - - expect(draggedChip.draggable).toBeTrue(); - UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 0, draggedChipElem.offsetHeight, false); - expect(QueryBuilderFunctions.getDropGhost(fix)).not.toBe(null); - }); - - it('Should allow dragging a sub-query condition while a sub-query is expanded.', () => { - chipComponents[1].nativeElement.click(); - - const draggedChip = chipComponents[2].componentInstance; - const draggedChipElem = draggedChip.nativeElement; - - UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 0, draggedChipElem.offsetHeight, false); - expect(QueryBuilderFunctions.getDropGhost(fix)).not.toBe(null); - }); - - it('Should successfully rearrange sub-query conditions via mouse drag.', fakeAsync(() => { - chipComponents[1].nativeElement.click(); - - const draggedChip = chipComponents[2].componentInstance; - const draggedChipElem = draggedChip.nativeElement; - - UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 0, draggedChipElem.offsetHeight, true); - tick(50); - fix.detectChanges(); - QueryBuilderFunctions.verifyFocusedChip('Id', 'Equals', '123'); - - chipComponents = QueryBuilderFunctions.getVisibleChips(fix); - expect(chipComponents.length).toBe(5); - expect(QueryBuilderFunctions.getChipContent(chipComponents[1].nativeElement)).toBe("ProductName Equals abc"); - expect(QueryBuilderFunctions.getChipContent(chipComponents[2].nativeElement)).toBe("Id Equals 123"); - })); - - it('Should not allow dragging a sub-query condition outside the sub-query.', () => { - chipComponents[1].nativeElement.click(); - - const draggedChip = chipComponents[2].componentInstance; - const draggedChipElem = draggedChip.nativeElement; - - UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 0, -10 * draggedChipElem.offsetHeight, false); - - expect(QueryBuilderFunctions.getVisibleChips(fix).length).toBe(4); - expect(QueryBuilderFunctions.getDropGhost(fix)).toBe(null); - }); - - it('Should successfully drop a condition inside a newly created group.', fakeAsync(() => { - var addGroupButton = QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtons(fix, 0).pop(); - QueryBuilderFunctions.verifyGroupLineCount(fix, 2, 1); - - (addGroupButton as HTMLElement).click(); - const draggedChip = chipComponents.pop().componentInstance; - const draggedChipElem = draggedChip.nativeElement; - UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 0, 3 * draggedChipElem.offsetHeight, true); - tick(300); - fix.detectChanges(); - QueryBuilderFunctions.verifyFocusedChip('OrderDate', 'Today'); - - chipComponents = QueryBuilderFunctions.getVisibleChips(fix); - expect(chipComponents.length).toBe(4); - QueryBuilderFunctions.verifyGroupLineCount(fix, 2, 2); - const newGroup = QueryBuilderFunctions.getQueryBuilderAllGroups(fix).pop(); - const newGroupConditions = newGroup.querySelectorAll('igx-chip'); - expect(newGroupConditions.length).toBe(1); - expect(QueryBuilderFunctions.getChipContent(newGroupConditions[0])).toBe("OrderDate Today"); - })); - - it('Should render drop ghost properly when keyboard dragged.', fakeAsync(() => { - const draggedIndicator = fix.debugElement.queryAll(By.css('.igx-drag-indicator'))[1]; - const tree = fix.debugElement.query(By.css('.igx-filter-tree')); - - draggedIndicator.triggerEventHandler('focus', {}); - draggedIndicator.nativeElement.focus(); - - spyOn(tree.nativeElement, 'dispatchEvent').and.callThrough(); - const dropGhostContent = QueryBuilderFunctions.GetChipsContentAsArray(fix)[1]; - - //pass 1 down to bottom - let keyPress = new KeyboardEvent('keydown', { key: 'ArrowDown' }); - for (let i = 0; i <= 5; i++) { - tree.nativeElement.dispatchEvent(keyPress); - tick(20); - fix.detectChanges(); - - const [dropGhost, prevElement, nextElement, newChipContents] = QueryBuilderFunctions.getDropGhostAndItsSiblings(fix); - - switch (true) { - case i === 0: - expect(dropGhost).toBeDefined(); - expect(prevElement).toBeNull(); - expect(nextElement).toEqual('OrderName Ends With a'); - expect(newChipContents[4]).toBe(dropGhostContent); - break; - case i === 1: - expect(dropGhost).toBeDefined(); - expect(prevElement).toEqual('OrderName Ends With a'); - expect(nextElement).toEqual('OrderDate Today'); - expect(newChipContents[5]).toBe(dropGhostContent); - break; - case i === 2: - expect(dropGhost).toBeDefined(); - expect(prevElement).toEqual('OrderDate Today'); - expect(nextElement).toBeNull(); - expect(newChipContents[6]).toBe(dropGhostContent); - break; - case i >= 3: - expect(dropGhost).toBeDefined(); - expect(prevElement).toEqual('or OrderName Ends With a OrderDate Today'); - expect(nextElement).toBeNull(); - expect(newChipContents[6]).toBe(dropGhostContent); - break; - } - } - - //pass 2 up to top - keyPress = new KeyboardEvent('keydown', { key: 'ArrowUp' }); - for (let i = 0; i <= 10; i++) { - tree.nativeElement.dispatchEvent(keyPress); - tick(20); - fix.detectChanges(); - - const [dropGhost, prevElement, nextElement, newChipContents] = QueryBuilderFunctions.getDropGhostAndItsSiblings(fix); - - switch (true) { - case i === 0: - expect(dropGhost).toBeDefined(); - expect(prevElement).toEqual('OrderDate Today'); - expect(nextElement).toBeNull(); - expect(newChipContents[6]).toBe(dropGhostContent); - break; - case i === 1: - expect(dropGhost).toBeDefined(); - expect(prevElement).toEqual('OrderName Ends With a'); - expect(nextElement).toEqual('OrderDate Today'); - expect(newChipContents[5]).toBe(dropGhostContent); - break; - case i === 2: - expect(dropGhost).toBeDefined(); - expect(prevElement).toBeNull(); - expect(nextElement).toEqual('OrderName Ends With a'); - expect(newChipContents[4]).toBe(dropGhostContent); - break; - case i === 3: - expect(dropGhost).toBeDefined(); - expect(prevElement).toEqual('OrderName Equals foo'); - expect(nextElement).toEqual('or OrderName Ends With a OrderDate Today'); - expect(newChipContents[1]).toBe(dropGhostContent); - break; - case i >= 4: - expect(dropGhost).toBeDefined(); - expect(prevElement).toBeNull(); - expect(nextElement).toEqual('OrderName Equals foo'); - expect(newChipContents[0]).toBe(dropGhostContent); - break; - } - } - - //pass 3 down to bottom again - keyPress = new KeyboardEvent('keydown', { key: 'ArrowDown' }); - for (let i = 0; i <= 10; i++) { - tree.nativeElement.dispatchEvent(keyPress); - tick(20); - fix.detectChanges(); + UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 0, -4 * heightOffset, true); + tick(50); + fix.detectChanges(); + QueryBuilderFunctions.verifyFocusedChip('OrderDate', 'Today'); + + UIInteractions.moveDragDirective(fix, chipComponents[4].componentInstance.dragDirective, 0, -4 * heightOffset, true); + tick(50); + fix.detectChanges(); + QueryBuilderFunctions.verifyFocusedChip('OrderName', 'Ends With', 'a'); + + chipComponents = QueryBuilderFunctions.getVisibleChips(fix); + + const firstChipBounds = chipComponents[0].nativeElement.getBoundingClientRect(); + const droppedChipBounds = chipComponents[3].nativeElement.getBoundingClientRect(); + expect(QueryBuilderFunctions.getQueryBuilderTreeChildGroups(QueryBuilderFunctions.getQueryBuilderTreeRootGroup(fix) as HTMLElement).length).toBe(0); + expect(droppedChipBounds.x).toBeCloseTo(firstChipBounds.x); + expect(chipComponents.length).toBe(4); + })); + + it('Should drop the condition above the currently edited condition on dragging up.', fakeAsync(() => { + chipComponents = QueryBuilderFunctions.getVisibleChips(fix); + const draggedChip = chipComponents[3].componentInstance; // "OrderDate Today" chip + const draggedChipElem = draggedChip.nativeElement; + + chipComponents[2].nativeElement.click(); + + UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 0, -2.5 * draggedChipElem.offsetHeight, true); + tick(50); + fix.detectChanges(); + QueryBuilderFunctions.verifyFocusedChip('OrderDate', 'Today'); + + chipComponents = QueryBuilderFunctions.getVisibleChips(fix); + expect(QueryBuilderFunctions.getChipContent(chipComponents[2].nativeElement)).toBe("OrderDate Today"); + })); + + it('Should be able to drag a top-level condition while a sub-query is expanded.', () => { + chipComponents[1].nativeElement.click(); + + const draggedChip = chipComponents[0].componentInstance; + const draggedChipElem = draggedChip.nativeElement; + + expect(draggedChip.draggable).toBe(true); + UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 0, draggedChipElem.offsetHeight, false); + expect(QueryBuilderFunctions.getDropGhost(fix)).not.toBe(null); + }); + + it('Should allow dragging a sub-query condition while a sub-query is expanded.', () => { + chipComponents[1].nativeElement.click(); + + const draggedChip = chipComponents[2].componentInstance; + const draggedChipElem = draggedChip.nativeElement; + + UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 0, draggedChipElem.offsetHeight, false); + expect(QueryBuilderFunctions.getDropGhost(fix)).not.toBe(null); + }); + + it('Should successfully rearrange sub-query conditions via mouse drag.', fakeAsync(() => { + chipComponents[1].nativeElement.click(); + + const draggedChip = chipComponents[2].componentInstance; + const draggedChipElem = draggedChip.nativeElement; + + UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 0, draggedChipElem.offsetHeight, true); + tick(50); + fix.detectChanges(); + QueryBuilderFunctions.verifyFocusedChip('Id', 'Equals', '123'); + + chipComponents = QueryBuilderFunctions.getVisibleChips(fix); + expect(chipComponents.length).toBe(5); + expect(QueryBuilderFunctions.getChipContent(chipComponents[1].nativeElement)).toBe("ProductName Equals abc"); + expect(QueryBuilderFunctions.getChipContent(chipComponents[2].nativeElement)).toBe("Id Equals 123"); + })); + + it('Should not allow dragging a sub-query condition outside the sub-query.', () => { + chipComponents[1].nativeElement.click(); + + const draggedChip = chipComponents[2].componentInstance; + const draggedChipElem = draggedChip.nativeElement; + + UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 0, -10 * draggedChipElem.offsetHeight, false); + + expect(QueryBuilderFunctions.getVisibleChips(fix).length).toBe(4); + expect(QueryBuilderFunctions.getDropGhost(fix)).toBe(null); + }); + + it('Should successfully drop a condition inside a newly created group.', fakeAsync(() => { + var addGroupButton = QueryBuilderFunctions.getQueryBuilderTreeRootGroupButtons(fix, 0).pop(); + QueryBuilderFunctions.verifyGroupLineCount(fix, 2, 1); + + (addGroupButton as HTMLElement).click(); + const draggedChip = chipComponents.pop().componentInstance; + const draggedChipElem = draggedChip.nativeElement; + UIInteractions.moveDragDirective(fix, draggedChip.dragDirective, 0, 3 * draggedChipElem.offsetHeight, true); + tick(300); + fix.detectChanges(); + QueryBuilderFunctions.verifyFocusedChip('OrderDate', 'Today'); + + chipComponents = QueryBuilderFunctions.getVisibleChips(fix); + expect(chipComponents.length).toBe(4); + QueryBuilderFunctions.verifyGroupLineCount(fix, 2, 2); + const newGroup = QueryBuilderFunctions.getQueryBuilderAllGroups(fix).pop(); + const newGroupConditions = newGroup.querySelectorAll('igx-chip'); + expect(newGroupConditions.length).toBe(1); + expect(QueryBuilderFunctions.getChipContent(newGroupConditions[0])).toBe("OrderDate Today"); + })); + + it('Should render drop ghost properly when keyboard dragged.', fakeAsync(() => { + const draggedIndicator = fix.debugElement.queryAll(By.css('.igx-drag-indicator'))[1]; + const tree = fix.debugElement.query(By.css('.igx-filter-tree')); + + draggedIndicator.triggerEventHandler('focus', {}); + draggedIndicator.nativeElement.focus(); + + vi.spyOn(tree.nativeElement, 'dispatchEvent'); + const dropGhostContent = QueryBuilderFunctions.GetChipsContentAsArray(fix)[1]; + + //pass 1 down to bottom + let keyPress = new KeyboardEvent('keydown', { key: 'ArrowDown' }); + for (let i = 0; i <= 5; i++) { + tree.nativeElement.dispatchEvent(keyPress); + tick(20); + fix.detectChanges(); + + const [dropGhost, prevElement, nextElement, newChipContents] = QueryBuilderFunctions.getDropGhostAndItsSiblings(fix); + + switch (true) { + case i === 0: + expect(dropGhost).toBeDefined(); + expect(prevElement).toBeNull(); + expect(nextElement).toEqual('OrderName Ends With a'); + expect(newChipContents[4]).toBe(dropGhostContent); + break; + case i === 1: + expect(dropGhost).toBeDefined(); + expect(prevElement).toEqual('OrderName Ends With a'); + expect(nextElement).toEqual('OrderDate Today'); + expect(newChipContents[5]).toBe(dropGhostContent); + break; + case i === 2: + expect(dropGhost).toBeDefined(); + expect(prevElement).toEqual('OrderDate Today'); + expect(nextElement).toBeNull(); + expect(newChipContents[6]).toBe(dropGhostContent); + break; + case i >= 3: + expect(dropGhost).toBeDefined(); + expect(prevElement).toEqual('or OrderName Ends With a OrderDate Today'); + expect(nextElement).toBeNull(); + expect(newChipContents[6]).toBe(dropGhostContent); + break; + } + } - const [dropGhost, prevElement, nextElement, newChipContents] = QueryBuilderFunctions.getDropGhostAndItsSiblings(fix); + //pass 2 up to top + keyPress = new KeyboardEvent('keydown', { key: 'ArrowUp' }); + for (let i = 0; i <= 10; i++) { + tree.nativeElement.dispatchEvent(keyPress); + tick(20); + fix.detectChanges(); + + const [dropGhost, prevElement, nextElement, newChipContents] = QueryBuilderFunctions.getDropGhostAndItsSiblings(fix); + + switch (true) { + case i === 0: + expect(dropGhost).toBeDefined(); + expect(prevElement).toEqual('OrderDate Today'); + expect(nextElement).toBeNull(); + expect(newChipContents[6]).toBe(dropGhostContent); + break; + case i === 1: + expect(dropGhost).toBeDefined(); + expect(prevElement).toEqual('OrderName Ends With a'); + expect(nextElement).toEqual('OrderDate Today'); + expect(newChipContents[5]).toBe(dropGhostContent); + break; + case i === 2: + expect(dropGhost).toBeDefined(); + expect(prevElement).toBeNull(); + expect(nextElement).toEqual('OrderName Ends With a'); + expect(newChipContents[4]).toBe(dropGhostContent); + break; + case i === 3: + expect(dropGhost).toBeDefined(); + expect(prevElement).toEqual('OrderName Equals foo'); + expect(nextElement).toEqual('or OrderName Ends With a OrderDate Today'); + expect(newChipContents[1]).toBe(dropGhostContent); + break; + case i >= 4: + expect(dropGhost).toBeDefined(); + expect(prevElement).toBeNull(); + expect(nextElement).toEqual('OrderName Equals foo'); + expect(newChipContents[0]).toBe(dropGhostContent); + break; + } + } - switch (true) { - case i === 0: - expect(dropGhost).toBeDefined(); - expect(prevElement).toEqual('OrderName Equals foo'); - expect(nextElement).toEqual('or OrderName Ends With a OrderDate Today'); - expect(newChipContents[1]).toBe(dropGhostContent); - break; - case i === 1: - expect(dropGhost).toBeDefined(); - expect(prevElement).toBeNull(); - expect(nextElement).toEqual('OrderName Ends With a'); - expect(newChipContents[4]).toBe(dropGhostContent); - break; - case i === 2: - expect(dropGhost).toBeDefined(); - expect(prevElement).toEqual('OrderName Ends With a'); - expect(nextElement).toEqual('OrderDate Today'); - expect(newChipContents[5]).toBe(dropGhostContent); - break; - case i === 3: - expect(dropGhost).toBeDefined(); - expect(prevElement).toEqual('OrderDate Today'); - expect(nextElement).toBeNull(); - expect(newChipContents[6]).toBe(dropGhostContent); - break; - case i >= 4: - expect(dropGhost).toBeDefined(); - expect(prevElement).toEqual('or OrderName Ends With a OrderDate Today'); - expect(nextElement).toBeNull(); - expect(newChipContents[6]).toBe(dropGhostContent); - break; - } - } - })); + //pass 3 down to bottom again + keyPress = new KeyboardEvent('keydown', { key: 'ArrowDown' }); + for (let i = 0; i <= 10; i++) { + tree.nativeElement.dispatchEvent(keyPress); + tick(20); + fix.detectChanges(); + + const [dropGhost, prevElement, nextElement, newChipContents] = QueryBuilderFunctions.getDropGhostAndItsSiblings(fix); + + switch (true) { + case i === 0: + expect(dropGhost).toBeDefined(); + expect(prevElement).toEqual('OrderName Equals foo'); + expect(nextElement).toEqual('or OrderName Ends With a OrderDate Today'); + expect(newChipContents[1]).toBe(dropGhostContent); + break; + case i === 1: + expect(dropGhost).toBeDefined(); + expect(prevElement).toBeNull(); + expect(nextElement).toEqual('OrderName Ends With a'); + expect(newChipContents[4]).toBe(dropGhostContent); + break; + case i === 2: + expect(dropGhost).toBeDefined(); + expect(prevElement).toEqual('OrderName Ends With a'); + expect(nextElement).toEqual('OrderDate Today'); + expect(newChipContents[5]).toBe(dropGhostContent); + break; + case i === 3: + expect(dropGhost).toBeDefined(); + expect(prevElement).toEqual('OrderDate Today'); + expect(nextElement).toBeNull(); + expect(newChipContents[6]).toBe(dropGhostContent); + break; + case i >= 4: + expect(dropGhost).toBeDefined(); + expect(prevElement).toEqual('or OrderName Ends With a OrderDate Today'); + expect(nextElement).toBeNull(); + expect(newChipContents[6]).toBe(dropGhostContent); + break; + } + } + })); - it('Should commit drop upon hitting \'Enter\' when keyboard dragged.', fakeAsync(() => { - const draggedIndicator = fix.debugElement.queryAll(By.css('.igx-drag-indicator'))[4]; - const tree = fix.debugElement.query(By.css('.igx-filter-tree')); + it('Should commit drop upon hitting \'Enter\' when keyboard dragged.', fakeAsync(() => { + const draggedIndicator = fix.debugElement.queryAll(By.css('.igx-drag-indicator'))[4]; + const tree = fix.debugElement.query(By.css('.igx-filter-tree')); - draggedIndicator.triggerEventHandler('focus', {}); - draggedIndicator.nativeElement.focus(); + draggedIndicator.triggerEventHandler('focus', {}); + draggedIndicator.nativeElement.focus(); - spyOn(tree.nativeElement, 'dispatchEvent').and.callThrough(); + vi.spyOn(tree.nativeElement, 'dispatchEvent'); - tree.nativeElement.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' })); - tick(20); - fix.detectChanges(); + tree.nativeElement.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' })); + tick(20); + fix.detectChanges(); - tree.nativeElement.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' })); - tick(20); - fix.detectChanges(); + tree.nativeElement.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' })); + tick(20); + fix.detectChanges(); - //Verify that expressionTree is correct - const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); - expect(exprTree).toBe(`{ + //Verify that expressionTree is correct + const exprTree = JSON.stringify(fix.componentInstance.queryBuilder.expressionTree, null, 2); + expect(exprTree).toBe(`{ "filteringOperands": [ { "fieldName": "OrderName", @@ -3207,75 +3214,77 @@ describe('IgxQueryBuilder', () => { "*" ] }`); - })); + })); - it('Should cancel drop upon hitting \'Escape\' when keyboard dragged.', fakeAsync(() => { - const draggedIndicator = fix.debugElement.queryAll(By.css('.igx-drag-indicator'))[4]; - const tree = fix.debugElement.query(By.css('.igx-filter-tree')); + it('Should cancel drop upon hitting \'Escape\' when keyboard dragged.', fakeAsync(() => { + const draggedIndicator = fix.debugElement.queryAll(By.css('.igx-drag-indicator'))[4]; + const tree = fix.debugElement.query(By.css('.igx-filter-tree')); - draggedIndicator.triggerEventHandler('focus', {}); - draggedIndicator.nativeElement.focus(); + draggedIndicator.triggerEventHandler('focus', {}); + draggedIndicator.nativeElement.focus(); - spyOn(tree.nativeElement, 'dispatchEvent').and.callThrough(); + vi.spyOn(tree.nativeElement, 'dispatchEvent'); - tree.nativeElement.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' })); - tick(20); - fix.detectChanges(); + tree.nativeElement.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' })); + tick(20); + fix.detectChanges(); - tree.nativeElement.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' })); - tick(20); - fix.detectChanges(); + tree.nativeElement.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' })); + tick(20); + fix.detectChanges(); - chipComponents = QueryBuilderFunctions.getVisibleChips(fix); - expect(QueryBuilderFunctions.getChipContent(chipComponents[2].nativeElement)).toBe("OrderName Ends With a"); - expect(QueryBuilderFunctions.getChipContent(chipComponents[3].nativeElement)).toBe("OrderDate Today"); - })); + chipComponents = QueryBuilderFunctions.getVisibleChips(fix); + expect(QueryBuilderFunctions.getChipContent(chipComponents[2].nativeElement)).toBe("OrderName Ends With a"); + expect(QueryBuilderFunctions.getChipContent(chipComponents[3].nativeElement)).toBe("OrderDate Today"); + })); - }); + }); }); @Component({ - template: ` + template: ` `, - standalone: true, - imports: [ - IgxQueryBuilderComponent - ] + standalone: true, + imports: [ + IgxQueryBuilderComponent + ] }) export class IgxQueryBuilderSampleTestComponent implements OnInit { - @ViewChild(IgxQueryBuilderComponent) public queryBuilder: IgxQueryBuilderComponent; - public entities: Array; + @ViewChild(IgxQueryBuilderComponent) + public queryBuilder: IgxQueryBuilderComponent; + public entities: Array; - public ngOnInit(): void { - this.entities = SampleEntities.map(a => ({ ...a })); - } + public ngOnInit(): void { + this.entities = SampleEntities.map(a => ({ ...a })); + } } @Component({ - template: ` + template: ` `, - standalone: true, - imports: [ - IgxQueryBuilderComponent - ] + standalone: true, + imports: [ + IgxQueryBuilderComponent + ] }) export class IgxQueryBuilderInvalidSampleTestComponent implements OnInit { - @ViewChild(IgxQueryBuilderComponent) public queryBuilder: IgxQueryBuilderComponent; - public entities: Array; - public expressionTree: IExpressionTree; - - public ngOnInit(): void { - this.entities = []; - this.expressionTree = QueryBuilderFunctions.generateExpressionTree(); - } + @ViewChild(IgxQueryBuilderComponent) + public queryBuilder: IgxQueryBuilderComponent; + public entities: Array; + public expressionTree: IExpressionTree; + + public ngOnInit(): void { + this.entities = []; + this.expressionTree = QueryBuilderFunctions.generateExpressionTree(); + } } @Component({ - template: ` + template: ` `, - standalone: true, - imports: [ - IgxQueryBuilderComponent, - IgxQueryBuilderHeaderComponent, - IgxQueryBuilderSearchValueTemplateDirective, - IgxComboComponent, - NgTemplateOutlet, - FormsModule - ] + standalone: true, + imports: [ + IgxQueryBuilderComponent, + IgxQueryBuilderHeaderComponent, + IgxQueryBuilderSearchValueTemplateDirective, + IgxComboComponent, + NgTemplateOutlet, + FormsModule + ] }) export class IgxQueryBuilderCustomTemplateSampleTestComponent implements OnInit { - @ViewChild(IgxQueryBuilderComponent) public queryBuilder: IgxQueryBuilderComponent; - @ViewChild('searchValueTemplate', { read: IgxQueryBuilderSearchValueTemplateDirective, static: true }) - public searchValueTemplate: IgxQueryBuilderSearchValueTemplateDirective; - public entities: Array; - public expressionTree: IExpressionTree; - public comboData: any[]; - - - public ngOnInit(): void { - this.entities = SampleEntities.map(a => ({ ...a })); - this.entities[1].fields[0].formatter = (value: any, rowData: any) => rowData === 'equals' ? (Array.from(value)[0] as any).id : value; - - const tree = new FilteringExpressionsTree(FilteringLogic.And, null, 'Orders', ['*']); - tree.filteringOperands.push({ - fieldName: 'OrderId', - condition: IgxNumberFilteringOperand.instance().condition('greaterThan'), - conditionName: 'greaterThan', - searchVal: 3, - ignoreCase: true - }); - - this.expressionTree = tree; - - this.comboData = [ - { id: 0, field: 'A' }, - { id: 1, field: 'B' } - ]; - } + @ViewChild(IgxQueryBuilderComponent) + public queryBuilder: IgxQueryBuilderComponent; + @ViewChild('searchValueTemplate', { read: IgxQueryBuilderSearchValueTemplateDirective, static: true }) + public searchValueTemplate: IgxQueryBuilderSearchValueTemplateDirective; + public entities: Array; + public expressionTree: IExpressionTree; + public comboData: any[]; + + + public ngOnInit(): void { + this.entities = SampleEntities.map(a => ({ ...a })); + this.entities[1].fields[0].formatter = (value: any, rowData: any) => rowData === 'equals' ? (Array.from(value)[0] as any).id : value; + + const tree = new FilteringExpressionsTree(FilteringLogic.And, null, 'Orders', ['*']); + tree.filteringOperands.push({ + fieldName: 'OrderId', + condition: IgxNumberFilteringOperand.instance().condition('greaterThan'), + conditionName: 'greaterThan', + searchVal: 3, + ignoreCase: true + }); + + this.expressionTree = tree; + + this.comboData = [ + { id: 0, field: 'A' }, + { id: 1, field: 'B' } + ]; + } } diff --git a/projects/igniteui-angular/radio/src/radio/radio-group/radio-group.directive.spec.ts b/projects/igniteui-angular/radio/src/radio/radio-group/radio-group.directive.spec.ts index 9767c6ab702..2f6495be405 100644 --- a/projects/igniteui-angular/radio/src/radio/radio-group/radio-group.directive.spec.ts +++ b/projects/igniteui-angular/radio/src/radio/radio-group/radio-group.directive.spec.ts @@ -6,6 +6,7 @@ import { FormsModule, ReactiveFormsModule, UntypedFormGroup, UntypedFormBuilder, import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { By } from '@angular/platform-browser'; import { IgxRadioComponent } from '../../radio/radio.component'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxRadioGroupDirective', () => { beforeEach(waitForAsync(() => { @@ -26,7 +27,7 @@ describe('IgxRadioGroupDirective', () => { RadioGroupVerticalComponent ] }) - .compileComponents(); + .compileComponents(); })); it('Properly initialize the radio group buttons\' properties.', fakeAsync(() => { @@ -57,7 +58,7 @@ describe('IgxRadioGroupDirective', () => { fixture.detectChanges(); tick(); - expect(radioInstance.checked).toBeTrue(); + expect(radioInstance.checked).toBe(true); })); it('Setting radioGroup\'s properties should affect all radio buttons.', fakeAsync(() => { @@ -106,7 +107,7 @@ describe('IgxRadioGroupDirective', () => { expect(radioInstance.selected).toBeDefined(); expect(radioInstance.selected).toEqual(radioInstance.radioButtons.last); - spyOn(radioInstance.change, 'emit'); + vi.spyOn(radioInstance.change, 'emit'); radioInstance.value = 'Foo'; fixture.detectChanges(); @@ -129,7 +130,7 @@ describe('IgxRadioGroupDirective', () => { expect(radioInstance.selected).toBeDefined(); expect(radioInstance.selected).toEqual(radioInstance.radioButtons.last); - spyOn(radioInstance.change, 'emit'); + vi.spyOn(radioInstance.change, 'emit'); radioInstance.selected = radioInstance.radioButtons.first; fixture.detectChanges(); @@ -205,7 +206,7 @@ describe('IgxRadioGroupDirective', () => { fixture.detectChanges(); tick(); - fixture.componentInstance.choices = [ 0, 1, 4, 7 ]; + fixture.componentInstance.choices = [0, 1, 4, 7]; fixture.detectChanges(); tick(); @@ -548,7 +549,7 @@ describe('IgxRadioGroupDirective', () => { fixture.detectChanges(); tick(); - spyOn(radioGroup.radioButtons.toArray()[1].nativeElement, 'focus'); + vi.spyOn(radioGroup.radioButtons.toArray()[1].nativeElement, 'focus'); const groupElement = fixture.debugElement.query(By.css('igx-radio-group')).nativeElement; const event = new KeyboardEvent('keydown', { key: 'ArrowDown' }); @@ -571,7 +572,7 @@ describe('IgxRadioGroupDirective', () => { fixture.detectChanges(); tick(); - spyOn(firstButton.nativeElement, 'blur'); + vi.spyOn(firstButton.nativeElement, 'blur'); const groupElement = fixture.debugElement.query(By.css('igx-radio-group')).nativeElement; const event = new KeyboardEvent('keydown', { key: 'ArrowDown' }); @@ -595,7 +596,7 @@ describe('IgxRadioGroupDirective', () => { const groupElement = fixture.debugElement.query(By.css('igx-radio-group')).nativeElement; const event = new KeyboardEvent('keydown', { key: 'ArrowDown', cancelable: true }); - spyOn(event, 'preventDefault'); + vi.spyOn(event, 'preventDefault'); groupElement.dispatchEvent(event); fixture.detectChanges(); @@ -718,7 +719,8 @@ describe('IgxRadioGroupDirective', () => { imports: [IgxRadioGroupDirective, IgxRadioComponent] }) class RadioGroupSimpleComponent { - @ViewChild('radioGroup', { read: IgxRadioGroupDirective, static: true }) public radioGroup: IgxRadioGroupDirective; + @ViewChild('radioGroup', { read: IgxRadioGroupDirective, static: true }) + public radioGroup: IgxRadioGroupDirective; } @Component({ @@ -733,7 +735,8 @@ class RadioGroupSimpleComponent { imports: [IgxRadioComponent, IgxRadioGroupDirective] }) class RadioGroupComponent { - @ViewChild('radioGroup', { read: IgxRadioGroupDirective, static: true }) public radioGroup: IgxRadioGroupDirective; + @ViewChild('radioGroup', { read: IgxRadioGroupDirective, static: true }) + public radioGroup: IgxRadioGroupDirective; } @Component({ @@ -748,7 +751,8 @@ class RadioGroupComponent { imports: [IgxRadioComponent, IgxRadioGroupDirective] }) class RadioGroupRequiredComponent { - @ViewChild('radioGroup', { read: IgxRadioGroupDirective, static: true }) public radioGroup: IgxRadioGroupDirective; + @ViewChild('radioGroup', { read: IgxRadioGroupDirective, static: true }) + public radioGroup: IgxRadioGroupDirective; } interface Person { @@ -790,7 +794,8 @@ class RadioGroupOnPushComponent { imports: [IgxRadioComponent, IgxRadioGroupDirective, FormsModule] }) class RadioGroupWithModelComponent { - @ViewChild('radioGroupSeasons', { read: IgxRadioGroupDirective, static: true }) public radioGroup: IgxRadioGroupDirective; + @ViewChild('radioGroupSeasons', { read: IgxRadioGroupDirective, static: true }) + public radioGroup: IgxRadioGroupDirective; public seasons = [ 'Winter', @@ -894,7 +899,7 @@ class RadioGroupDeepProjectionComponent { } @Component({ - template: ` + template: ` `, - imports: [IgxRadioComponent, IgxRadioGroupDirective] + imports: [IgxRadioComponent, IgxRadioGroupDirective] }) class RadioGroupTestComponent implements OnInit { @@ -915,7 +920,10 @@ class RadioGroupTestComponent implements OnInit { public required = false; public value: any; - public radios: { label: string; value: any }[] = []; + public radios: { + label: string; + value: any; + }[] = []; public handleChange(args: any) { this.value = args.value; @@ -924,11 +932,10 @@ class RadioGroupTestComponent implements OnInit { public ngOnInit(): void { this.container.clear(); this.radios.forEach((option) => { - const componentRef: ComponentRef = - this.container.createComponent(IgxRadioComponent); + const componentRef: ComponentRef = this.container.createComponent(IgxRadioComponent); componentRef.instance.placeholderLabel.nativeElement.textContent = - option.label; + option.label; componentRef.instance.value = option.value; }); } @@ -972,7 +979,8 @@ class DynamicRadioGroupComponent { imports: [IgxRadioGroupDirective, IgxRadioComponent] }) class RadioGroupVerticalComponent { - @ViewChild('radioGroup', { read: IgxRadioGroupDirective, static: true }) public radioGroup: IgxRadioGroupDirective; + @ViewChild('radioGroup', { read: IgxRadioGroupDirective, static: true }) + public radioGroup: IgxRadioGroupDirective; } const dispatchRadioEvent = (eventName, radioNativeElement, fixture) => { diff --git a/projects/igniteui-angular/radio/src/radio/radio.component.spec.ts b/projects/igniteui-angular/radio/src/radio/radio.component.spec.ts index cd8447ce251..91bc1a2b51c 100644 --- a/projects/igniteui-angular/radio/src/radio/radio.component.spec.ts +++ b/projects/igniteui-angular/radio/src/radio/radio.component.spec.ts @@ -5,6 +5,7 @@ import { By } from '@angular/platform-browser'; import { IgxRadioComponent } from './radio.component'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('IgxRadio', () => { @@ -262,7 +263,8 @@ describe('IgxRadio', () => { imports: [IgxRadioComponent] }) class InitRadioComponent { - @ViewChild('radio', { static: true }) public radio: IgxRadioComponent; + @ViewChild('radio', { static: true }) + public radio: IgxRadioComponent; } @Component({ @@ -274,7 +276,8 @@ class InitRadioComponent { imports: [FormsModule, IgxRadioComponent] }) class RadioWithModelComponent { - @ViewChildren(IgxRadioComponent) public radios; + @ViewChildren(IgxRadioComponent) + public radios; public selected = 'Foo'; } @@ -292,15 +295,16 @@ class RadioWithModelComponent { imports: [FormsModule, IgxRadioComponent] }) class DisabledRadioComponent { - @ViewChildren(IgxRadioComponent) public radios; + @ViewChildren(IgxRadioComponent) + public radios; public items = [{ - value: 'Foo', - disabled: false - }, { - value: 'Bar', - disabled: true - }]; + value: 'Foo', + disabled: false + }, { + value: 'Bar', + disabled: true + }]; public selected = 'Foo'; } @@ -318,7 +322,8 @@ class DisabledRadioComponent { imports: [FormsModule, IgxRadioComponent] }) class RequiredRadioComponent { - @ViewChildren(IgxRadioComponent) public radios; + @ViewChildren(IgxRadioComponent) + public radios; } @Component({ @@ -327,7 +332,8 @@ class RequiredRadioComponent { imports: [IgxRadioComponent] }) class RadioExternalLabelComponent { - @ViewChild('radio', { static: true }) public radio: IgxRadioComponent; + @ViewChild('radio', { static: true }) + public radio: IgxRadioComponent; public label = 'My Label'; } @@ -336,7 +342,8 @@ class RadioExternalLabelComponent { imports: [IgxRadioComponent] }) class RadioInvisibleLabelComponent { - @ViewChild('radio', { static: true }) public radio: IgxRadioComponent; + @ViewChild('radio', { static: true }) + public radio: IgxRadioComponent; public label = 'Invisible Label'; } diff --git a/projects/igniteui-angular/schematics/ng-add/index.spec.ts b/projects/igniteui-angular/schematics/ng-add/index.spec.ts index 6b4662db54b..e25d65db4e7 100644 --- a/projects/igniteui-angular/schematics/ng-add/index.spec.ts +++ b/projects/igniteui-angular/schematics/ng-add/index.spec.ts @@ -1,3 +1,4 @@ +import { describe, it, expect, beforeEach } from 'vitest'; import { EmptyTree } from '@angular-devkit/schematics'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; import * as path from 'path'; @@ -6,255 +7,255 @@ import { DEPENDENCIES_MAP, PackageTarget, PackageEntry } from '../utils/dependen import { ProjectType } from '../utils/util'; describe('ng-add schematics', () => { - const collectionPath = path.join(__dirname, '../collection.json'); - const runner: SchematicTestRunner = new SchematicTestRunner('cli-schematics', collectionPath); - let tree: UnitTestTree; - const sourceRoot = 'testSrc'; - const ngJsonConfig = { - version: 1, - projects: { - testProj: { - root: '/', - sourceRoot, - projectType: ProjectType.Application, - architect: { - serve: {}, - build: { - options: { - main: `${sourceRoot}/main.ts`, - polyfills: `${sourceRoot}/polyfills.ts`, - scripts: [] + const collectionPath = path.join(__dirname, '../collection.json'); + const runner: SchematicTestRunner = new SchematicTestRunner('cli-schematics', collectionPath); + let tree: UnitTestTree; + const sourceRoot = 'testSrc'; + const ngJsonConfig = { + version: 1, + projects: { + testProj: { + root: '/', + sourceRoot, + projectType: ProjectType.Application, + architect: { + serve: {}, + build: { + options: { + main: `${sourceRoot}/main.ts`, + polyfills: `${sourceRoot}/polyfills.ts`, + scripts: [] + } + }, + test: { + options: { + main: `${sourceRoot}/test.ts`, + polyfills: `${sourceRoot}/polyfills.ts`, + scripts: [] + } + }, + } } - }, - test: { - options: { - main: `${sourceRoot}/test.ts`, - polyfills: `${sourceRoot}/polyfills.ts`, - scripts: [] - } - }, } - } - } - }; - - const pkgJsonConfig = { - dependencies: {}, - devDependencies: {} - }; - - const resetJsonConfigs = (treeArg: UnitTestTree) => { - treeArg.overwrite('/angular.json', JSON.stringify(ngJsonConfig)); - treeArg.overwrite('/package.json', JSON.stringify(pkgJsonConfig)); - }; - - beforeEach(() => { - tree = new UnitTestTree(new EmptyTree()); - tree.create('/angular.json', JSON.stringify(ngJsonConfig)); - tree.create('/package.json', JSON.stringify(pkgJsonConfig)); - tree.create(`${sourceRoot}/main.ts`, '// test comment'); - tree.create(`${sourceRoot}/test.ts`, '// test comment'); - }); - - it('should include ALL dependencies in map', () => { - const pkgJson = require('../../package.json'); - const allDependencies = Object.assign({}, pkgJson.dependencies, pkgJson.peerDependencies, pkgJson.igxDevDependencies); - for (const key of Object.keys(allDependencies)) { - const expectedPackages: PackageEntry = { - name: key, - target: jasmine.anything() as any - }; - expect(DEPENDENCIES_MAP).toContain(expectedPackages, `Dependency ${key} missing in dependencies map!`); - } - }); - - it('should add packages to package.json dependencies', async () => { - const expectedDeps = DEPENDENCIES_MAP.filter(dep => dep.target === PackageTarget.REGULAR).map(dep => dep.name); - const expectedDevDeps = DEPENDENCIES_MAP.filter(dep => dep.target === PackageTarget.DEV).map(dep => dep.name); - await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); - const pkgJsonData = JSON.parse(tree.readContent('/package.json')); - expect(pkgJsonData.dependencies).toBeTruthy(); - expect(pkgJsonData.devDependencies).toBeTruthy(); - // Check for explicit dependencies - expect(Object.keys(pkgJsonData.dependencies).length).toEqual(expectedDeps.length, `Different number of added dependencies!`); - expect(Object.keys(pkgJsonData.devDependencies).length).toEqual(expectedDevDeps.length, `Different number of added devDependencies!`); - for (const dependency of expectedDeps) { - expect(pkgJsonData.dependencies.hasOwnProperty(dependency)).toEqual(true, `Dependency ${dependency} is missing from output!`); - } - for (const dependency of expectedDevDeps) { - expect(pkgJsonData.devDependencies.hasOwnProperty(dependency)).toEqual(true, `DevDependency ${dependency} is missing from output!`); - } - }); - - it('should add the correct igniteui-angular packages to package.json dependencies', async () => { - await runner.runSchematic('ng-add', { normalizeCss: false }, tree); - const pkgJsonData = JSON.parse(tree.readContent('/package.json')); - // hammer is optional now. - expect(pkgJsonData.dependencies['hammerjs']).toBeFalsy(); - }); - - it('should add hammerjs dependency to package.json dependencies if addHammer prompt is set.', async () => { - await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); - const pkgJsonData = JSON.parse(tree.readContent('/package.json')); - expect(pkgJsonData.dependencies['hammerjs']).toBeTruthy(); - }); - - it('should NOT add hammer.js to the main.ts file', async () => { - await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); - const mainTs = tree.read(`${sourceRoot}/main.ts`).toString(); - expect(mainTs).not.toContain('import \'hammerjs\';'); - }); - - it('should NOT add hammer.js to the test.ts file', async () => { - await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); - const testTs = tree.read(`${sourceRoot}/test.ts`).toString(); - expect(testTs).not.toContain('import \'hammerjs\';'); - }); - - // Hammer is optional now. - it('should not add hammer.js in angular.json build options under scripts', async () => { - await runner.runSchematic('ng-add', { normalizeCss: false }, tree); - const ngJsonConfigResult = JSON.parse(tree.read('/angular.json').toString()); - expect(ngJsonConfigResult.projects.testProj.architect.build.options.scripts).not.toContain('./node_modules/hammerjs/hammer.min.js'); - }); - - it('should add hammer.js in angular.json build options under scripts if addHammer prompt is set.', async () => { - await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); - const ngJsonConfigResult = JSON.parse(tree.read('/angular.json').toString()); - expect(ngJsonConfigResult.projects.testProj.architect.build.options.scripts).toContain('./node_modules/hammerjs/hammer.min.js'); - }); - - // Hammer is optional now. - it('should not add hammer.js in angular.json test options under scripts', async () => { - await runner.runSchematic('ng-add', { normalizeCss: false }, tree); - const ngJsonConfigResult = JSON.parse(tree.read('/angular.json').toString()); - expect(ngJsonConfigResult.projects.testProj.architect.test.options.scripts).not.toContain('./node_modules/hammerjs/hammer.min.js'); - }); - - it('should add hammer.js in angular.json test options under scripts if addHammer prompt is set.', async () => { - await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); - const ngJsonConfigResult = JSON.parse(tree.read('/angular.json').toString()); - expect(ngJsonConfigResult.projects.testProj.architect.test.options.scripts).toContain('./node_modules/hammerjs/hammer.min.js'); - }); - - it('should NOT duplicate hammer.js if it exists in angular.json build options', async () => { - const ngJsonConfig1 = JSON.parse(tree.read('/angular.json').toString()); - ngJsonConfig1.projects.testProj.architect.build.options.scripts.push('./node_modules/hammerjs/hammer.min.js'); - tree.overwrite('/angular.json', JSON.stringify(ngJsonConfig1)); - await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); - - const ngJsonConfigResult = JSON.parse(tree.read('/angular.json').toString()); - expect(ngJsonConfigResult.projects.testProj.architect.build.options.scripts.length).toBe(1); - expect(ngJsonConfigResult.projects.testProj.architect.build.options.scripts).toMatch('./node_modules/hammerjs/hammer.min.js'); - }); - - it('should NOT duplicate hammer.js if it exists in angular.json test options', async () => { - const ngJsonConfig1 = JSON.parse(tree.read('/angular.json').toString()); - ngJsonConfig1.projects.testProj.architect.test.options.scripts.push('./node_modules/hammerjs/hammer.min.js'); - tree.overwrite('/angular.json', JSON.stringify(ngJsonConfig1)); - await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); - - const ngJsonConfigResult = JSON.parse(tree.read('/angular.json').toString()); - expect(ngJsonConfigResult.projects.testProj.architect.test.options.scripts.length).toBe(1); - expect(ngJsonConfigResult.projects.testProj.architect.test.options.scripts).toMatch('./node_modules/hammerjs/hammer.min.js'); - }); - - it('should NOT add hammer.js to main.ts if it exists in angular.json build options', async () => { - const ngJsonConfig1 = JSON.parse(tree.read('/angular.json').toString()); - ngJsonConfig1.projects.testProj.architect.build.options.scripts.push('./node_modules/hammerjs/hammer.min.js'); - tree.overwrite('/angular.json', JSON.stringify(ngJsonConfig1)); - await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); - - const newContent = tree.read(`${sourceRoot}/main.ts`).toString(); - expect(newContent).toMatch('// test comment'); - }); - - it('should NOT add hammer.js to test.ts if it exists in angular.json test options', async () => { - const ngJsonConfig1 = JSON.parse(tree.read('/angular.json').toString()); - ngJsonConfig1.projects.testProj.architect.test.options.scripts.push('./node_modules/hammerjs/hammer.min.js'); - tree.overwrite('/angular.json', JSON.stringify(ngJsonConfig1)); - await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); - - const newContent = tree.read(`${sourceRoot}/test.ts`).toString(); - expect(newContent).toMatch('// test comment'); - }); - - // Hammer is optional now. - it('should not add hammer.js to package.json dependencies', async () => { - await runner.runSchematic('ng-add', { normalizeCss: false }, tree); - const pkgJsonData = JSON.parse(tree.readContent('/package.json')); - expect(pkgJsonData.dependencies['hammerjs']).toBeFalsy(); - }); - - it('should add hammer.js to package.json dependencies if addHammer prompt is set.', async () => { - await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); - const pkgJsonData = JSON.parse(tree.readContent('/package.json')); - expect(pkgJsonData.dependencies['hammerjs']).toBeTruthy(); - }); - - it('should NOT add hammer.js to angular.json if it exists in main.ts options', async () => { - const mainTsPath = `${sourceRoot}/main.ts`; - const content = tree.read(mainTsPath).toString(); - tree.overwrite(mainTsPath, 'import \'hammerjs\';\n' + content); - await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); - - const ngJsonConfigResult = JSON.parse(tree.read('/angular.json').toString()); - expect(ngJsonConfigResult.projects.testProj.architect.build.options.scripts.length).toBe(0); - expect(ngJsonConfigResult.projects.testProj.architect.build.options.scripts).not.toContain('./node_modules/hammerjs/hammer.min.js'); - }); - - it('should add the CLI only to devDependencies', async () => { - await runner.runSchematic('ng-add', { normalizeCss: false }, tree); - const pkgJsonData = JSON.parse(tree.readContent('/package.json')); - - const version = require('../../package.json')['igxDevDependencies']['@igniteui/angular-schematics']; - expect(pkgJsonData.devDependencies['@igniteui/angular-schematics']).toBe(version); - expect(pkgJsonData.dependencies['@igniteui/angular-schematics']).toBeFalsy(); - }); - - it('should properly add css reset', async () => { - tree.create(`${sourceRoot}/styles.scss`, ''); - await runner.runSchematic('ng-add', { normalizeCss: true }, tree); - let pkgJsonData = JSON.parse(tree.readContent('/package.json')); - expect(tree.readContent(`${sourceRoot}/styles.scss`)).toEqual(scssImport); - expect(pkgJsonData.dependencies['minireset.css']).toBeTruthy(); - resetJsonConfigs(tree); - tree.delete(`${sourceRoot}/styles.scss`); - - tree.create(`${sourceRoot}/styles.sass`, ''); - await runner.runSchematic('ng-add', { normalizeCss: true }, tree); - pkgJsonData = JSON.parse(tree.readContent('/package.json')); - expect(tree.readContent(`${sourceRoot}/styles.sass`)).toEqual(scssImport); - expect(pkgJsonData.dependencies['minireset.css']).toBeTruthy(); - resetJsonConfigs(tree); - tree.delete(`${sourceRoot}/styles.sass`); - - tree.create(`${sourceRoot}/styles.css`, ''); - await runner.runSchematic('ng-add', { normalizeCss: true }, tree); - pkgJsonData = JSON.parse(tree.readContent('/package.json')); - expect(tree.readContent(`${sourceRoot}/styles.css`)).toBe(''); - expect(pkgJsonData.dependencies['minireset.css']).toBeTruthy(); - expect(JSON.parse(tree.readContent('/angular.json')).projects['testProj'].architect.build.options.styles).toContain(cssImport); - resetJsonConfigs(tree); - tree.delete(`${sourceRoot}/styles.css`); - - tree.create(`${sourceRoot}/styles.less`, ''); - await runner.runSchematic('ng-add', { normalizeCss: true }, tree); - pkgJsonData = JSON.parse(tree.readContent('/package.json')); - expect(tree.readContent(`${sourceRoot}/styles.less`)).toBe(''); - expect(pkgJsonData.dependencies['minireset.css']).toBeTruthy(); - expect(JSON.parse(tree.readContent('/angular.json')).projects['testProj'].architect.build.options.styles).toContain(cssImport); - resetJsonConfigs(tree); - tree.delete(`${sourceRoot}/styles.less`); - - tree.create(`${sourceRoot}/styles.styl`, ''); - await runner.runSchematic('ng-add', { normalizeCss: true }, tree); - pkgJsonData = JSON.parse(tree.readContent('/package.json')); - expect(tree.readContent(`${sourceRoot}/styles.styl`)).toBe(''); - expect(pkgJsonData.dependencies['minireset.css']).toBeTruthy(); - expect(JSON.parse(tree.readContent('/angular.json')).projects['testProj'].architect.build.options.styles).toContain(cssImport); - resetJsonConfigs(tree); - tree.delete(`${sourceRoot}/styles.styl`); - }); + }; + + const pkgJsonConfig = { + dependencies: {}, + devDependencies: {} + }; + + const resetJsonConfigs = (treeArg: UnitTestTree) => { + treeArg.overwrite('/angular.json', JSON.stringify(ngJsonConfig)); + treeArg.overwrite('/package.json', JSON.stringify(pkgJsonConfig)); + }; + + beforeEach(() => { + tree = new UnitTestTree(new EmptyTree()); + tree.create('/angular.json', JSON.stringify(ngJsonConfig)); + tree.create('/package.json', JSON.stringify(pkgJsonConfig)); + tree.create(`${sourceRoot}/main.ts`, '// test comment'); + tree.create(`${sourceRoot}/test.ts`, '// test comment'); + }); + + it('should include ALL dependencies in map', () => { + const pkgJson = require('../../package.json'); + const allDependencies = Object.assign({}, pkgJson.dependencies, pkgJson.peerDependencies, pkgJson.igxDevDependencies); + for (const key of Object.keys(allDependencies)) { + const expectedPackages: PackageEntry = { + name: key, + target: expect.anything() as any + }; + expect(DEPENDENCIES_MAP).toContain(expectedPackages); + } + }); + + it('should add packages to package.json dependencies', async () => { + const expectedDeps = DEPENDENCIES_MAP.filter(dep => dep.target === PackageTarget.REGULAR).map(dep => dep.name); + const expectedDevDeps = DEPENDENCIES_MAP.filter(dep => dep.target === PackageTarget.DEV).map(dep => dep.name); + await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); + const pkgJsonData = JSON.parse(tree.readContent('/package.json')); + expect(pkgJsonData.dependencies).toBeTruthy(); + expect(pkgJsonData.devDependencies).toBeTruthy(); + // Check for explicit dependencies + expect(Object.keys(pkgJsonData.dependencies).length).toEqual(expectedDeps.length); + expect(Object.keys(pkgJsonData.devDependencies).length).toEqual(expectedDevDeps.length); + for (const dependency of expectedDeps) { + expect(pkgJsonData.dependencies.hasOwnProperty(dependency)).toEqual(true); + } + for (const dependency of expectedDevDeps) { + expect(pkgJsonData.devDependencies.hasOwnProperty(dependency)).toEqual(true); + } + }); + + it('should add the correct igniteui-angular packages to package.json dependencies', async () => { + await runner.runSchematic('ng-add', { normalizeCss: false }, tree); + const pkgJsonData = JSON.parse(tree.readContent('/package.json')); + // hammer is optional now. + expect(pkgJsonData.dependencies['hammerjs']).toBeFalsy(); + }); + + it('should add hammerjs dependency to package.json dependencies if addHammer prompt is set.', async () => { + await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); + const pkgJsonData = JSON.parse(tree.readContent('/package.json')); + expect(pkgJsonData.dependencies['hammerjs']).toBeTruthy(); + }); + + it('should NOT add hammer.js to the main.ts file', async () => { + await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); + const mainTs = tree.read(`${sourceRoot}/main.ts`).toString(); + expect(mainTs).not.toContain('import \'hammerjs\';'); + }); + + it('should NOT add hammer.js to the test.ts file', async () => { + await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); + const testTs = tree.read(`${sourceRoot}/test.ts`).toString(); + expect(testTs).not.toContain('import \'hammerjs\';'); + }); + + // Hammer is optional now. + it('should not add hammer.js in angular.json build options under scripts', async () => { + await runner.runSchematic('ng-add', { normalizeCss: false }, tree); + const ngJsonConfigResult = JSON.parse(tree.read('/angular.json').toString()); + expect(ngJsonConfigResult.projects.testProj.architect.build.options.scripts).not.toContain('./node_modules/hammerjs/hammer.min.js'); + }); + + it('should add hammer.js in angular.json build options under scripts if addHammer prompt is set.', async () => { + await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); + const ngJsonConfigResult = JSON.parse(tree.read('/angular.json').toString()); + expect(ngJsonConfigResult.projects.testProj.architect.build.options.scripts).toContain('./node_modules/hammerjs/hammer.min.js'); + }); + + // Hammer is optional now. + it('should not add hammer.js in angular.json test options under scripts', async () => { + await runner.runSchematic('ng-add', { normalizeCss: false }, tree); + const ngJsonConfigResult = JSON.parse(tree.read('/angular.json').toString()); + expect(ngJsonConfigResult.projects.testProj.architect.test.options.scripts).not.toContain('./node_modules/hammerjs/hammer.min.js'); + }); + + it('should add hammer.js in angular.json test options under scripts if addHammer prompt is set.', async () => { + await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); + const ngJsonConfigResult = JSON.parse(tree.read('/angular.json').toString()); + expect(ngJsonConfigResult.projects.testProj.architect.test.options.scripts).toContain('./node_modules/hammerjs/hammer.min.js'); + }); + + it('should NOT duplicate hammer.js if it exists in angular.json build options', async () => { + const ngJsonConfig1 = JSON.parse(tree.read('/angular.json').toString()); + ngJsonConfig1.projects.testProj.architect.build.options.scripts.push('./node_modules/hammerjs/hammer.min.js'); + tree.overwrite('/angular.json', JSON.stringify(ngJsonConfig1)); + await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); + + const ngJsonConfigResult = JSON.parse(tree.read('/angular.json').toString()); + expect(ngJsonConfigResult.projects.testProj.architect.build.options.scripts.length).toBe(1); + expect(ngJsonConfigResult.projects.testProj.architect.build.options.scripts).toMatch('./node_modules/hammerjs/hammer.min.js'); + }); + + it('should NOT duplicate hammer.js if it exists in angular.json test options', async () => { + const ngJsonConfig1 = JSON.parse(tree.read('/angular.json').toString()); + ngJsonConfig1.projects.testProj.architect.test.options.scripts.push('./node_modules/hammerjs/hammer.min.js'); + tree.overwrite('/angular.json', JSON.stringify(ngJsonConfig1)); + await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); + + const ngJsonConfigResult = JSON.parse(tree.read('/angular.json').toString()); + expect(ngJsonConfigResult.projects.testProj.architect.test.options.scripts.length).toBe(1); + expect(ngJsonConfigResult.projects.testProj.architect.test.options.scripts).toMatch('./node_modules/hammerjs/hammer.min.js'); + }); + + it('should NOT add hammer.js to main.ts if it exists in angular.json build options', async () => { + const ngJsonConfig1 = JSON.parse(tree.read('/angular.json').toString()); + ngJsonConfig1.projects.testProj.architect.build.options.scripts.push('./node_modules/hammerjs/hammer.min.js'); + tree.overwrite('/angular.json', JSON.stringify(ngJsonConfig1)); + await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); + + const newContent = tree.read(`${sourceRoot}/main.ts`).toString(); + expect(newContent).toMatch('// test comment'); + }); + + it('should NOT add hammer.js to test.ts if it exists in angular.json test options', async () => { + const ngJsonConfig1 = JSON.parse(tree.read('/angular.json').toString()); + ngJsonConfig1.projects.testProj.architect.test.options.scripts.push('./node_modules/hammerjs/hammer.min.js'); + tree.overwrite('/angular.json', JSON.stringify(ngJsonConfig1)); + await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); + + const newContent = tree.read(`${sourceRoot}/test.ts`).toString(); + expect(newContent).toMatch('// test comment'); + }); + + // Hammer is optional now. + it('should not add hammer.js to package.json dependencies', async () => { + await runner.runSchematic('ng-add', { normalizeCss: false }, tree); + const pkgJsonData = JSON.parse(tree.readContent('/package.json')); + expect(pkgJsonData.dependencies['hammerjs']).toBeFalsy(); + }); + + it('should add hammer.js to package.json dependencies if addHammer prompt is set.', async () => { + await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); + const pkgJsonData = JSON.parse(tree.readContent('/package.json')); + expect(pkgJsonData.dependencies['hammerjs']).toBeTruthy(); + }); + + it('should NOT add hammer.js to angular.json if it exists in main.ts options', async () => { + const mainTsPath = `${sourceRoot}/main.ts`; + const content = tree.read(mainTsPath).toString(); + tree.overwrite(mainTsPath, 'import \'hammerjs\';\n' + content); + await runner.runSchematic('ng-add', { normalizeCss: false, addHammer: true }, tree); + + const ngJsonConfigResult = JSON.parse(tree.read('/angular.json').toString()); + expect(ngJsonConfigResult.projects.testProj.architect.build.options.scripts.length).toBe(0); + expect(ngJsonConfigResult.projects.testProj.architect.build.options.scripts).not.toContain('./node_modules/hammerjs/hammer.min.js'); + }); + + it('should add the CLI only to devDependencies', async () => { + await runner.runSchematic('ng-add', { normalizeCss: false }, tree); + const pkgJsonData = JSON.parse(tree.readContent('/package.json')); + + const version = require('../../package.json')['igxDevDependencies']['@igniteui/angular-schematics']; + expect(pkgJsonData.devDependencies['@igniteui/angular-schematics']).toBe(version); + expect(pkgJsonData.dependencies['@igniteui/angular-schematics']).toBeFalsy(); + }); + + it('should properly add css reset', async () => { + tree.create(`${sourceRoot}/styles.scss`, ''); + await runner.runSchematic('ng-add', { normalizeCss: true }, tree); + let pkgJsonData = JSON.parse(tree.readContent('/package.json')); + expect(tree.readContent(`${sourceRoot}/styles.scss`)).toEqual(scssImport); + expect(pkgJsonData.dependencies['minireset.css']).toBeTruthy(); + resetJsonConfigs(tree); + tree.delete(`${sourceRoot}/styles.scss`); + + tree.create(`${sourceRoot}/styles.sass`, ''); + await runner.runSchematic('ng-add', { normalizeCss: true }, tree); + pkgJsonData = JSON.parse(tree.readContent('/package.json')); + expect(tree.readContent(`${sourceRoot}/styles.sass`)).toEqual(scssImport); + expect(pkgJsonData.dependencies['minireset.css']).toBeTruthy(); + resetJsonConfigs(tree); + tree.delete(`${sourceRoot}/styles.sass`); + + tree.create(`${sourceRoot}/styles.css`, ''); + await runner.runSchematic('ng-add', { normalizeCss: true }, tree); + pkgJsonData = JSON.parse(tree.readContent('/package.json')); + expect(tree.readContent(`${sourceRoot}/styles.css`)).toBe(''); + expect(pkgJsonData.dependencies['minireset.css']).toBeTruthy(); + expect(JSON.parse(tree.readContent('/angular.json')).projects['testProj'].architect.build.options.styles).toContain(cssImport); + resetJsonConfigs(tree); + tree.delete(`${sourceRoot}/styles.css`); + + tree.create(`${sourceRoot}/styles.less`, ''); + await runner.runSchematic('ng-add', { normalizeCss: true }, tree); + pkgJsonData = JSON.parse(tree.readContent('/package.json')); + expect(tree.readContent(`${sourceRoot}/styles.less`)).toBe(''); + expect(pkgJsonData.dependencies['minireset.css']).toBeTruthy(); + expect(JSON.parse(tree.readContent('/angular.json')).projects['testProj'].architect.build.options.styles).toContain(cssImport); + resetJsonConfigs(tree); + tree.delete(`${sourceRoot}/styles.less`); + + tree.create(`${sourceRoot}/styles.styl`, ''); + await runner.runSchematic('ng-add', { normalizeCss: true }, tree); + pkgJsonData = JSON.parse(tree.readContent('/package.json')); + expect(tree.readContent(`${sourceRoot}/styles.styl`)).toBe(''); + expect(pkgJsonData.dependencies['minireset.css']).toBeTruthy(); + expect(JSON.parse(tree.readContent('/angular.json')).projects['testProj'].architect.build.options.styles).toContain(cssImport); + resetJsonConfigs(tree); + tree.delete(`${sourceRoot}/styles.styl`); + }); }); diff --git a/projects/igniteui-angular/select/src/select/select.component.spec.ts b/projects/igniteui-angular/select/src/select/select.component.spec.ts index d0ee4095bc1..7bd220a46a6 100644 --- a/projects/igniteui-angular/select/src/select/select.component.spec.ts +++ b/projects/igniteui-angular/select/src/select/select.component.spec.ts @@ -4,6 +4,7 @@ import { TestBed, tick, fakeAsync, waitForAsync, discardPeriodicTasks } from '@a import { FormsModule, UntypedFormGroup, UntypedFormBuilder, UntypedFormControl, Validators, ReactiveFormsModule, NgForm, NgControl } from '@angular/forms'; import { By } from '@angular/platform-browser'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { describe, it, test, expect, beforeEach, afterAll, vi } from 'vitest'; import { IGX_DROPDOWN_BASE, IgxDropDownItemComponent, ISelectionEventArgs } from '../../../drop-down/src/drop-down/public_api'; import { IgxHintDirective, IgxInputState, IgxLabelDirective, IgxPrefixDirective, IgxSuffixDirective } from '../../../input-group/src/public_api'; @@ -175,9 +176,7 @@ describe('igxSelect', () => { const customOverlaySettings = { modal: true, closeOnOutsideClick: false, - positionStrategy: new ConnectedPositioningStrategy( - positionSettings - ), + positionStrategy: new ConnectedPositioningStrategy(positionSettings), scrollStrategy: new AbsoluteScrollStrategy() }; select.overlaySettings = customOverlaySettings; @@ -215,7 +214,7 @@ describe('igxSelect', () => { })); it('should close dropdown on clicking selected item', fakeAsync(() => { - spyOn(select.selectionChanging, 'emit'); + vi.spyOn(select.selectionChanging, 'emit'); select.items[1].selected = true; select.open(); fixture.detectChanges(); @@ -289,13 +288,13 @@ describe('igxSelect', () => { const inputGroup = fixture.debugElement.query(By.css('.' + CSS_CLASS_INPUT_GROUP)); expect(select).toBeTruthy(); - spyOn(select.opening, 'emit'); - spyOn(select.opened, 'emit'); - spyOn(select.closing, 'emit'); - spyOn(select.closed, 'emit'); - spyOn(select, 'toggle').and.callThrough(); - spyOn(select, 'open').and.callThrough(); - spyOn(select, 'close').and.callThrough(); + vi.spyOn(select.opening, 'emit'); + vi.spyOn(select.opened, 'emit'); + vi.spyOn(select.closing, 'emit'); + vi.spyOn(select.closed, 'emit'); + vi.spyOn(select, 'toggle'); + vi.spyOn(select, 'open'); + vi.spyOn(select, 'close'); inputGroup.nativeElement.click(); tick(); @@ -328,8 +327,8 @@ describe('igxSelect', () => { fixture.detectChanges(); expect(select.collapsed).toBeFalsy(); - spyOn(select.closing, 'emit'); - spyOn(select.closed, 'emit'); + vi.spyOn(select.closing, 'emit'); + vi.spyOn(select.closed, 'emit'); selectedItemEl.nativeElement.click(); tick(); @@ -342,13 +341,13 @@ describe('igxSelect', () => { const toggleBtn = fixture.debugElement.query(By.css('.' + CSS_CLASS_TOGGLE_BUTTON)); expect(select).toBeTruthy(); - spyOn(select.opening, 'emit'); - spyOn(select.opened, 'emit'); - spyOn(select.closing, 'emit'); - spyOn(select.closed, 'emit'); - spyOn(select, 'toggle').and.callThrough(); - spyOn(select, 'open').and.callThrough(); - spyOn(select, 'close').and.callThrough(); + vi.spyOn(select.opening, 'emit'); + vi.spyOn(select.opened, 'emit'); + vi.spyOn(select.closing, 'emit'); + vi.spyOn(select.closed, 'emit'); + vi.spyOn(select, 'toggle'); + vi.spyOn(select, 'open'); + vi.spyOn(select, 'close'); toggleBtn.nativeElement.click(); tick(); @@ -363,8 +362,8 @@ describe('igxSelect', () => { it('should emit closing events on input blur when closeOnOutsideClick: true (default value)', fakeAsync(() => { const dummyInput = fixture.componentInstance.dummyInput.nativeElement; - spyOn(select.closing, 'emit'); - spyOn(select.closed, 'emit'); + vi.spyOn(select.closing, 'emit'); + vi.spyOn(select.closed, 'emit'); expect(select).toBeDefined(); select.toggle(); @@ -385,8 +384,8 @@ describe('igxSelect', () => { it('should NOT emit closing events on input blur when closeOnOutsideClick: false', fakeAsync(() => { const dummyInput = fixture.componentInstance.dummyInput.nativeElement; - spyOn(select.closing, 'emit'); - spyOn(select.closed, 'emit'); + vi.spyOn(select.closing, 'emit'); + vi.spyOn(select.closed, 'emit'); const customOverlaySettings = { closeOnOutsideClick: false @@ -683,7 +682,7 @@ describe('igxSelect', () => { // no validator, but there is a set error expect(selectComp.input.valid).toBe(IgxInputState.INVALID); - expect((selectComp as any).inputGroup.element.nativeElement).toHaveClass(CSS_CLASS_INPUT_GROUP_INVALID); + expect((selectComp as any).inputGroup.element.nativeElement.classList.contains(CSS_CLASS_INPUT_GROUP_INVALID)).toBe(true); expect((selectComp as any).inputGroup.element.nativeElement.classList.contains(CSS_CLASS_INPUT_GROUP_REQUIRED)).toBe(false); })); @@ -774,8 +773,8 @@ describe('igxSelect', () => { select = fix.componentInstance.select; const input = fix.debugElement.query(By.css(`.${CSS_CLASS_INPUT}`)); - spyOn(select, 'onFocus'); - spyOn(select, 'onBlur'); + vi.spyOn(select, 'onFocus'); + vi.spyOn(select, 'onBlur'); input.triggerEventHandler('focus', {}); expect(select.onFocus).toHaveBeenCalled(); @@ -1084,26 +1083,25 @@ describe('igxSelect', () => { checkInputValue(); })); - it('should not append any text to the input box when no item is selected and value is not set or does not match any item', - fakeAsync(() => { - // There is not a selected item initially - expect(select.selectedItem).toBeUndefined(); - expect(select.value).toBeNull(); - expect(select.input.value).toEqual(''); - expect(inputElement.nativeElement.textContent).toEqual(''); + it('should not append any text to the input box when no item is selected and value is not set or does not match any item', fakeAsync(() => { + // There is not a selected item initially + expect(select.selectedItem).toBeUndefined(); + expect(select.value).toBeNull(); + expect(select.input.value).toEqual(''); + expect(inputElement.nativeElement.textContent).toEqual(''); - select.value = 'Ghost city'; - tick(); - fixture.detectChanges(); - select.toggle(); - tick(); - fixture.detectChanges(); - expect(select.selectedItem).toBeUndefined(); - expect(select.input.value).toEqual(''); - expect(inputElement.nativeElement.value).toEqual(''); - const selectedItems = fixture.debugElement.nativeElement.querySelectorAll('.' + CSS_CLASS_SELECTED_ITEM); - expect(selectedItems.length).toEqual(0); - })); + select.value = 'Ghost city'; + tick(); + fixture.detectChanges(); + select.toggle(); + tick(); + fixture.detectChanges(); + expect(select.selectedItem).toBeUndefined(); + expect(select.input.value).toEqual(''); + expect(inputElement.nativeElement.value).toEqual(''); + const selectedItems = fixture.debugElement.nativeElement.querySelectorAll('.' + CSS_CLASS_SELECTED_ITEM); + expect(selectedItems.length).toEqual(0); + })); it('should not append any text to the input box when an item is focused but not selected', fakeAsync(() => { let focusedItem = select.items[2]; @@ -1239,8 +1237,8 @@ describe('igxSelect', () => { it('should properly emit selectionChanging event on item click', fakeAsync(() => { let selectedItemEl = selectList.children[5]; let selectedItem = select.items[5]; - spyOn(select.selectionChanging, 'emit'); - spyOn(select, 'selectItem').and.callThrough(); + vi.spyOn(select.selectionChanging, 'emit'); + vi.spyOn(select, 'selectItem'); const args: ISelectionEventArgs = { oldSelection: {}, newSelection: selectedItem, @@ -1275,8 +1273,8 @@ describe('igxSelect', () => { it('should properly emit selectionChanging event on item selected property setting', () => { let selectedItem = select.items[3]; - spyOn(select.selectionChanging, 'emit'); - spyOn(select, 'selectItem').and.callThrough(); + vi.spyOn(select.selectionChanging, 'emit'); + vi.spyOn(select, 'selectItem'); const args: ISelectionEventArgs = { oldSelection: {}, newSelection: selectedItem, @@ -1302,13 +1300,13 @@ describe('igxSelect', () => { it('should properly emit selectionChanging/close events on key interaction', fakeAsync(() => { let selectedItem = select.items[3]; - spyOn(select.opening, 'emit'); - spyOn(select.opened, 'emit'); - spyOn(select.closing, 'emit'); - spyOn(select.closed, 'emit'); - spyOn(select, 'close').and.callThrough(); - spyOn(select.selectionChanging, 'emit'); - spyOn(select, 'selectItem').and.callThrough(); + vi.spyOn(select.opening, 'emit'); + vi.spyOn(select.opened, 'emit'); + vi.spyOn(select.closing, 'emit'); + vi.spyOn(select.closed, 'emit'); + vi.spyOn(select, 'close'); + vi.spyOn(select.selectionChanging, 'emit'); + vi.spyOn(select, 'selectItem'); const args: ISelectionEventArgs = { oldSelection: {}, newSelection: selectedItem, @@ -1339,10 +1337,10 @@ describe('igxSelect', () => { expect(select.close).toHaveBeenCalledTimes(1); // Correct event order - expect(select.opening.emit).toHaveBeenCalledBefore(select.opened.emit); - expect(select.opened.emit).toHaveBeenCalledBefore(select.selectionChanging.emit); - expect(select.selectionChanging.emit).toHaveBeenCalledBefore(select.closing.emit); - expect(select.closing.emit).toHaveBeenCalledBefore(select.closed.emit); + expect(Math.min(...vi.mocked(select.opening.emit).mock.invocationCallOrder)).toBeLessThan(Math.min(...vi.mocked(select.opened.emit).mock.invocationCallOrder)); + expect(Math.min(...vi.mocked(select.opened.emit).mock.invocationCallOrder)).toBeLessThan(Math.min(...vi.mocked(select.selectionChanging.emit).mock.invocationCallOrder)); + expect(Math.min(...vi.mocked(select.selectionChanging.emit).mock.invocationCallOrder)).toBeLessThan(Math.min(...vi.mocked(select.closing.emit).mock.invocationCallOrder)); + expect(Math.min(...vi.mocked(select.closing.emit).mock.invocationCallOrder)).toBeLessThan(Math.min(...vi.mocked(select.closed.emit).mock.invocationCallOrder)); args.oldSelection = selectedItem; selectedItem = select.items[9]; @@ -1383,7 +1381,7 @@ describe('igxSelect', () => { it('should properly emit selectionChanging event using selectItem method', () => { let selectedItem = select.items[4]; - spyOn(select.selectionChanging, 'emit'); + vi.spyOn(select.selectionChanging, 'emit'); const args: ISelectionEventArgs = { oldSelection: {}, newSelection: selectedItem, @@ -1407,7 +1405,7 @@ describe('igxSelect', () => { it('should not emit selectionChanging when selection does not change', () => { const item = select.items[5]; - spyOn(select.selectionChanging, 'emit'); + vi.spyOn(select.selectionChanging, 'emit'); select.selectItem(item); expect(select.selectionChanging.emit).toHaveBeenCalledTimes(1); select.selectItem(item); @@ -1420,7 +1418,7 @@ describe('igxSelect', () => { it('should not select header items passed through selectItem method', () => { const item = select.items[5]; - spyOn(select.selectionChanging, 'emit'); + vi.spyOn(select.selectionChanging, 'emit'); expect(select.selectedItem).toBeFalsy(); item.isHeader = true; select.selectItem(item); @@ -1438,71 +1436,69 @@ describe('igxSelect', () => { selectList = fixture.debugElement.query(By.css('.' + CSS_CLASS_DROPDOWN_LIST_SCROLL)); }); - it('should populate the input with the specified selected item text @input, instead of the selected item element innerText', - fakeAsync(() => { - let selectedItemIndex = 1; - const groupIndex = 0; - const groupElement = selectList.children[groupIndex]; - const itemElementToSelect = groupElement.children[selectedItemIndex].nativeElement; - - const checkInputValue = () => { - expect(select.selectedItem.text).toEqual(select.input.value); - expect(inputElement.nativeElement.value.toString().trim()).toEqual(select.selectedItem.text); - }; - - // There is not a selected item initially - const selectedItems = fixture.debugElement.queryAll(By.css('.' + CSS_CLASS_SELECTED_ITEM)); - expect(selectedItems.length).toEqual(0); - expect(select.value).toBeNull(); - expect(select.input.value).toEqual(''); - expect(inputElement.nativeElement.value).toEqual(''); - - // Select item - mouse click - select.toggle(); - tick(); - fixture.detectChanges(); - itemElementToSelect.click(); - fixture.detectChanges(); - checkInputValue(); + it('should populate the input with the specified selected item text @input, instead of the selected item element innerText', fakeAsync(() => { + let selectedItemIndex = 1; + const groupIndex = 0; + const groupElement = selectList.children[groupIndex]; + const itemElementToSelect = groupElement.children[selectedItemIndex].nativeElement; - // Select item - selectItem method - selectedItemIndex = 2; - select.selectItem(select.items[selectedItemIndex]); - tick(); - fixture.detectChanges(); - select.toggle(); - tick(); - fixture.detectChanges(); - checkInputValue(); + const checkInputValue = () => { + expect(select.selectedItem.text).toEqual(select.input.value); + expect(inputElement.nativeElement.value.toString().trim()).toEqual(select.selectedItem.text); + }; - // Select item - item selected property - selectedItemIndex = 3; - select.items[selectedItemIndex].selected = true; - fixture.detectChanges(); - checkInputValue(); - })); - - it('Should populate the input with the selected item element innerText, when text @Input is undefined(not set)', - fakeAsync(() => { - const selectedItemIndex = 2; - // const groupIndex = 0; - // const groupElement = selectList.children[groupIndex]; - // const itemElementToSelect = groupElement.children[selectedItemIndex].nativeElement; - const expectedInputText = 'Paris star'; - - const checkInputValue = () => { - expect(select.selectedItem.itemText).toEqual(expectedInputText); - expect(select.selectedItem.itemText).toEqual(select.input.value); - expect(inputElement.nativeElement.value.toString().trim()).toEqual(select.selectedItem.itemText); - }; - - // Select item - no select-item text. Should set item;s element innerText as input value. - (select.items[selectedItemIndex] as IgxSelectItemComponent).text = undefined; - select.items[selectedItemIndex].selected = true; - fixture.detectChanges(); - tick(); - checkInputValue(); - })); + // There is not a selected item initially + const selectedItems = fixture.debugElement.queryAll(By.css('.' + CSS_CLASS_SELECTED_ITEM)); + expect(selectedItems.length).toEqual(0); + expect(select.value).toBeNull(); + expect(select.input.value).toEqual(''); + expect(inputElement.nativeElement.value).toEqual(''); + + // Select item - mouse click + select.toggle(); + tick(); + fixture.detectChanges(); + itemElementToSelect.click(); + fixture.detectChanges(); + checkInputValue(); + + // Select item - selectItem method + selectedItemIndex = 2; + select.selectItem(select.items[selectedItemIndex]); + tick(); + fixture.detectChanges(); + select.toggle(); + tick(); + fixture.detectChanges(); + checkInputValue(); + + // Select item - item selected property + selectedItemIndex = 3; + select.items[selectedItemIndex].selected = true; + fixture.detectChanges(); + checkInputValue(); + })); + + it('Should populate the input with the selected item element innerText, when text @Input is undefined(not set)', fakeAsync(() => { + const selectedItemIndex = 2; + // const groupIndex = 0; + // const groupElement = selectList.children[groupIndex]; + // const itemElementToSelect = groupElement.children[selectedItemIndex].nativeElement; + const expectedInputText = 'Paris star'; + + const checkInputValue = () => { + expect(select.selectedItem.itemText).toEqual(expectedInputText); + expect(select.selectedItem.itemText).toEqual(select.input.value); + expect(inputElement.nativeElement.value.toString().trim()).toEqual(select.selectedItem.itemText); + }; + + // Select item - no select-item text. Should set item;s element innerText as input value. + (select.items[selectedItemIndex] as IgxSelectItemComponent).text = undefined; + select.items[selectedItemIndex].selected = true; + fixture.detectChanges(); + tick(); + checkInputValue(); + })); }); }); @@ -1667,13 +1663,13 @@ describe('igxSelect', () => { })); it('should properly emit opening/closing events on ALT+ArrowUp/Down keys interaction', fakeAsync(() => { - spyOn(select.opening, 'emit'); - spyOn(select.opened, 'emit'); - spyOn(select.closing, 'emit'); - spyOn(select.closed, 'emit'); - spyOn(select, 'toggle').and.callThrough(); - spyOn(select, 'open').and.callThrough(); - spyOn(select, 'close').and.callThrough(); + vi.spyOn(select.opening, 'emit'); + vi.spyOn(select.opened, 'emit'); + vi.spyOn(select.closing, 'emit'); + vi.spyOn(select.closed, 'emit'); + vi.spyOn(select, 'toggle'); + vi.spyOn(select, 'open'); + vi.spyOn(select, 'close'); inputElement.triggerEventHandler('keydown', altArrowDownKeyEvent); tick(); @@ -1687,13 +1683,13 @@ describe('igxSelect', () => { })); it('should properly emit opening/closing events on ENTER/ESC key interaction', fakeAsync(() => { - spyOn(select.opening, 'emit'); - spyOn(select.opened, 'emit'); - spyOn(select.closing, 'emit'); - spyOn(select.closed, 'emit'); - spyOn(select, 'open').and.callThrough(); - spyOn(select, 'close').and.callThrough(); - spyOn(select, 'toggle').and.callThrough(); + vi.spyOn(select.opening, 'emit'); + vi.spyOn(select.opened, 'emit'); + vi.spyOn(select.closing, 'emit'); + vi.spyOn(select.closed, 'emit'); + vi.spyOn(select, 'open'); + vi.spyOn(select, 'close'); + vi.spyOn(select, 'toggle'); inputElement.triggerEventHandler('keydown', enterKeyEvent); tick(); @@ -1707,13 +1703,13 @@ describe('igxSelect', () => { })); it('should properly emit opening/closing events on SPACE/ESC key interaction', fakeAsync(() => { - spyOn(select.opening, 'emit'); - spyOn(select.opened, 'emit'); - spyOn(select.closing, 'emit'); - spyOn(select.closed, 'emit'); - spyOn(select, 'open').and.callThrough(); - spyOn(select, 'close').and.callThrough(); - spyOn(select, 'toggle').and.callThrough(); + vi.spyOn(select.opening, 'emit'); + vi.spyOn(select.opened, 'emit'); + vi.spyOn(select.closing, 'emit'); + vi.spyOn(select.closed, 'emit'); + vi.spyOn(select, 'open'); + vi.spyOn(select, 'close'); + vi.spyOn(select, 'toggle'); inputElement.triggerEventHandler('keydown', spaceKeyEvent); tick(); @@ -2024,7 +2020,8 @@ describe('igxSelect', () => { 'Übersee', 'Бургас', 'Karlsruhe', - 'Östringen']; + 'Östringen' + ]; fixture.detectChanges(); select.open(); fixture.detectChanges(); @@ -2110,7 +2107,7 @@ describe('igxSelect', () => { it('character key navigation when dropdown is closed should wrap selection', fakeAsync(() => { const filteredItemsInxs = fixture.componentInstance.filterCities('l'); - for (const item of filteredItemsInxs) { + for (const item of filteredItemsInxs) { inputElement.triggerEventHandler('keydown', { key: 'l' }); tick(); fixture.detectChanges(); @@ -2139,7 +2136,8 @@ describe('igxSelect', () => { 'Übersee', 'Бургас', 'Karlsruhe', - 'Östringen']; + 'Östringen' + ]; fixture.detectChanges(); // German characters @@ -2194,7 +2192,7 @@ describe('igxSelect', () => { it('Should navigate through items when dropdown is closed and initial value is passed', fakeAsync(() => { select.close(); fixture.detectChanges(); - spyOn(select, 'navigateNext').and.callThrough(); + vi.spyOn(select, 'navigateNext'); const choices = select.children.toArray(); select.value = choices[5].value; fixture.detectChanges(); @@ -2300,7 +2298,8 @@ describe('igxSelect', () => { 'Option 7', 'Option 8', 'Option 9', - 'Option 10']; + 'Option 10' + ]; fixture.detectChanges(); selectedItemIndex = 0; @@ -2358,33 +2357,33 @@ describe('igxSelect', () => { verifySelectedItemPositioning(); })); - it('should display selected item over input and possible items above and below when item in the middle of the list is selected', + it('should display selected item over input and possible items above and below when item in the middle of the list is selected', // there is enough scroll left in scroll container so the dropdown is NOT REPOSITIONED below the input - fakeAsync(() => { - selectedItemIndex = 3; - select.items[selectedItemIndex].selected = true; - (select.element as HTMLElement).style.marginTop = '10px'; - fixture.detectChanges(); - select.toggle(); - tick(); - fixture.detectChanges(); - getBoundingRectangles(); - verifySelectedItemPositioning(); - (select.element as HTMLElement).parentElement.style.marginTop = '10px'; - fixture.detectChanges(); - })); + fakeAsync(() => { + selectedItemIndex = 3; + select.items[selectedItemIndex].selected = true; + (select.element as HTMLElement).style.marginTop = '10px'; + fixture.detectChanges(); + select.toggle(); + tick(); + fixture.detectChanges(); + getBoundingRectangles(); + verifySelectedItemPositioning(); + (select.element as HTMLElement).parentElement.style.marginTop = '10px'; + fixture.detectChanges(); + })); - it('should display selected item and all possible items above when last item is selected', + it('should display selected item and all possible items above when last item is selected', // there is NO enough scroll left in scroll container so the dropdown is REPOSITIONED below the input - fakeAsync(() => { - selectedItemIndex = 9; - select.items[selectedItemIndex].selected = true; - fixture.detectChanges(); - select.toggle(); - tick(); - fixture.detectChanges(); - getBoundingRectangles(); - })); + fakeAsync(() => { + selectedItemIndex = 9; + select.items[selectedItemIndex].selected = true; + fixture.detectChanges(); + select.toggle(); + tick(); + fixture.detectChanges(); + getBoundingRectangles(); + })); }); describe('Not enough space below to open positioning tests: ', () => { @@ -2396,30 +2395,29 @@ describe('igxSelect', () => { selectList = fixture.debugElement.query(By.css('.' + CSS_CLASS_DROPDOWN_LIST_SCROLL)); }); - it('should display list with selected item and all possible items after it when first item is selected', - fakeAsync(() => { - selectedItemIndex = 0; - select.items[selectedItemIndex].selected = true; - fixture.detectChanges(); - select.toggle(); - tick(); - fixture.detectChanges(); - getBoundingRectangles(); - })); - it('should display selected item and all possible items above and below when item in the middle of the list is selected', + it('should display list with selected item and all possible items after it when first item is selected', fakeAsync(() => { + selectedItemIndex = 0; + select.items[selectedItemIndex].selected = true; + fixture.detectChanges(); + select.toggle(); + tick(); + fixture.detectChanges(); + getBoundingRectangles(); + })); + it('should display selected item and all possible items above and below when item in the middle of the list is selected', // there is NO enough scroll atop the scroll container so the dropdown is REPOSITIONED above the input - fakeAsync(() => { - selectedItemIndex = 3; - select.items[selectedItemIndex].selected = true; - fixture.detectChanges(); - select.toggle(); - tick(); - fixture.detectChanges(); - getBoundingRectangles(); - })); + fakeAsync(() => { + selectedItemIndex = 3; + select.items[selectedItemIndex].selected = true; + fixture.detectChanges(); + select.toggle(); + tick(); + fixture.detectChanges(); + getBoundingRectangles(); + })); it(`should display selected item and all possible items above and position selected item over input - when item is close to the end of the list is selected`, + when item is close to the end of the list is selected`, // there is enough scroll left in scroll container so the dropdown is NOT REPOSITIONED above the input fakeAsync(() => { selectedItemIndex = 7; @@ -2571,10 +2569,10 @@ describe('igxSelect', () => { expect(selectHeader).toBeDefined(); expect(selectFooter).toBeDefined(); // elements structure is correct - expect(selectListWrapper.nativeElement.firstElementChild).toHaveClass(CSS_CLASS_DROPDOWN_SELECT_HEADER); - expect(selectListWrapper.nativeElement.lastElementChild).toHaveClass(CSS_CLASS_DROPDOWN_SELECT_FOOTER); - expect(selectList.nativeElement.previousElementSibling).toHaveClass(CSS_CLASS_DROPDOWN_SELECT_HEADER); - expect(selectList.nativeElement.nextElementSibling).toHaveClass(CSS_CLASS_DROPDOWN_SELECT_FOOTER); + expect(selectListWrapper.nativeElement.firstElementChild.classList.contains(CSS_CLASS_DROPDOWN_SELECT_HEADER)).toBe(true); + expect(selectListWrapper.nativeElement.lastElementChild.classList.contains(CSS_CLASS_DROPDOWN_SELECT_FOOTER)).toBe(true); + expect(selectList.nativeElement.previousElementSibling.classList.contains(CSS_CLASS_DROPDOWN_SELECT_HEADER)).toBe(true); + expect(selectList.nativeElement.nextElementSibling.classList.contains(CSS_CLASS_DROPDOWN_SELECT_FOOTER)).toBe(true); }); it('Should NOT render header and footer elements, if template is not defined', fakeAsync(() => { @@ -2588,8 +2586,8 @@ describe('igxSelect', () => { expect(selectHeader).toBeNull(); expect(selectFooter).toBeNull(); // elements structure is correct - expect(selectListWrapper.nativeElement.firstElementChild).toHaveClass(CSS_CLASS_DROPDOWN_LIST_SCROLL); - expect(selectListWrapper.nativeElement.lastElementChild).toHaveClass(CSS_CLASS_DROPDOWN_LIST_SCROLL); + expect(selectListWrapper.nativeElement.firstElementChild.classList.contains(CSS_CLASS_DROPDOWN_LIST_SCROLL)).toBe(true); + expect(selectListWrapper.nativeElement.lastElementChild.classList.contains(CSS_CLASS_DROPDOWN_LIST_SCROLL)).toBe(true); expect(selectList.nativeElement.previousElementSibling).toBeNull(); expect(selectList.nativeElement.nextElementSibling).toBeNull(); })); @@ -2619,22 +2617,21 @@ describe('igxSelect', () => { }); }); describe('Input with input group directives - hint, label, prefix, suffix: ', () => { - beforeEach(() => { + beforeEach(() => { fixture = TestBed.createComponent(IgxSelectAffixComponent); select = fixture.componentInstance.select; fixture.detectChanges(); }); - it('should not open dropdown on hint container click', - fakeAsync(() => { - const hint = fixture.debugElement.query(By.directive(IgxHintDirective)); - const hintContainer: HTMLElement = hint.nativeElement.parentElement; + it('should not open dropdown on hint container click', fakeAsync(() => { + const hint = fixture.debugElement.query(By.directive(IgxHintDirective)); + const hintContainer: HTMLElement = hint.nativeElement.parentElement; - expect(select.collapsed).toBeTruthy(); - hintContainer.click(); - tick(); - fixture.detectChanges(); - expect(select.collapsed).toBeTruthy(); + expect(select.collapsed).toBeTruthy(); + hintContainer.click(); + tick(); + fixture.detectChanges(); + expect(select.collapsed).toBeTruthy(); })); it('should not open dropdown on hint element click', () => { @@ -2650,13 +2647,26 @@ describe('igxSelect', () => { describe('igxSelect ControlValueAccessor Unit', () => { let select: IgxSelectComponent; it('Should correctly implement interface methods', () => { - const mockSelection = jasmine.createSpyObj('IgxSelectionAPIService', ['get', 'set', 'clear', 'delete', 'first_item']); - const mockCdr = jasmine.createSpyObj('ChangeDetectorRef', ['detectChanges']); - const mockNgControl = jasmine.createSpyObj('NgControl', ['registerOnChangeCb', 'registerOnTouchedCb']); - const mockInjector = jasmine.createSpyObj('Injector', { - get: mockNgControl - }); - const mockDocument = jasmine.createSpyObj('DOCUMENT', [], { 'defaultView': { getComputedStyle: () => null }}); + const mockSelection = { + get: vi.fn().mockName("IgxSelectionAPIService.get"), + set: vi.fn().mockName("IgxSelectionAPIService.set"), + clear: vi.fn().mockName("IgxSelectionAPIService.clear"), + delete: vi.fn().mockName("IgxSelectionAPIService.delete"), + first_item: vi.fn().mockName("IgxSelectionAPIService.first_item") + }; + const mockCdr = { + detectChanges: vi.fn().mockName("ChangeDetectorRef.detectChanges") + }; + const mockNgControl = { + registerOnChangeCb: vi.fn().mockName("NgControl.registerOnChangeCb"), + registerOnTouchedCb: vi.fn().mockName("NgControl.registerOnTouchedCb") + }; + const mockInjector = { + get: vi.fn().mockName("Injector.get").mockReturnValue(mockNgControl) + }; + const mockDocument = { + 'defaultView': { getComputedStyle: () => null } + }; TestBed.configureTestingModule({ imports: [NoopAnimationsModule], @@ -2703,7 +2713,7 @@ describe('igxSelect ControlValueAccessor Unit', () => { expect(mockNgControl.registerOnTouchedCb).toHaveBeenCalledTimes(1); select.input = {} as any; - spyOnProperty(select, 'collapsed').and.returnValue(true); + vi.spyOn(select, 'collapsed').mockReturnValue(true); select.onBlur(); expect(mockNgControl.registerOnTouchedCb).toHaveBeenCalledTimes(2); @@ -2712,8 +2722,10 @@ describe('igxSelect ControlValueAccessor Unit', () => { expect(mockSelection.delete).toHaveBeenCalled(); }); - it('Should correctly handle ngControl validity', () => { - pending('Convert existing form test here'); + it.skip('Should correctly handle ngControl validity', () => { + // TODO: vitest-migration: The pending() function was converted to a skipped test (`it.skip`). See: https://vitest.dev/api/vi.html#it-skip + // pending('Convert existing form test here'); + ; }); }); @@ -2732,7 +2744,8 @@ describe('igxSelect ControlValueAccessor Unit', () => { imports: [FormsModule, IgxSelectComponent, IgxSelectItemComponent, IgxLabelDirective] }) class IgxSelectSimpleComponent { - @ViewChild('dummyInput') public dummyInput: ElementRef; + @ViewChild('dummyInput') + public dummyInput: ElementRef; @ViewChild('select', { read: IgxSelectComponent, static: true }) public select: IgxSelectComponent; @ViewChild('simpleLabel', { read: ElementRef, static: true }) @@ -2754,7 +2767,8 @@ class IgxSelectSimpleComponent { 'Padua', 'Palermo', 'Palma de Mallorca', - 'Amsterdam']; + 'Amsterdam' + ]; public value = null; // returns an array of the filtered items indexes @@ -2784,7 +2798,10 @@ class IgxSelectSimpleComponent { class IgxSelectGroupsComponent { @ViewChild('select', { read: IgxSelectComponent, static: true }) public select: IgxSelectComponent; - public locations: { continent: string, capitals: string[] } [] = [ + public locations: { + continent: string; + capitals: string[]; + }[] = [ { continent: 'Europe', capitals: ['Berlin', 'London', 'Paris'] }, { continent: 'South America', capitals: ['Buenos Aires', 'Caracas', 'Lima'] }, { continent: 'North America', capitals: ['Washington', 'Ottawa', 'Mexico City'] } @@ -2841,7 +2858,8 @@ class IgxSelectTopComponent { 'Option 7', 'Option 8', 'Option 9', - 'Option 10']; + 'Option 10' + ]; } @Component({ template: ` @@ -2869,7 +2887,8 @@ class IgxSelectBottomComponent { 'Option 7', 'Option 8', 'Option 9', - 'Option 10']; + 'Option 10' + ]; } @Component({ template: ` @@ -3117,7 +3136,7 @@ class IgxSelectCDRComponent { public render = true; public columns: Array = [ - { field: 'ID', type: 'string' }, + { field: 'ID', type: 'string' }, { field: 'CompanyName', type: 'string' }, { field: 'ContactName', type: 'string' } ]; diff --git a/projects/igniteui-angular/simple-combo/src/simple-combo/simple-combo.component.spec.ts b/projects/igniteui-angular/simple-combo/src/simple-combo/simple-combo.component.spec.ts index 1030bcc7ab5..a5cb9fb2d61 100644 --- a/projects/igniteui-angular/simple-combo/src/simple-combo/simple-combo.component.spec.ts +++ b/projects/igniteui-angular/simple-combo/src/simple-combo/simple-combo.component.spec.ts @@ -1,3 +1,5 @@ +import type { Mock } from "vitest"; +import { describe, it, expect, beforeEach, afterAll, vi } from 'vitest'; import { AsyncPipe } from '@angular/common'; import { AfterViewInit, ChangeDetectorRef, Component, DOCUMENT, DebugElement, ElementRef, Injector, OnDestroy, OnInit, ViewChild, inject } from '@angular/core'; import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing'; @@ -59,22 +61,37 @@ describe('IgxSimpleCombo', () => { ]; const elementRef = { nativeElement: null }; const mockSelection: { - [key: string]: jasmine.Spy; - } = jasmine.createSpyObj('IgxSelectionAPIService', ['get', 'set', 'add_items', 'select_items', 'delete']); - const mockCdr = jasmine.createSpyObj('ChangeDetectorRef', ['markForCheck', 'detectChanges']); - const mockComboService = jasmine.createSpyObj('IgxComboAPIService', ['register', 'clear']); - const mockNgControl = jasmine.createSpyObj('NgControl', ['registerOnChangeCb', 'registerOnTouchedCb']); - const mockInjector = jasmine.createSpyObj('Injector', { - get: mockNgControl - }); - mockSelection.get.and.returnValue(new Set([])); + [key: string]: Mock; + } = { + get: vi.fn().mockName("IgxSelectionAPIService.get"), + set: vi.fn().mockName("IgxSelectionAPIService.set"), + add_items: vi.fn().mockName("IgxSelectionAPIService.add_items"), + select_items: vi.fn().mockName("IgxSelectionAPIService.select_items"), + delete: vi.fn().mockName("IgxSelectionAPIService.delete") + }; + const mockCdr = { + markForCheck: vi.fn().mockName("ChangeDetectorRef.markForCheck"), + detectChanges: vi.fn().mockName("ChangeDetectorRef.detectChanges") + }; + const mockComboService = { + register: vi.fn().mockName("IgxComboAPIService.register"), + clear: vi.fn().mockName("IgxComboAPIService.clear") + }; + const mockNgControl = { + registerOnChangeCb: vi.fn().mockName("NgControl.registerOnChangeCb"), + registerOnTouchedCb: vi.fn().mockName("NgControl.registerOnTouchedCb") + }; + const mockInjector = { + get: vi.fn().mockName("Injector.get").mockReturnValue(mockNgControl) + }; + mockSelection.get.mockReturnValue(new Set([])); const platformUtil = null; - const mockDocument = jasmine.createSpyObj('DOCUMENT', [], { + const mockDocument = { 'body': document.createElement('div'), 'defaultView': { getComputedStyle: () => ({}) } - }); + }; beforeEach(() => { TestBed.configureTestingModule({ @@ -95,14 +112,12 @@ describe('IgxSimpleCombo', () => { combo = TestBed.inject(IgxSimpleComboComponent); }); - jasmine.getEnv().allowRespy(true); - - afterAll(() => { - jasmine.getEnv().allowRespy(false); - }); - it('should properly call dropdown methods on toggle', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['open', 'close', 'toggle']); + const dropdown = { + open: vi.fn().mockName("IgxComboDropDownComponent.open"), + close: vi.fn().mockName("IgxComboDropDownComponent.close"), + toggle: vi.fn().mockName("IgxComboDropDownComponent.toggle") + }; combo.ngOnInit(); combo.dropdown = dropdown; dropdown.collapsed = true; @@ -123,7 +138,9 @@ describe('IgxSimpleCombo', () => { expect(combo.collapsed).toBe(false); }); it('should call dropdown toggle with correct overlaySettings', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['toggle']); + const dropdown = { + toggle: vi.fn().mockName("IgxComboDropDownComponent.toggle") + }; combo.ngOnInit(); combo.dropdown = dropdown; const defaultSettings = (combo as any)._overlaySettings; @@ -147,14 +164,18 @@ describe('IgxSimpleCombo', () => { expect(combo.displayKey === combo.valueKey).toBeFalsy(); }); it('should select items through select method', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']); - const comboInput = jasmine.createSpyObj('IgxInputDirective', ['value']); + const dropdown = { + selectItem: vi.fn().mockName("IgxComboDropDownComponent.selectItem") + }; + const comboInput = { + value: vi.fn().mockName("IgxInputDirective.value") + }; combo.ngOnInit(); combo.comboInput = comboInput; combo.data = complexData; combo.valueKey = 'country'; // with valueKey combo.dropdown = dropdown; - spyOnProperty(combo, 'totalItemCount').and.returnValue(combo.data.length); + vi.spyOn(combo, 'totalItemCount').mockReturnValue(combo.data.length); let selectedItem = combo.data[0]; let selectedValue = combo.data[0].country; @@ -179,8 +200,8 @@ describe('IgxSimpleCombo', () => { }); it('should emit owner on `opening` and `closing`', () => { combo.ngOnInit(); - spyOn(combo.opening, 'emit').and.callThrough(); - spyOn(combo.closing, 'emit').and.callThrough(); + vi.spyOn(combo.opening, 'emit'); + vi.spyOn(combo.closing, 'emit'); const mockObj = {}; const mockEvent = new Event('mock'); const inputEvent: IBaseCancelableBrowserEventArgs = { @@ -215,15 +236,19 @@ describe('IgxSimpleCombo', () => { sub.unsubscribe(); }); it('should fire selectionChanging event on item selection', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']); + const dropdown = { + selectItem: vi.fn().mockName("IgxComboDropDownComponent.selectItem") + }; combo.ngOnInit(); combo.data = data; combo.dropdown = dropdown; - const comboInput = jasmine.createSpyObj('IgxInputDirective', ['value']); + const comboInput = { + value: vi.fn().mockName("IgxInputDirective.value") + }; comboInput.value = 'test'; combo.comboInput = comboInput; - spyOnProperty(combo, 'totalItemCount').and.returnValue(combo.data.length); - spyOn(combo.selectionChanging, 'emit'); + vi.spyOn(combo, 'totalItemCount').mockReturnValue(combo.data.length); + vi.spyOn(combo.selectionChanging, 'emit'); let oldSelection = undefined; let newSelection = [combo.data[1]]; @@ -255,13 +280,15 @@ describe('IgxSimpleCombo', () => { }); }); it('should properly emit added and removed values in change event on single value selection', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']); + const dropdown = { + selectItem: vi.fn().mockName("IgxComboDropDownComponent.selectItem") + }; combo.ngOnInit(); combo.data = complexData; combo.valueKey = 'country'; combo.dropdown = dropdown; - spyOnProperty(combo, 'totalItemCount').and.returnValue(combo.data.length); - const selectionSpy = spyOn(combo.selectionChanging, 'emit'); + vi.spyOn(combo, 'totalItemCount').mockReturnValue(combo.data.length); + const selectionSpy = vi.spyOn(combo.selectionChanging, 'emit'); const expectedResults: ISimpleComboSelectionChangingEventArgs = { newValue: combo.data[0][combo.valueKey], oldValue: undefined, @@ -271,7 +298,9 @@ describe('IgxSimpleCombo', () => { displayText: `${combo.data[0][combo.displayKey]}`, cancel: false }; - const comboInput = jasmine.createSpyObj('IgxInputDirective', ['value']); + const comboInput = { + value: vi.fn().mockName("IgxInputDirective.value") + }; comboInput.value = 'test'; combo.comboInput = comboInput; combo.select(combo.data[0][combo.valueKey]); @@ -287,13 +316,17 @@ describe('IgxSimpleCombo', () => { expect(selectionSpy).toHaveBeenCalledWith(expectedResults); }); it('should properly handle selection manipulation through selectionChanging emit', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']); + const dropdown = { + selectItem: vi.fn().mockName("IgxComboDropDownComponent.selectItem") + }; combo.ngOnInit(); combo.data = data; combo.dropdown = dropdown; - spyOnProperty(combo, 'totalItemCount').and.returnValue(combo.data.length); - spyOn(combo.selectionChanging, 'emit').and.callFake((event: IComboSelectionChangingEventArgs) => event.newValue = undefined); - const comboInput = jasmine.createSpyObj('IgxInputDirective', ['value']); + vi.spyOn(combo, 'totalItemCount').mockReturnValue(combo.data.length); + vi.spyOn(combo.selectionChanging, 'emit').mockImplementation((event: IComboSelectionChangingEventArgs) => event.newValue = undefined); + const comboInput = { + value: vi.fn().mockName("IgxInputDirective.value") + }; combo.comboInput = comboInput; // No items are initially selected expect(combo.selection).toEqual(undefined); @@ -329,13 +362,18 @@ describe('IgxSimpleCombo', () => { expect(combo.data.length).toBe(0); }); it('should properly handleInputChange', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem', 'navigateFirst']); + const dropdown = { + selectItem: vi.fn().mockName("IgxComboDropDownComponent.selectItem"), + navigateFirst: vi.fn().mockName("IgxComboDropDownComponent.navigateFirst") + }; combo.ngOnInit(); combo.data = data; combo.dropdown = dropdown; - const matchSpy = spyOn(combo, 'checkMatch').and.callThrough(); - spyOn(combo.searchInputUpdate, 'emit'); - const comboInput = jasmine.createSpyObj('IgxInputDirective', ['value']); + const matchSpy = vi.spyOn(combo, 'checkMatch'); + vi.spyOn(combo.searchInputUpdate, 'emit'); + const comboInput = { + value: vi.fn().mockName("IgxInputDirective.value") + }; comboInput.value = 'test'; combo.comboInput = comboInput; @@ -369,11 +407,19 @@ describe('IgxSimpleCombo', () => { combo.searchInputUpdate.subscribe((e) => { e.cancel = true; }); - const matchSpy = spyOn(combo, 'checkMatch').and.callThrough(); - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem', 'collapsed', 'open', 'navigateFirst']); + const matchSpy = vi.spyOn(combo, 'checkMatch'); + const dropdown = { + selectItem: vi.fn().mockName("IgxComboDropDownComponent.selectItem"), + collapsed: vi.fn().mockName("IgxComboDropDownComponent.collapsed"), + open: vi.fn().mockName("IgxComboDropDownComponent.open"), + navigateFirst: vi.fn().mockName("IgxComboDropDownComponent.navigateFirst") + }; combo.dropdown = dropdown; - spyOn(combo.searchInputUpdate, 'emit').and.callThrough(); - const comboInput = jasmine.createSpyObj('IgxInputDirective', ['value', 'focused']); + vi.spyOn(combo.searchInputUpdate, 'emit'); + const comboInput = { + value: vi.fn().mockName("IgxInputDirective.value"), + focused: vi.fn().mockName("IgxInputDirective.focused") + }; comboInput.value = 'test'; combo.comboInput = comboInput; @@ -382,9 +428,18 @@ describe('IgxSimpleCombo', () => { expect(matchSpy).toHaveBeenCalledTimes(1); }); it('should not open on click if combo is disabled', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['open', 'close', 'toggle']); - const spyObj = jasmine.createSpyObj('event', ['stopPropagation', 'preventDefault']); - const comboInput = jasmine.createSpyObj('IgxInputDirective', ['value']); + const dropdown = { + open: vi.fn().mockName("IgxComboDropDownComponent.open"), + close: vi.fn().mockName("IgxComboDropDownComponent.close"), + toggle: vi.fn().mockName("IgxComboDropDownComponent.toggle") + }; + const spyObj = { + stopPropagation: vi.fn().mockName("event.stopPropagation"), + preventDefault: vi.fn().mockName("event.preventDefault") + }; + const comboInput = { + value: vi.fn().mockName("IgxInputDirective.value") + }; comboInput.value = 'test'; combo.comboInput = comboInput; combo.ngOnInit(); @@ -396,16 +451,24 @@ describe('IgxSimpleCombo', () => { expect(combo.dropdown.collapsed).toBeTruthy(); }); it('should not clear value when combo is disabled', () => { - const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem', 'focusedItem']); - const spyObj = jasmine.createSpyObj('event', ['stopPropagation']); + const dropdown = { + selectItem: vi.fn().mockName("IgxComboDropDownComponent.selectItem"), + focusedItem: vi.fn().mockName("IgxComboDropDownComponent.focusedItem") + }; + const spyObj = { + stopPropagation: vi.fn().mockName("event.stopPropagation") + }; combo.ngOnInit(); combo.data = data; combo.dropdown = dropdown; combo.disabled = true; - const comboInput = jasmine.createSpyObj('IgxInputDirective', ['value', 'focus']); + const comboInput = { + value: vi.fn().mockName("IgxInputDirective.value"), + focus: vi.fn().mockName("IgxInputDirective.focus") + }; comboInput.value = 'test'; combo.comboInput = comboInput; - spyOnProperty(combo, 'totalItemCount').and.returnValue(combo.data.length); + vi.spyOn(combo, 'totalItemCount').mockReturnValue(combo.data.length); const item = combo.data.slice(0, 1); combo.select(item); @@ -414,14 +477,12 @@ describe('IgxSimpleCombo', () => { }); it('should delete the selection on destroy', () => { - jasmine.getEnv().allowRespy(true); const selectionService = TestBed.inject(IgxSelectionAPIService); - const comboClearSpy = spyOn(mockComboService, 'clear'); - const selectionDeleteSpy = spyOn(selectionService, 'delete'); + const comboClearSpy = vi.spyOn(mockComboService, 'clear'); + const selectionDeleteSpy = vi.spyOn(selectionService, 'delete'); combo.ngOnDestroy(); expect(comboClearSpy).toHaveBeenCalled(); expect(selectionDeleteSpy).toHaveBeenCalled(); - jasmine.getEnv().allowRespy(false); }); }); @@ -627,7 +688,7 @@ describe('IgxSimpleCombo', () => { expect(footerHTMLElement.parentNode).toEqual(dropdownList); expect(footerHTMLElement.textContent).toEqual('This is a footer'); }); - xit('should initialize the component with empty data and bindings', () => { + it.skip('should initialize the component with empty data and bindings', () => { fixture = TestBed.createComponent(IgxSimpleComboEmptyComponent); expect(() => { fixture.detectChanges(); @@ -954,7 +1015,9 @@ describe('IgxSimpleCombo', () => { expect(combo).toBeDefined(); expect(combo.valueKey).toBeDefined(); let selectedItem = combo.data[1]; - const spyObj = jasmine.createSpyObj('event', ['stopPropagation']); + const spyObj = { + stopPropagation: vi.fn().mockName("event.stopPropagation") + }; combo.toggle(); combo.select(combo.data[1][combo.valueKey]); @@ -1008,8 +1071,8 @@ describe('IgxSimpleCombo', () => { }); it('should toggle dropdown list with arrow down/up keys', fakeAsync(() => { - spyOn(combo, 'open').and.callThrough(); - spyOn(combo, 'close').and.callThrough(); + vi.spyOn(combo, 'open'); + vi.spyOn(combo, 'close'); combo.onArrowDown(UIInteractions.getKeyboardEvent('keydown', 'ArrowDown')); tick(); @@ -1063,11 +1126,11 @@ describe('IgxSimpleCombo', () => { expect(dropdown.focusedItem).toBeTruthy(); expect(dropdown.focusedItem.index).toEqual(1); - spyOn(combo.closed, 'emit').and.callThrough(); + vi.spyOn(combo.closed, 'emit'); UIInteractions.triggerEventHandlerKeyDown('Space', dropdownContent); fixture.detectChanges(); expect(combo.closed.emit).not.toHaveBeenCalled(); - expect(combo.selection).toBeDefined() + expect(combo.selection).toBeDefined(); }); it('should close the dropdown list on pressing Tab key', fakeAsync(() => { @@ -1085,7 +1148,7 @@ describe('IgxSimpleCombo', () => { // allowCustomValues does not matter combo.select(combo.data[2][combo.valueKey]); fixture.detectChanges(); - expect(combo.selection).toBeDefined() + expect(combo.selection).toBeDefined(); expect(input.nativeElement.value).toEqual('Massachusetts'); UIInteractions.simulateTyping('L', input, 13, 14); @@ -1101,7 +1164,7 @@ describe('IgxSimpleCombo', () => { UIInteractions.triggerEventHandlerKeyDown('Tab', input); fixture.detectChanges(); expect(input.nativeElement.value.length).toEqual(0); - expect(combo.selection).not.toBeDefined() + expect(combo.selection).not.toBeDefined(); }); it('should not clear selection on tab/blur after filtering and selecting a value', () => { @@ -1111,17 +1174,17 @@ describe('IgxSimpleCombo', () => { fixture.detectChanges(); UIInteractions.triggerKeyDownEvtUponElem('Enter', input.nativeElement); - expect(combo.selection).toBeDefined() + expect(combo.selection).toBeDefined(); expect(combo.displayValue).toEqual('Wisconsin'); UIInteractions.triggerEventHandlerKeyDown('Tab', input); fixture.detectChanges(); - expect(combo.selection).toBeDefined() + expect(combo.selection).toBeDefined(); expect(combo.displayValue).toEqual('Wisconsin'); }); it('should toggle combo dropdown on Enter of the focused toggle icon', fakeAsync(() => { - spyOn(combo, 'toggle').and.callThrough(); + vi.spyOn(combo, 'toggle'); const toggleBtn = fixture.debugElement.query(By.css(`.${CSS_CLASS_TOGGLEBUTTON}`)); UIInteractions.triggerEventHandlerKeyDown('Enter', toggleBtn); @@ -1140,7 +1203,7 @@ describe('IgxSimpleCombo', () => { it('should clear the selection on Enter of the focused clear icon', () => { combo.select(combo.data[2][combo.valueKey]); fixture.detectChanges(); - expect(combo.selection).toBeDefined() + expect(combo.selection).toBeDefined(); expect(input.nativeElement.value).toEqual('Massachusetts'); const clearBtn = fixture.debugElement.query(By.css(`.${CSS_CLASS_CLEARBUTTON}`)); @@ -1216,7 +1279,7 @@ describe('IgxSimpleCombo', () => { })); it('should close when an item is clicked on', () => { - spyOn(combo, 'close').and.callThrough(); + vi.spyOn(combo, 'close'); combo.open(); fixture.detectChanges(); const item1 = fixture.debugElement.query(By.css(`.${CSS_CLASS_DROPDOWNLISTITEM}`)); @@ -1240,15 +1303,15 @@ describe('IgxSimpleCombo', () => { UIInteractions.triggerEventHandlerKeyDown('Tab', input); fixture.detectChanges(); - expect(combo.selection).toBeDefined() + expect(combo.selection).toBeDefined(); }); it('should scroll to top when opened and there is no selection', () => { combo.deselect(); fixture.detectChanges(); - spyOn(combo, 'onClick').and.callThrough(); - spyOn((combo as any).virtDir, 'scrollTo').and.callThrough(); + vi.spyOn(combo, 'onClick'); + vi.spyOn((combo as any).virtDir, 'scrollTo'); const toggleButton = fixture.debugElement.query(By.directive(IgxIconComponent)); expect(toggleButton).toBeDefined(); @@ -1264,12 +1327,12 @@ describe('IgxSimpleCombo', () => { it('should close the dropdown with Alt + ArrowUp', fakeAsync(() => { combo.open(); fixture.detectChanges(); - spyOn(combo, 'close').and.callThrough(); + vi.spyOn(combo, 'close'); UIInteractions.triggerEventHandlerKeyDown('ArrowDown', input); tick(); fixture.detectChanges(); - expect(document.activeElement).toHaveClass('igx-combo__content'); + expect(document.activeElement.classList.contains('igx-combo__content')).toBe(true); UIInteractions.triggerEventHandlerKeyDown('ArrowUp', input, true, true); fixture.detectChanges(); @@ -1311,7 +1374,7 @@ describe('IgxSimpleCombo', () => { UIInteractions.triggerEventHandlerKeyDown('Backspace', input); fixture.detectChanges(); - expect(combo.selection).not.toBeDefined() + expect(combo.selection).not.toBeDefined(); input.triggerEventHandler('blur', {}); fixture.detectChanges(); @@ -1324,19 +1387,19 @@ describe('IgxSimpleCombo', () => { UIInteractions.triggerEventHandlerKeyDown('Backspace', input); fixture.detectChanges(); - expect(combo.selection).not.toBeDefined() + expect(combo.selection).not.toBeDefined(); }); it('should display all list items when clearing the input by Space', () => { combo.select('Wisconsin'); fixture.detectChanges(); - expect(combo.selection).toBeDefined() + expect(combo.selection).toBeDefined(); UIInteractions.simulateTyping(' ', input, 0, 9); fixture.detectChanges(); - expect(combo.selection).not.toBeDefined() + expect(combo.selection).not.toBeDefined(); expect(combo.filteredData.length).toEqual(combo.data.length); }); @@ -1344,7 +1407,7 @@ describe('IgxSimpleCombo', () => { combo.open(); fixture.detectChanges(); - spyOn(combo, 'close').and.callThrough(); + vi.spyOn(combo, 'close'); UIInteractions.triggerEventHandlerKeyDown('Tab', input); fixture.detectChanges(); @@ -1388,7 +1451,7 @@ describe('IgxSimpleCombo', () => { }); it('should not clear the input on blur with a partial match but it should select the match item', () => { - spyOn(combo.dropdown.closing, 'emit').and.callThrough(); + vi.spyOn(combo.dropdown.closing, 'emit'); input.triggerEventHandler('focus', {}); fixture.detectChanges(); @@ -1422,7 +1485,7 @@ describe('IgxSimpleCombo', () => { fixture.detectChanges(); expect(combo.displayValue).toEqual('Apple'); - expect(combo.selection).toBeDefined() + expect(combo.selection).toBeDefined(); }); it('should not clear input on blur when dropdown is collapsed with match', () => { @@ -1439,12 +1502,12 @@ describe('IgxSimpleCombo', () => { fixture.detectChanges(); expect(combo.displayValue).toEqual('New Jersey'); - expect(combo.selection).toBeDefined() + expect(combo.selection).toBeDefined(); }); it('should open the combo when input is focused', () => { - spyOn(combo, 'open').and.callThrough(); - spyOn(combo, 'close').and.callThrough(); + vi.spyOn(combo, 'open'); + vi.spyOn(combo, 'close'); input.triggerEventHandler('focus', {}); fixture.detectChanges(); @@ -1673,7 +1736,7 @@ describe('IgxSimpleCombo', () => { combo.select('Wisconsin'); fixture.detectChanges(); - expect(combo.selection).toBeDefined() + expect(combo.selection).toBeDefined(); let clearButton = fixture.debugElement.query(By.css(`.${CSS_CLASS_CLEARBUTTON}`)); expect(clearButton).not.toBeNull(); @@ -1683,7 +1746,7 @@ describe('IgxSimpleCombo', () => { UIInteractions.simulateTyping('L', input, 9, 10); fixture.detectChanges(); - expect(combo.selection).not.toBeDefined() + expect(combo.selection).not.toBeDefined(); //should hide the clear button immediately when clearing the selection by typing clearButton = fixture.debugElement.query(By.css(`.${CSS_CLASS_CLEARBUTTON}`)); @@ -1765,35 +1828,35 @@ describe('IgxSimpleCombo', () => { })); it('should properly filter dropdown when pasting from clipboard in input', () => { - spyOn(combo, 'handleInputChange').and.callThrough(); + vi.spyOn(combo, 'handleInputChange'); combo.open(); input.triggerEventHandler('focus', {}); fixture.detectChanges(); const target = { value: combo.data[1].field - } - combo.comboInput.value = target.value + }; + combo.comboInput.value = target.value; const pasteData = new DataTransfer(); const pasteEvent = new ClipboardEvent('paste', { clipboardData: pasteData }); Object.defineProperty(pasteEvent, 'target', { writable: false, value: target - }) + }); input.triggerEventHandler('paste', pasteEvent); fixture.detectChanges(); expect(combo.handleInputChange).toHaveBeenCalledTimes(1); - expect(combo.handleInputChange).toHaveBeenCalledWith(jasmine.objectContaining({ - target: jasmine.objectContaining({ value: target.value }) + expect(combo.handleInputChange).toHaveBeenCalledWith(expect.objectContaining({ + target: expect.objectContaining({ value: target.value }) })); - expect(combo.filteredData.length).toBeLessThan(combo.data.length) - expect(combo.filteredData[0].field).toBe(target.value) + expect(combo.filteredData.length).toBeLessThan(combo.data.length); + expect(combo.filteredData[0].field).toBe(target.value); }); it('should prevent Enter key default behavior when filtering data', fakeAsync(() => { const keyEvent = new KeyboardEvent('keydown', { key: 'Enter' }); - const spy = spyOn(keyEvent, 'preventDefault'); + const spy = vi.spyOn(keyEvent, 'preventDefault'); expect(combo.collapsed).toBe(true); expect(combo.selection).toBeUndefined(); @@ -1820,7 +1883,7 @@ describe('IgxSimpleCombo', () => { })); it('should emit selectionChanging event when input value changes', () => { - spyOn(combo.selectionChanging, 'emit').and.callThrough(); + vi.spyOn(combo.selectionChanging, 'emit'); fixture.detectChanges(); combo.select('Connecticut'); @@ -1869,7 +1932,7 @@ describe('IgxSimpleCombo', () => { region: 'New England' }); - const cancelEventSpy = spyOn(combo.selectionChanging, 'emit').and.callFake((args: ISimpleComboSelectionChangingEventArgs) => { + const cancelEventSpy = vi.spyOn(combo.selectionChanging, 'emit').mockImplementation((args: ISimpleComboSelectionChangingEventArgs) => { args.cancel = true; }); @@ -1907,7 +1970,7 @@ describe('IgxSimpleCombo', () => { region: 'New England' }); - const cancelEventSpy = spyOn(combo.selectionChanging, 'emit').and.callFake((args: ISimpleComboSelectionChangingEventArgs) => { + const cancelEventSpy = vi.spyOn(combo.selectionChanging, 'emit').mockImplementation((args: ISimpleComboSelectionChangingEventArgs) => { args.cancel = true; }); @@ -2337,7 +2400,7 @@ describe('IgxSimpleCombo', () => { UIInteractions.triggerKeyDownEvtUponElem('Enter', input.nativeElement); fixture.detectChanges(); model = fixture.componentInstance.values; - expect(combo.selection).toBeDefined() + expect(combo.selection).toBeDefined(); expect(combo.displayValue).toEqual('Wisconsin'); expect(combo.value).toEqual('Wisconsin'); expect(model).toEqual('Wisconsin'); @@ -2616,7 +2679,7 @@ describe('IgxSimpleCombo', () => { combo.deselect(); fixture.detectChanges(); - expect(combo.selection).not.toBeDefined() + expect(combo.selection).not.toBeDefined(); expect(form.controls['comboValue'].value).toEqual(undefined); expect(combo.displayValue).toEqual(''); @@ -2627,7 +2690,7 @@ describe('IgxSimpleCombo', () => { expect(form.controls['comboValue'].value).toEqual(undefined); UIInteractions.triggerKeyDownEvtUponElem('Enter', input.nativeElement); - expect(combo.selection).toBeDefined() + expect(combo.selection).toBeDefined(); expect(combo.displayValue).toEqual('One'); expect(combo.value).toEqual(1); expect(form.controls['comboValue'].value).toEqual(1); @@ -2655,7 +2718,7 @@ describe('IgxSimpleCombo', () => { input = fixture.debugElement.query(By.css(`.${CSS_CLASS_COMBO_INPUTGROUP}`)); }); it('should prevent registration of remote entries when selectionChanging is cancelled', () => { - spyOn(combo.selectionChanging, 'emit').and.callFake((event: IComboSelectionChangingEventArgs) => event.cancel = true); + vi.spyOn(combo.selectionChanging, 'emit').mockImplementation((event: IComboSelectionChangingEventArgs) => event.cancel = true); combo.open(); fixture.detectChanges(); const item1 = fixture.debugElement.query(By.css(`.${CSS_CLASS_DROPDOWNLISTITEM}`)); @@ -2663,7 +2726,7 @@ describe('IgxSimpleCombo', () => { item1.triggerEventHandler('click', UIInteractions.getMouseEvent('click')); fixture.detectChanges(); - expect(combo.selection).not.toBeDefined() + expect(combo.selection).not.toBeDefined(); expect((combo as any)._remoteSelection[0]).toBeUndefined(); }); it('should add predefined selection to the input when data is bound after initialization', fakeAsync(() => { @@ -2679,7 +2742,7 @@ describe('IgxSimpleCombo', () => { })); it('should clear selection and not clear value when bound to remote data and item is out of view', (async () => { expect(combo.valueKey).toBeDefined(); - expect(combo.selection).not.toBeDefined() + expect(combo.selection).not.toBeDefined(); const selectedItem = combo.data[1]; combo.toggle(); @@ -2696,20 +2759,20 @@ describe('IgxSimpleCombo', () => { UIInteractions.triggerEventHandlerKeyDown('Tab', input); fixture.detectChanges(); - expect(combo.selection).toBeDefined() + expect(combo.selection).toBeDefined(); expect(combo.displayValue).toEqual(`${selectedItem[combo.displayKey]}`); expect(combo.value).toEqual(selectedItem[combo.valueKey]); })); it('should set combo.displayValue to empty string when bound to remote data and selected item\'s data is not present', (async () => { expect(combo.valueKey).toBeDefined(); expect(combo.valueKey).toEqual('id'); - expect(combo.selection).not.toBeDefined() + expect(combo.selection).not.toBeDefined(); // current combo data - id: 0 - 9 // select item that is not present in the data source yet combo.select(15); - expect(combo.selection).toBeDefined() + expect(combo.selection).toBeDefined(); expect(combo.displayValue).toEqual(''); combo.toggle(); @@ -2742,7 +2805,7 @@ describe('IgxSimpleCombo', () => { reactiveForm = fixture.componentInstance.reactiveForm; reactiveControl = reactiveForm.form.controls['comboValue']; input = fixture.debugElement.query(By.css(`.${CSS_CLASS_COMBO_INPUTGROUP}`)); - tick() + tick(); fixture.detectChanges(); expect(combo).toBeTruthy(); @@ -2806,7 +2869,7 @@ describe('IgxSimpleCombo', () => { await wait(30); fixture.detectChanges(); } catch (error) { - fail(`Test failed with error: ${error}`) + throw new Error(`Test failed with error: ${error}`); } const virtState = grid.verticalScrollContainer.state; @@ -2818,7 +2881,7 @@ describe('IgxSimpleCombo', () => { const targetCell = grid.gridAPI.get_cell_by_index(i, 'Region') as any; comboNativeEl = targetCell.nativeElement.querySelector(SIMPLE_COMBO_ELEMENT); const comboInput = comboNativeEl.querySelector('input'); - expect(comboInput.value).toBe('', `Failed on index: ${i.toString()}`); + expect(comboInput.value, `Failed on index: ${i.toString()}`).toBe(''); } for (let i = virtState.startIndex; i < virtState.startIndex + virtState.chunkSize && i < grid.dataView.length; i++) { @@ -2977,7 +3040,7 @@ export class ComboModelBindingComponent implements OnInit { public ngOnInit() { this.items = [{ text: 'One', id: 0 }, { text: 'Two', id: 1 }, { text: 'Three', id: 2 }, - { text: 'Four', id: 3 }, { text: 'Five', id: 4 }]; + { text: 'Four', id: 3 }, { text: 'Five', id: 4 }]; } } @@ -3013,8 +3076,8 @@ class IgxComboInContainerTestComponent { 'Prague', 'Padua', 'Palermo', - 'Palma de Mallorca']; - + 'Palma de Mallorca' + ]; } @Component({ @@ -3215,7 +3278,7 @@ export class IgxSimpleComboBindingDataAfterInitComponent implements AfterViewIni public ngAfterViewInit() { requestAnimationFrame(() => { this.items = [{ text: 'One', id: 1 }, { text: 'Two', id: 2 }, { text: 'Three', id: 3 }, - { text: 'Four', id: 4 }, { text: 'Five', id: 5 }]; + { text: 'Four', id: 4 }, { text: 'Five', id: 5 }]; this.cdr.detectChanges(); }); } diff --git a/projects/igniteui-angular/slider/src/slider/slider.component.spec.ts b/projects/igniteui-angular/slider/src/slider/slider.component.spec.ts index 4838a1e45ba..f1d51657344 100644 --- a/projects/igniteui-angular/slider/src/slider/slider.component.spec.ts +++ b/projects/igniteui-angular/slider/src/slider/slider.component.spec.ts @@ -7,6 +7,7 @@ import { ɵDIR_DOCUMENT, ɵIgxDirectionality } from 'igniteui-angular/core'; import { UIInteractions, wait } from '../../../test-utils/ui-interactions.spec'; import { IgxSliderType, IgxThumbFromTemplateDirective, IgxThumbToTemplateDirective, IRangeSliderValue, TickLabelsOrientation, TicksOrientation } from './slider.common'; import { IgxSliderComponent } from './slider.component'; +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; const SLIDER_CLASS = '.igx-slider'; const THUMB_TAG = 'igx-thumb'; @@ -25,8 +26,12 @@ const TOP_TO_BOTTOM_TICK_LABLES = '.igx-slider__tick-labels--top-bottom'; const BOTTOM_TO_TOP_TICK_LABLES = '.igx-slider__tick-labels--bottom-top'; interface FakeDoc { - body: { dir?: string }; - documentElement: { dir?: string }; + body: { + dir?: string; + }; + documentElement: { + dir?: string; + }; } describe('IgxSlider', () => { @@ -60,7 +65,7 @@ describe('IgxSlider', () => { let fixture: ComponentFixture; let slider: IgxSliderComponent; - beforeEach(() => { + beforeEach(() => { fixture = TestBed.createComponent(SliderInitializeTestComponent); slider = fixture.componentInstance.slider; fixture.detectChanges(); @@ -333,9 +338,9 @@ describe('IgxSlider', () => { }); it('should not set value if value is nullish but not zero', () => { - spyOn(slider as any, 'isNullishButNotZero').and.returnValue(true); - const setValueSpy = spyOn(slider, 'setValue'); - const positionHandlersAndUpdateTrackSpy = spyOn(slider as any, 'positionHandlersAndUpdateTrack'); + vi.spyOn(slider as any, 'isNullishButNotZero').mockReturnValue(true); + const setValueSpy = vi.spyOn(slider, 'setValue'); + const positionHandlersAndUpdateTrackSpy = vi.spyOn(slider as any, 'positionHandlersAndUpdateTrack'); slider.writeValue(null); fixture.detectChanges(); @@ -351,9 +356,9 @@ describe('IgxSlider', () => { }); it('should set value and update track when value is not nullish and not zero', () => { - spyOn(slider as any, 'isNullishButNotZero').and.returnValue(false); - const setValueSpy = spyOn(slider, 'setValue'); - const positionHandlersAndUpdateTrackSpy = spyOn(slider as any, 'positionHandlersAndUpdateTrack'); + vi.spyOn(slider as any, 'isNullishButNotZero').mockReturnValue(false); + const setValueSpy = vi.spyOn(slider, 'setValue'); + const positionHandlersAndUpdateTrackSpy = vi.spyOn(slider as any, 'positionHandlersAndUpdateTrack'); const value = 10; slider.writeValue(value); @@ -364,8 +369,8 @@ describe('IgxSlider', () => { }); it('should normalize value by step', () => { - spyOn(slider as any, 'isNullishButNotZero').and.returnValue(false); - const normalizeByStepSpy = spyOn(slider as any, 'normalizeByStep'); + vi.spyOn(slider as any, 'isNullishButNotZero').mockReturnValue(false); + const normalizeByStepSpy = vi.spyOn(slider as any, 'normalizeByStep'); const value = 10; slider.writeValue(value); @@ -416,7 +421,7 @@ describe('IgxSlider', () => { expect(sliderInstance.maxValue).toEqual(expectedMax); }); - it('continuous(smooth) sliding should be allowed', async() => { + it('continuous(smooth) sliding should be allowed', async () => { sliderInstance.continuous = true; sliderInstance.thumbLabelVisibilityDuration = 10; fixture.detectChanges(); @@ -448,7 +453,7 @@ describe('IgxSlider', () => { expect(sliderInstance.value).toEqual(sliderInstance.minValue); }); - it('should not move thumb slider and value should remain the same when slider is disabled', async() => { + it('should not move thumb slider and value should remain the same when slider is disabled', async () => { sliderInstance.disabled = true; fixture.detectChanges(); @@ -467,7 +472,7 @@ describe('IgxSlider', () => { await wait(); expect(sliderInstance.value).toBe(sliderInstance.minValue); - }); + }); }); describe('RANGE slider Base tests', () => { @@ -486,7 +491,7 @@ describe('IgxSlider', () => { expect((slider.value as IRangeSliderValue).upper).toBe(slider.upperBound); }); - it('continuous(smooth) sliding should be allowed', async() => { + it('continuous(smooth) sliding should be allowed', async () => { slider.continuous = true; fixture.detectChanges(); @@ -510,7 +515,7 @@ describe('IgxSlider', () => { }); // K.D. Removing this functionality because of 0 benefit and lots of issues. - xit('should switch from lower to upper thumb and vice versa when the lower value is equal to the upper one', () => { + it.skip('should switch from lower to upper thumb and vice versa when the lower value is equal to the upper one', () => { slider.value = { lower: 60, upper: 60 @@ -665,7 +670,7 @@ describe('IgxSlider', () => { it('labels should show/hide on pointer up/down', async () => { const sliderEl = fixture.debugElement.query(By.css(SLIDER_CLASS)); - sliderEl.triggerEventHandler('pointerdown', { pointerId: 1, preventDefault: () => {}}); + sliderEl.triggerEventHandler('pointerdown', { pointerId: 1, preventDefault: () => { } }); await wait(50); fixture.detectChanges(); @@ -673,7 +678,7 @@ describe('IgxSlider', () => { let activeLabel = fixture.debugElement.query(By.css('.igx-slider-thumb-label-to--active')); expect(activeLabel).not.toBeNull(); - sliderEl.triggerEventHandler('pointerup', {pointerId: 1, preventDefault: () => {}}); + sliderEl.triggerEventHandler('pointerup', { pointerId: 1, preventDefault: () => { } }); await wait(slider.thumbLabelVisibilityDuration + 10); fixture.detectChanges(); @@ -684,7 +689,7 @@ describe('IgxSlider', () => { it('should be able to change thumbLabelVisibilityDuration', async () => { const sliderEl = fixture.debugElement.query(By.css(SLIDER_CLASS)); slider.thumbLabelVisibilityDuration = 1000; - sliderEl.triggerEventHandler('pointerdown', {pointerId: 1, preventDefault: () => {}}); + sliderEl.triggerEventHandler('pointerdown', { pointerId: 1, preventDefault: () => { } }); await wait(50); fixture.detectChanges(); @@ -692,7 +697,7 @@ describe('IgxSlider', () => { let activeLabel = fixture.debugElement.query(By.css('.igx-slider-thumb-label-to--active')); expect(activeLabel).not.toBeNull(); - sliderEl.triggerEventHandler('pointerup', {pointerId: 1, preventDefault: () => {}}); + sliderEl.triggerEventHandler('pointerup', { pointerId: 1, preventDefault: () => { } }); await wait(750); fixture.detectChanges(); @@ -845,9 +850,9 @@ describe('IgxSlider', () => { expect(slider).toBeDefined(); expect(slider.upperLabel).toEqual('Winter'); - const valueChangeSpy = spyOn(slider.valueChange, 'emit').and.callThrough(); - const upperValueChangeSpy = spyOn(slider.upperValueChange, 'emit').and.callThrough(); - const lowerValueChangeSpy = spyOn(slider.lowerValueChange, 'emit').and.callThrough(); + const valueChangeSpy = vi.spyOn(slider.valueChange, 'emit'); + const upperValueChangeSpy = vi.spyOn(slider.upperValueChange, 'emit'); + const lowerValueChangeSpy = vi.spyOn(slider.lowerValueChange, 'emit'); UIInteractions.triggerKeyDownEvtUponElem('ArrowLeft', thumb.nativeElement, true); fixture.detectChanges(); @@ -858,17 +863,17 @@ describe('IgxSlider', () => { UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', thumb.nativeElement, true); fixture.detectChanges(); expect(valueChangeSpy).toHaveBeenCalledTimes(1); - expect(valueChangeSpy).toHaveBeenCalledWith({oldValue: 0, value: 1}); + expect(valueChangeSpy).toHaveBeenCalledWith({ oldValue: 0, value: 1 }); UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', thumb.nativeElement, true); fixture.detectChanges(); expect(valueChangeSpy).toHaveBeenCalledTimes(2); - expect(valueChangeSpy).toHaveBeenCalledWith({oldValue: 1, value: 2}); + expect(valueChangeSpy).toHaveBeenCalledWith({ oldValue: 1, value: 2 }); UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', thumb.nativeElement, true); fixture.detectChanges(); expect(valueChangeSpy).toHaveBeenCalledTimes(3); - expect(valueChangeSpy).toHaveBeenCalledWith({oldValue: 2, value: 3}); + expect(valueChangeSpy).toHaveBeenCalledWith({ oldValue: 2, value: 3 }); UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', thumb.nativeElement, true); fixture.detectChanges(); @@ -877,7 +882,7 @@ describe('IgxSlider', () => { UIInteractions.triggerKeyDownEvtUponElem('ArrowLeft', thumb.nativeElement, true); fixture.detectChanges(); expect(valueChangeSpy).toHaveBeenCalledTimes(4); - expect(valueChangeSpy).toHaveBeenCalledWith({oldValue: 3, value: 2}); + expect(valueChangeSpy).toHaveBeenCalledWith({ oldValue: 3, value: 2 }); expect(upperValueChangeSpy).not.toHaveBeenCalled(); expect(lowerValueChangeSpy).not.toHaveBeenCalled(); }); @@ -928,7 +933,7 @@ describe('IgxSlider', () => { const sliderEl = fixture.debugElement.query(By.css(SLIDER_CLASS)); fixture.detectChanges(); - sliderEl.triggerEventHandler('pointerdown', { pointerId: 1, preventDefault: () => {}}); + sliderEl.triggerEventHandler('pointerdown', { pointerId: 1, preventDefault: () => { } }); await wait(100); fixture.detectChanges(); @@ -936,7 +941,7 @@ describe('IgxSlider', () => { let activeLabel = fixture.debugElement.query(By.css('.igx-slider-thumb-label-from--active')); expect(activeLabel).not.toBeNull(); - sliderEl.triggerEventHandler('pointerup', { pointerId: 1, preventDefault: () => {}}); + sliderEl.triggerEventHandler('pointerup', { pointerId: 1, preventDefault: () => { } }); await wait(slider.thumbLabelVisibilityDuration + 10); fixture.detectChanges(); @@ -947,7 +952,7 @@ describe('IgxSlider', () => { it('should be able to change thumbLabelVisibilityDuration', async () => { const sliderEl = fixture.debugElement.query(By.css(SLIDER_CLASS)).nativeElement; slider.thumbLabelVisibilityDuration = 1000; - sliderEl.dispatchEvent( new PointerEvent('pointerdown', { pointerId: 1 })); + sliderEl.dispatchEvent(new PointerEvent('pointerdown', { pointerId: 1 })); await wait(50); fixture.detectChanges(); @@ -955,7 +960,7 @@ describe('IgxSlider', () => { let activeLabel = fixture.debugElement.query(By.css('.igx-slider-thumb-label-from--active')); expect(activeLabel).not.toBeNull(); - sliderEl.dispatchEvent( new PointerEvent('pointerup', { pointerId: 1})); + sliderEl.dispatchEvent(new PointerEvent('pointerup', { pointerId: 1 })); await wait(750); fixture.detectChanges(); @@ -980,32 +985,32 @@ describe('IgxSlider', () => { UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', fromThumb, true); fixture.detectChanges(); - expect(slider.value).toEqual({lower: 1, upper: 6}); + expect(slider.value).toEqual({ lower: 1, upper: 6 }); expect(slider.lowerLabel).toEqual('Tuesday'); UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', fromThumb, true); fixture.detectChanges(); - expect(slider.value).toEqual({lower: 2, upper: 6}); + expect(slider.value).toEqual({ lower: 2, upper: 6 }); expect(slider.lowerLabel).toEqual('Wednesday'); UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', fromThumb, true); fixture.detectChanges(); - expect(slider.value).toEqual({lower: 3, upper: 6}); + expect(slider.value).toEqual({ lower: 3, upper: 6 }); expect(slider.lowerLabel).toEqual('Thursday'); UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', fromThumb, true); fixture.detectChanges(); - expect(slider.value).toEqual({lower: 4, upper: 6}); + expect(slider.value).toEqual({ lower: 4, upper: 6 }); expect(slider.lowerLabel).toEqual('Friday'); UIInteractions.triggerKeyDownEvtUponElem('ArrowLeft', toThumb, true); fixture.detectChanges(); - expect(slider.value).toEqual({lower: 4, upper: 5}); + expect(slider.value).toEqual({ lower: 4, upper: 5 }); expect(slider.upperLabel).toEqual('Saturday'); UIInteractions.triggerKeyDownEvtUponElem('ArrowLeft', toThumb, true); fixture.detectChanges(); - expect(slider.value).toEqual({lower: 4, upper: 4}); + expect(slider.value).toEqual({ lower: 4, upper: 4 }); expect(slider.upperLabel).toEqual('Friday'); }); @@ -1039,7 +1044,7 @@ describe('IgxSlider', () => { it('upper bounds should be applied correctly', () => { const toThumb = fixture.debugElement.query(By.css(THUMB_TO_CLASS)); const fromThumb = fixture.debugElement.query(By.css(THUMB_FROM_CLASS)); - expect(slider.value).toEqual({lower: 0, upper: 6}); + expect(slider.value).toEqual({ lower: 0, upper: 6 }); slider.lowerBound = 1; slider.upperBound = 4; @@ -1048,15 +1053,15 @@ describe('IgxSlider', () => { expect(slider.upperBound).toBe(4); expect(slider.lowerBound).toBe(1); - slider.value = {lower: -1, upper: 3}; + slider.value = { lower: -1, upper: 3 }; fixture.detectChanges(); - expect(slider.value).toEqual({lower: 1, upper: 3}); + expect(slider.value).toEqual({ lower: 1, upper: 3 }); - slider.value = {lower: 1, upper: 10}; + slider.value = { lower: 1, upper: 10 }; fixture.detectChanges(); - expect(slider.value).toEqual({lower: 1, upper: 4}); + expect(slider.value).toEqual({ lower: 1, upper: 4 }); UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', toThumb.nativeElement, true); fixture.detectChanges(); @@ -1076,7 +1081,7 @@ describe('IgxSlider', () => { expect(slider.lowerLabel).toEqual('Tuesday'); }); - it ('when you try to set invalid value for upper/lower value they should not reset', () => { + it('when you try to set invalid value for upper/lower value they should not reset', () => { slider.lowerBound = 1; slider.upperBound = 4; fixture.detectChanges(); @@ -1136,22 +1141,22 @@ describe('IgxSlider', () => { expect(fromThumb).toBeDefined(); expect(slider.upperLabel).toEqual('Sunday'); expect(slider.lowerLabel).toEqual('Monday'); - const valueChangeSpy = spyOn(slider.valueChange, 'emit').and.callThrough(); - const lowerValueChangeSpy = spyOn(slider.lowerValueChange, 'emit').and.callThrough(); - const upperValueChangeSpy = spyOn(slider.upperValueChange, 'emit').and.callThrough(); + const valueChangeSpy = vi.spyOn(slider.valueChange, 'emit'); + const lowerValueChangeSpy = vi.spyOn(slider.lowerValueChange, 'emit'); + const upperValueChangeSpy = vi.spyOn(slider.upperValueChange, 'emit'); UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', fromThumb.nativeElement, true); fixture.detectChanges(); expect(valueChangeSpy).toHaveBeenCalledTimes(1); expect(lowerValueChangeSpy).toHaveBeenCalledTimes(1); - expect(valueChangeSpy).toHaveBeenCalledWith({oldValue: {lower: 0, upper: 6}, value: {lower: 1, upper: 6}}); + expect(valueChangeSpy).toHaveBeenCalledWith({ oldValue: { lower: 0, upper: 6 }, value: { lower: 1, upper: 6 } }); expect(lowerValueChangeSpy).toHaveBeenCalledWith(1); UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', fromThumb.nativeElement, true); fixture.detectChanges(); expect(valueChangeSpy).toHaveBeenCalledTimes(2); expect(lowerValueChangeSpy).toHaveBeenCalledTimes(2); - expect(valueChangeSpy).toHaveBeenCalledWith({oldValue: {lower: 1, upper: 6}, value: {lower: 2, upper: 6}}); + expect(valueChangeSpy).toHaveBeenCalledWith({ oldValue: { lower: 1, upper: 6 }, value: { lower: 2, upper: 6 } }); expect(lowerValueChangeSpy).toHaveBeenCalledWith(2); UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', toThumb.nativeElement, true); @@ -1162,8 +1167,9 @@ describe('IgxSlider', () => { UIInteractions.triggerKeyDownEvtUponElem('ArrowLeft', toThumb.nativeElement, true); fixture.detectChanges(); expect(valueChangeSpy).toHaveBeenCalledTimes(3); - expect(upperValueChangeSpy).toHaveBeenCalledOnceWith(5); - expect(valueChangeSpy).toHaveBeenCalledWith({oldValue: {lower: 2, upper: 6}, value: {lower: 2, upper: 5}}); + expect(upperValueChangeSpy).toHaveBeenCalledTimes(1); + expect(upperValueChangeSpy).toHaveBeenCalledWith(5); + expect(valueChangeSpy).toHaveBeenCalledWith({ oldValue: { lower: 2, upper: 6 }, value: { lower: 2, upper: 5 } }); }); it('dynamically change the type of the slider SLIDER, RANGE, LABEL', () => { @@ -1259,17 +1265,17 @@ describe('IgxSlider', () => { it(`When setting min and max value for range slider, max value should be applied firstly, due correct appliement of the min value.`, () => { - const fix = TestBed.createComponent(SliderMinMaxComponent); - fix.detectChanges(); + const fix = TestBed.createComponent(SliderMinMaxComponent); + fix.detectChanges(); - const slider = fix.componentInstance.slider; - slider.type = IgxSliderType.RANGE; + const slider = fix.componentInstance.slider; + slider.type = IgxSliderType.RANGE; - fix.detectChanges(); + fix.detectChanges(); - expect(slider.minValue).toEqual(fix.componentInstance.minValue); - expect(slider.maxValue).toEqual(fix.componentInstance.maxValue); - }); + expect(slider.minValue).toEqual(fix.componentInstance.minValue); + expect(slider.maxValue).toEqual(fix.componentInstance.maxValue); + }); it('should track min/maxValue if lower/upperBound are undefined (issue #920)', () => { const fixture = TestBed.createComponent(SliderTestComponent); @@ -1456,25 +1462,25 @@ describe('IgxSlider', () => { fix.detectChanges(); const instance = fix.componentInstance; - const spyOnDragFinished = spyOn(instance.slider.dragFinished, 'emit').and.callThrough(); + const spyOnDragFinished = vi.spyOn(instance.slider.dragFinished, 'emit'); const sliderEl = fix.debugElement.query(By.css(SLIDER_CLASS)); const thumbTo = fix.debugElement.query(By.css(THUMB_TO_CLASS)); thumbTo.triggerEventHandler('focus', null); fix.detectChanges(); - sliderEl.triggerEventHandler('pointerdown', {pointerId: 1, clientX: 150, preventDefault: () => { }}); + sliderEl.triggerEventHandler('pointerdown', { pointerId: 1, clientX: 150, preventDefault: () => { } }); fix.detectChanges(); let currentValue = instance.slider.value; expect(spyOnDragFinished).toHaveBeenCalledTimes(0); expect(currentValue).toBeGreaterThan(0); - sliderEl.triggerEventHandler('pointerdown', {pointerId: 1, clientX: 350, preventDefault: () => { }}); + sliderEl.triggerEventHandler('pointerdown', { pointerId: 1, clientX: 350, preventDefault: () => { } }); fix.detectChanges(); expect(spyOnDragFinished).toHaveBeenCalledTimes(0); expect(instance.slider.value).toBeGreaterThan(currentValue as number); currentValue = instance.slider.value; - sliderEl.triggerEventHandler('pointerup', {pointerId: 1, preventDefault: () => { }}); + sliderEl.triggerEventHandler('pointerup', { pointerId: 1, preventDefault: () => { } }); fix.detectChanges(); expect(spyOnDragFinished).toHaveBeenCalledTimes(1); expect(instance.slider.value).toEqual(currentValue); @@ -2040,20 +2046,18 @@ describe('IgxSlider', () => { const verifySecondaryTicsLabelsAreHidden = (ticks, hidden) => { const allTicks = Array.from(ticks.nativeElement.querySelectorAll(`${SLIDER_GROUP_TICKS_CLASS}`)); - const secondaryTicks = allTicks.filter((ticker: any) => - !ticker.classList.contains(SLIDER_PRIMARY_GROUP_TICKS_CLASS_NAME) - ); + const secondaryTicks = allTicks.filter((ticker: any) => !ticker.classList.contains(SLIDER_PRIMARY_GROUP_TICKS_CLASS_NAME)); secondaryTicks.forEach(ticker => { - const label = (ticker as HTMLElement).querySelector(SLIDER_TICK_LABELS_CLASS); - expect(label.classList.contains(SLIDER_TICK_LABELS_HIDDEN_CLASS)).toEqual(hidden); + const label = (ticker as HTMLElement).querySelector(SLIDER_TICK_LABELS_CLASS); + expect(label.classList.contains(SLIDER_TICK_LABELS_HIDDEN_CLASS)).toEqual(hidden); }); }; const verifyPrimaryTicsLabelsAreHidden = (ticks, hidden) => { const primaryTicks = ticks.nativeElement.querySelectorAll(`${SLIDER_PRIMARY_GROUP_TICKS_CLASS}`); primaryTicks.forEach(ticker => { - const label = (ticker as HTMLElement).querySelector(SLIDER_TICK_LABELS_CLASS); - expect(label.classList.contains(SLIDER_TICK_LABELS_HIDDEN_CLASS)).toEqual(hidden); + const label = (ticker as HTMLElement).querySelector(SLIDER_TICK_LABELS_CLASS); + expect(label.classList.contains(SLIDER_TICK_LABELS_HIDDEN_CLASS)).toEqual(hidden); }); }; }); @@ -2095,7 +2099,7 @@ export class SliderRtlComponent { }) export class SliderTicksComponent { - @ViewChild(IgxSliderComponent, {static: true}) + @ViewChild(IgxSliderComponent, { static: true }) public slider: IgxSliderComponent; public primaryTicks = 0; @@ -2113,7 +2117,8 @@ export class SliderTicksComponent { imports: [IgxSliderComponent] }) class SliderInitializeTestComponent { - @ViewChild(IgxSliderComponent, { read: IgxSliderComponent, static: true }) public slider: IgxSliderComponent; + @ViewChild(IgxSliderComponent, { read: IgxSliderComponent, static: true }) + public slider: IgxSliderComponent; } @Component({ @@ -2123,7 +2128,8 @@ class SliderInitializeTestComponent { imports: [IgxSliderComponent] }) export class SliderMinMaxComponent { - @ViewChild(IgxSliderComponent, { read: IgxSliderComponent, static: true }) public slider: IgxSliderComponent; + @ViewChild(IgxSliderComponent, { read: IgxSliderComponent, static: true }) + public slider: IgxSliderComponent; public minValue = 150; public maxValue = 300; @@ -2140,7 +2146,8 @@ export class SliderMinMaxComponent { imports: [IgxSliderComponent] }) class SliderTestComponent { - @ViewChild(IgxSliderComponent, { read: IgxSliderComponent, static: true }) public slider: IgxSliderComponent; + @ViewChild(IgxSliderComponent, { read: IgxSliderComponent, static: true }) + public slider: IgxSliderComponent; public minValue = 0; public maxValue = 10; @@ -2162,7 +2169,8 @@ class SliderTestComponent { imports: [IgxSliderComponent] }) class SliderWithLabelsComponent { - @ViewChild(IgxSliderComponent, { read: IgxSliderComponent, static: true }) public slider: IgxSliderComponent; + @ViewChild(IgxSliderComponent, { read: IgxSliderComponent, static: true }) + public slider: IgxSliderComponent; } @Component({ @@ -2171,7 +2179,8 @@ class SliderWithLabelsComponent { imports: [IgxSliderComponent] }) class RangeSliderTestComponent { - @ViewChild(IgxSliderComponent, { static: true }) public slider: IgxSliderComponent; + @ViewChild(IgxSliderComponent, { static: true }) + public slider: IgxSliderComponent; public type = IgxSliderType.RANGE; } @@ -2205,7 +2214,8 @@ class RangeSliderWithLabelsComponent { imports: [IgxSliderComponent, IgxThumbFromTemplateDirective, IgxThumbToTemplateDirective] }) class RangeSliderWithCustomTemplateComponent { - @ViewChild(IgxSliderComponent, { read: IgxSliderComponent, static: true }) public slider: IgxSliderComponent; + @ViewChild(IgxSliderComponent, { read: IgxSliderComponent, static: true }) + public slider: IgxSliderComponent; public type = IgxSliderType.RANGE; } @@ -2218,9 +2228,11 @@ class RangeSliderWithCustomTemplateComponent { imports: [IgxSliderComponent, FormsModule] }) export class SliderTemplateFormComponent { - @ViewChild(IgxSliderComponent, { read: IgxSliderComponent, static: true }) public slider: IgxSliderComponent; + @ViewChild(IgxSliderComponent, { read: IgxSliderComponent, static: true }) + public slider: IgxSliderComponent; - @Input() public updateOn: 'change' | 'blur' | 'submit' = 'change'; + @Input() + public updateOn: 'change' | 'blur' | 'submit' = 'change'; public value = 10; } @@ -2234,7 +2246,8 @@ export class SliderTemplateFormComponent { imports: [IgxSliderComponent, FormsModule, ReactiveFormsModule] }) export class SliderReactiveFormComponent { - @ViewChild(IgxSliderComponent, { read: IgxSliderComponent, static: true }) public slider: IgxSliderComponent; + @ViewChild(IgxSliderComponent, { read: IgxSliderComponent, static: true }) + public slider: IgxSliderComponent; public formControl = new UntypedFormControl(10); } @@ -2246,7 +2259,8 @@ export class SliderReactiveFormComponent { imports: [IgxSliderComponent] }) export class SliderWithValueAdjustmentComponent { - @ViewChild(IgxSliderComponent, { read: IgxSliderComponent, static: true }) public slider: IgxSliderComponent; + @ViewChild(IgxSliderComponent, { read: IgxSliderComponent, static: true }) + public slider: IgxSliderComponent; public value = { lower: 50, diff --git a/projects/igniteui-angular/snackbar/src/snackbar/snackbar.component.spec.ts b/projects/igniteui-angular/snackbar/src/snackbar/snackbar.component.spec.ts index d8cf22d0adb..c249559818a 100644 --- a/projects/igniteui-angular/snackbar/src/snackbar/snackbar.component.spec.ts +++ b/projects/igniteui-angular/snackbar/src/snackbar/snackbar.component.spec.ts @@ -7,6 +7,7 @@ import { useAnimation } from '@angular/animations'; import { HorizontalAlignment, PositionSettings, VerticalAlignment } from 'igniteui-angular/core'; import { slideInLeft, slideInRight } from 'igniteui-angular/animations'; import { IgxButtonDirective } from '../../../directives/src/directives/button/button.directive'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; describe('IgxSnackbar', () => { beforeEach(waitForAsync(() => { @@ -45,7 +46,7 @@ describe('IgxSnackbar', () => { }); it('should auto hide 1 second after is open', fakeAsync(() => { - spyOn(snackbar.closing, 'emit'); + vi.spyOn(snackbar.closing, 'emit'); const displayTime = 1000; snackbar.displayTime = displayTime; fixture.detectChanges(); @@ -62,7 +63,7 @@ describe('IgxSnackbar', () => { })); it('should not auto hide 1 second after is open', fakeAsync(() => { - spyOn(snackbar.closing, 'emit'); + vi.spyOn(snackbar.closing, 'emit'); const displayTime = 1000; snackbar.displayTime = displayTime; snackbar.autoHide = false; @@ -82,7 +83,7 @@ describe('IgxSnackbar', () => { it('should trigger on action', fakeAsync(() => { snackbar.actionText = 'undo'; snackbar.displayTime = 100; - spyOn(snackbar.clicked, 'emit'); + vi.spyOn(snackbar.clicked, 'emit'); snackbar.open(); tick(100); @@ -95,7 +96,7 @@ describe('IgxSnackbar', () => { })); it('should emit opening when snackbar is shown', fakeAsync(() => { - spyOn(snackbar.opening, 'emit'); + vi.spyOn(snackbar.opening, 'emit'); snackbar.open(); tick(100); expect(snackbar.opening.emit).toHaveBeenCalled(); @@ -105,7 +106,7 @@ describe('IgxSnackbar', () => { it('should emit onOpened when snackbar is opened', fakeAsync(() => { snackbar.displayTime = 100; snackbar.autoHide = false; - spyOn(snackbar.opened, 'emit'); + vi.spyOn(snackbar.opened, 'emit'); snackbar.open(); tick(100); fixture.detectChanges(); @@ -114,7 +115,7 @@ describe('IgxSnackbar', () => { })); it('should emit closing when snackbar is hidden', () => { - spyOn(snackbar.closing, 'emit'); + vi.spyOn(snackbar.closing, 'emit'); snackbar.open(); snackbar.close(); expect(snackbar.closing.emit).toHaveBeenCalled(); @@ -123,7 +124,7 @@ describe('IgxSnackbar', () => { it('should emit onClosed when snackbar is closed', fakeAsync(() => { snackbar.displayTime = 100; snackbar.autoHide = false; - spyOn(snackbar.closed, 'emit'); + vi.spyOn(snackbar.closed, 'emit'); snackbar.open(); snackbar.close(); tick(100); @@ -137,13 +138,13 @@ describe('IgxSnackbar', () => { snackbar.toggle(); tick(100); - expect(snackbar.isVisible).toBeTrue(); - expect(snackbar.collapsed).toBeFalse(); + expect(snackbar.isVisible).toBe(true); + expect(snackbar.collapsed).toBe(false); snackbar.toggle(); tick(100); - expect(snackbar.isVisible).toBeFalse(); - expect(snackbar.collapsed).toBeTrue(); + expect(snackbar.isVisible).toBe(false); + expect(snackbar.collapsed).toBe(true); })); it('can set snackbar message through open method', fakeAsync(() => { @@ -161,8 +162,8 @@ describe('IgxSnackbar', () => { })); it('should be able to set custom positionSettings', () => { const defaultPositionSettings = snackbar.positionSettings; - const defaulOpenAnimationParams = {duration: '.35s', easing: 'cubic-bezier(0.0, 0.0, 0.2, 1)', - fromPosition: 'translateY(100%)', toPosition: 'translateY(0)'}; + const defaulOpenAnimationParams = { duration: '.35s', easing: 'cubic-bezier(0.0, 0.0, 0.2, 1)', + fromPosition: 'translateY(100%)', toPosition: 'translateY(0)' }; expect(defaultPositionSettings.horizontalDirection).toBe(-0.5); expect(defaultPositionSettings.verticalDirection).toBe(0); expect(defaultPositionSettings.openAnimation.options.params).toEqual(defaulOpenAnimationParams); @@ -180,8 +181,8 @@ describe('IgxSnackbar', () => { const customPositionSettings = snackbar.positionSettings; expect(customPositionSettings.horizontalDirection).toBe(-0.5); expect(customPositionSettings.verticalDirection).toBe(-0.5); - expect(customPositionSettings.openAnimation.options.params).toEqual({duration: '1000ms'}); - expect(customPositionSettings.minSize).toEqual({height: 100, width: 100}); + expect(customPositionSettings.openAnimation.options.params).toEqual({ duration: '1000ms' }); + expect(customPositionSettings.minSize).toEqual({ height: 100, width: 100 }); }); }); @@ -212,7 +213,7 @@ describe('IgxSnackbar with custom content', () => { expect(messageEl.nativeElement.innerText).toContain('Item shown'); const customContent = fixture.debugElement.query(By.css('.igx-snackbar__content')); - expect(customContent).toBeTruthy('Custom content is not found'); + expect(customContent, 'Custom content is not found').toBeTruthy(); // Verify the custom button is displayed instead of the snackbar actionText const button = fixture.debugElement.query(By.css('.igx-button')); @@ -222,12 +223,12 @@ describe('IgxSnackbar with custom content', () => { // Verify the message is displayed on the left side of the custom content const messageElRect = messageEl.nativeElement.getBoundingClientRect(); const customContentRect = customContent.nativeElement.getBoundingClientRect(); - expect(messageElRect.left <= customContentRect.left).toBe(true, 'The message is not on the left of the custom content'); + expect(messageElRect.left <= customContentRect.left, 'The message is not on the left of the custom content').toBe(true); // Verify the custom content element is on the left side of the button const buttonRect = button.nativeElement.getBoundingClientRect(); - expect(customContentRect.right <= buttonRect.left).toBe(true, 'The custom element is not on the left of the button'); - expect(messageElRect.right <= buttonRect.left).toBe(true, 'The button is not on the right side of the snackbar content'); + expect(customContentRect.right <= buttonRect.left, 'The custom element is not on the left of the button').toBe(true); + expect(messageElRect.right <= buttonRect.left, 'The button is not on the right side of the snackbar content').toBe(true); snackbar.close(); }); @@ -258,7 +259,8 @@ describe('IgxSnackbar with custom content', () => { imports: [IgxSnackbarComponent] }) class SnackbarInitializeTestComponent { - @ViewChild(IgxSnackbarComponent, { static: true }) public snackbar: IgxSnackbarComponent; + @ViewChild(IgxSnackbarComponent, { static: true }) + public snackbar: IgxSnackbarComponent; public text: string; } @@ -270,6 +272,7 @@ class SnackbarInitializeTestComponent { imports: [IgxSnackbarComponent, IgxButtonDirective] }) class SnackbarCustomContentComponent { - @ViewChild(IgxSnackbarComponent, { static: true }) public snackbar: IgxSnackbarComponent; + @ViewChild(IgxSnackbarComponent, { static: true }) + public snackbar: IgxSnackbarComponent; public text: string; } diff --git a/projects/igniteui-angular/splitter/src/splitter/splitter.component.spec.ts b/projects/igniteui-angular/splitter/src/splitter/splitter.component.spec.ts index 6933bfa774b..f10a8550b30 100644 --- a/projects/igniteui-angular/splitter/src/splitter/splitter.component.spec.ts +++ b/projects/igniteui-angular/splitter/src/splitter/splitter.component.spec.ts @@ -4,6 +4,7 @@ import { SplitterType, IgxSplitterComponent, ISplitterBarResizeEventArgs } from import { By } from '@angular/platform-browser'; import { UIInteractions } from '../../../test-utils/ui-interactions.spec'; import { IgxSplitterPaneComponent } from './splitter-pane/splitter-pane.component'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const SPLITTERBAR_CLASS = 'igx-splitter-bar'; const SPLITTERBAR_DIV_CLASS = '.igx-splitter-bar'; @@ -11,13 +12,11 @@ const SPLITTER_BAR_VERTICAL_CLASS = 'igx-splitter-bar--vertical'; const COLLAPSIBLE_CLASS = 'igx-splitter-bar--collapsible'; describe('IgxSplitter', () => { - beforeEach(waitForAsync(() => - TestBed.configureTestingModule({ - imports: [ - SplitterTestComponent - ] - }).compileComponents() - )); + beforeEach(waitForAsync(() => TestBed.configureTestingModule({ + imports: [ + SplitterTestComponent + ] + }).compileComponents())); let fixture: ComponentFixture; let splitter: IgxSplitterComponent; @@ -68,7 +67,7 @@ describe('IgxSplitter', () => { it('should allow resizing vertical splitter', () => { fixture.componentInstance.type = SplitterType.Vertical; fixture.detectChanges(); - const pane1 = splitter.panes.toArray()[0]; + const pane1 = splitter.panes.toArray()[0]; const pane2 = splitter.panes.toArray()[1]; expect(pane1.size).toBe('auto'); expect(pane2.size).toBe('auto'); @@ -87,7 +86,7 @@ describe('IgxSplitter', () => { expect(pane2.dragSize).toBe(pane2_originalSize + 100 + 'px'); }); it('should allow resizing horizontal splitter', () => { - const pane1 = splitter.panes.toArray()[0]; + const pane1 = splitter.panes.toArray()[0]; const pane2 = splitter.panes.toArray()[1]; expect(pane1.size).toBe('auto'); expect(pane2.size).toBe('auto'); @@ -109,7 +108,7 @@ describe('IgxSplitter', () => { it('should honor minSize/maxSize when resizing.', () => { fixture.componentInstance.type = SplitterType.Vertical; fixture.detectChanges(); - const pane1 = splitter.panes.toArray()[0]; + const pane1 = splitter.panes.toArray()[0]; const pane2 = splitter.panes.toArray()[1]; pane1.minSize = '100px'; pane1.maxSize = '300px'; @@ -136,10 +135,10 @@ describe('IgxSplitter', () => { it('should not allow drag resize if resizable is set to false.', () => { const splitterBarComponent = fixture.debugElement.query(By.css(SPLITTERBAR_CLASS)).context; expect(splitterBarComponent.cursor).toBe('col-resize'); - const pane1 = splitter.panes.toArray()[0]; + const pane1 = splitter.panes.toArray()[0]; pane1.resizable = false; fixture.detectChanges(); - const args = {cancel: false}; + const args = { cancel: false }; splitterBarComponent.onDragStart(args); expect(args.cancel).toBeTruthy(); expect(splitterBarComponent.cursor).toBe(''); @@ -148,7 +147,7 @@ describe('IgxSplitter', () => { it('should allow resizing with up/down arrow keys', () => { fixture.componentInstance.type = SplitterType.Vertical; fixture.detectChanges(); - const pane1 = splitter.panes.toArray()[0]; + const pane1 = splitter.panes.toArray()[0]; const pane2 = splitter.panes.toArray()[1]; expect(pane1.size).toBe('auto'); expect(pane2.size).toBe('auto'); @@ -177,7 +176,7 @@ describe('IgxSplitter', () => { it('should allow resizing with left/right arrow keys', () => { fixture.componentInstance.type = SplitterType.Horizontal; fixture.detectChanges(); - const pane1 = splitter.panes.toArray()[0]; + const pane1 = splitter.panes.toArray()[0]; const pane2 = splitter.panes.toArray()[1]; expect(pane1.size).toBe('auto'); expect(pane2.size).toBe('auto'); @@ -206,7 +205,7 @@ describe('IgxSplitter', () => { it('should allow expand/collapse with Ctrl + up/down arrow keys', () => { fixture.componentInstance.type = SplitterType.Vertical; fixture.detectChanges(); - const pane1 = splitter.panes.toArray()[0]; + const pane1 = splitter.panes.toArray()[0]; const pane2 = splitter.panes.toArray()[1]; expect(pane1.size).toBe('auto'); expect(pane2.size).toBe('auto'); @@ -229,7 +228,7 @@ describe('IgxSplitter', () => { it('should allow expand/collapse with Ctrl + left/right arrow keys', () => { fixture.componentInstance.type = SplitterType.Horizontal; fixture.detectChanges(); - const pane1 = splitter.panes.toArray()[0]; + const pane1 = splitter.panes.toArray()[0]; const pane2 = splitter.panes.toArray()[1]; expect(pane1.size).toBe('auto'); expect(pane2.size).toBe('auto'); @@ -250,7 +249,7 @@ describe('IgxSplitter', () => { }); it('should allow resize in % when pane size is auto.', () => { - const pane1 = splitter.panes.toArray()[0]; + const pane1 = splitter.panes.toArray()[0]; const pane2 = splitter.panes.toArray()[1]; expect(pane1.size).toBe('auto'); expect(pane2.size).toBe('auto'); @@ -268,15 +267,15 @@ describe('IgxSplitter', () => { splitterBarComponent.movingEnd.emit(-100); fixture.detectChanges(); - expect(pane1.size.indexOf('%') !== -1).toBeTrue(); - expect(pane2.size.indexOf('%') !== -1).toBeTrue(); + expect(pane1.size.indexOf('%') !== -1).toBe(true); + expect(pane2.size.indexOf('%') !== -1).toBe(true); expect(pane1.element.offsetWidth).toBeCloseTo(pane1_originalSize + 100); expect(pane2.element.offsetWidth).toBeCloseTo(pane2_originalSize - 100); }); it('should allow mixing % and px sizes.', () => { - const pane1 = splitter.panes.toArray()[0]; + const pane1 = splitter.panes.toArray()[0]; const pane2 = splitter.panes.toArray()[1]; pane1.size = '200px'; fixture.detectChanges(); @@ -297,14 +296,14 @@ describe('IgxSplitter', () => { // fist pane should remain in px expect(pane1.size).toBe('300px'); - expect(pane2.size.indexOf('%') !== -1).toBeTrue(); + expect(pane2.size.indexOf('%') !== -1).toBe(true); expect(pane1.element.offsetWidth).toBeCloseTo(pane1_originalSize + 100); expect(pane2.element.offsetWidth).toBeCloseTo(pane2_originalSize - 100); }); it('should reset transform style of vertical splitter bar after dragging', async () => { - const pane1 = splitter.panes.toArray()[0]; + const pane1 = splitter.panes.toArray()[0]; pane1.size = '200px'; fixture.detectChanges(); @@ -338,7 +337,8 @@ describe('IgxSplitter pane toggle', () => { ] }).compileComponents())); - let fixture; let splitter; + let fixture; + let splitter; beforeEach(waitForAsync(() => { fixture = TestBed.createComponent(SplitterTogglePaneComponent); fixture.detectChanges(); @@ -408,9 +408,9 @@ describe('IgxSplitter pane toggle', () => { it('should emit resizing events on splitter bar move: resizeStart, resizing, resizeEnd.', () => { fixture.componentInstance.type = SplitterType.Vertical; fixture.detectChanges(); - spyOn(splitter.resizeStart, 'emit').and.callThrough(); - spyOn(splitter.resizing, 'emit').and.callThrough(); - spyOn(splitter.resizeEnd, 'emit').and.callThrough(); + vi.spyOn(splitter.resizeStart, 'emit'); + vi.spyOn(splitter.resizing, 'emit'); + vi.spyOn(splitter.resizeEnd, 'emit'); const pane1 = splitter.panes.toArray()[0]; const pane2 = splitter.panes.toArray()[1]; @@ -442,7 +442,8 @@ describe('IgxSplitter pane collapse', () => { ] }).compileComponents())); - let fixture; let splitter; + let fixture; + let splitter; beforeEach(waitForAsync(() => { fixture = TestBed.createComponent(SplitterCollapsedPaneComponent); fixture.detectChanges(); @@ -476,7 +477,8 @@ describe('IgxSplitter resizing with minSize and browser window is shrinked', () }).compileComponents(); })); - let fixture; let splitter; + let fixture; + let splitter; beforeEach(waitForAsync(() => { fixture = TestBed.createComponent(SplitterMinSiezComponent); fixture.detectChanges(); @@ -488,11 +490,11 @@ describe('IgxSplitter resizing with minSize and browser window is shrinked', () const pane2 = splitter.panes.toArray()[1]; const splitterBarComponent = fixture.debugElement.query(By.css(SPLITTERBAR_CLASS)).context; const minSize = parseInt(pane1.minSize); - spyOn(splitter, 'onMoveEnd').and.callThrough(); + vi.spyOn(splitter, 'onMoveEnd'); splitterBarComponent.moveStart.emit(pane1); fixture.detectChanges(); - splitterBarComponent.movingEnd.emit(splitter.getTotalSize() -minSize); + splitterBarComponent.movingEnd.emit(splitter.getTotalSize() - minSize); fixture.detectChanges(); splitter.elementRef.nativeElement.style.width = '500px'; diff --git a/projects/igniteui-angular/stepper/src/stepper/stepper.component.spec.ts b/projects/igniteui-angular/stepper/src/stepper/stepper.component.spec.ts index 5dfafc2feed..9208985d101 100644 --- a/projects/igniteui-angular/stepper/src/stepper/stepper.component.spec.ts +++ b/projects/igniteui-angular/stepper/src/stepper/stepper.component.spec.ts @@ -9,20 +9,12 @@ import { IgxInputDirective, IgxInputGroupComponent } from '../../../input-group/ import { IgxAngularAnimationService, PlatformUtil, ɵDirection } from 'igniteui-angular/core'; import { UIInteractions } from '../../../test-utils/ui-interactions.spec'; import { IgxStepComponent } from './step/step.component'; -import { - HorizontalAnimationType, - IGX_STEPPER_COMPONENT, - IgxStepperOrientation, - IgxStepperTitlePosition, - IgxStepType, - IStepChangedEventArgs, - IStepChangingEventArgs, - VerticalAnimationType -} from './stepper.common'; +import { HorizontalAnimationType, IGX_STEPPER_COMPONENT, IgxStepperOrientation, IgxStepperTitlePosition, IgxStepType, IStepChangedEventArgs, IStepChangingEventArgs, VerticalAnimationType } from './stepper.common'; import { IgxStepperComponent } from './stepper.component'; import { IgxStepActiveIndicatorDirective, IgxStepCompletedIndicatorDirective, IgxStepContentDirective, IgxStepIndicatorDirective, IgxStepInvalidIndicatorDirective, IgxStepSubtitleDirective, IgxStepTitleDirective } from './stepper.directive'; import { IgxStepperService } from './stepper.service'; import { IgxDirectionality } from 'igniteui-angular/core/src/services/direction/directionality'; +import { describe, it, expect, beforeAll, beforeEach, afterAll, vi } from 'vitest'; const STEPPER_CLASS = 'igx-stepper'; const STEPPER_HEADER = 'igx-stepper__header'; @@ -53,43 +45,38 @@ const getStepperPositions = (): string[] => { return positions; }; -const testAnimationBehavior = ( - val: any, - fix: ComponentFixture, - isHorAnimTypeInvalidTest: boolean -): void => { +const testAnimationBehavior = (val: any, fix: ComponentFixture, isHorAnimTypeInvalidTest: boolean): void => { const stepper = fix.componentInstance.stepper; stepper.steps[0].active = true; fix.detectChanges(); const previousActiveStep = stepper.steps[0]; - const activeChangeSpy = spyOn(previousActiveStep.activeChange, 'emit'); - activeChangeSpy.calls.reset(); + const activeChangeSpy = vi.spyOn(previousActiveStep.activeChange, 'emit'); + activeChangeSpy.mockClear(); stepper.next(); fix.detectChanges(); tick(1000); if (!isHorAnimTypeInvalidTest) { - expect(previousActiveStep.activeChange.emit).withContext(val).toHaveBeenCalledOnceWith(false); + expect(previousActiveStep.activeChange.emit, val).toHaveBeenCalledTimes(1); + expect(previousActiveStep.activeChange.emit, val).toHaveBeenCalledWith(false); } else { - expect(previousActiveStep.activeChange.emit).withContext(val).not.toHaveBeenCalled(); + expect(previousActiveStep.activeChange.emit, val).not.toHaveBeenCalled(); } - activeChangeSpy.calls.reset(); + activeChangeSpy.mockClear(); }; describe('Rendering Tests', () => { let fix: ComponentFixture; let stepper: IgxStepperComponent; - beforeEach( - waitForAsync(() => { - TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule, - IgxStepperSampleTestComponent, - IgxStepperLinearComponent - ] - }).compileComponents(); - }) - ); + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [ + NoopAnimationsModule, + IgxStepperSampleTestComponent, + IgxStepperLinearComponent + ] + }).compileComponents(); + })); beforeEach(() => { fix = TestBed.createComponent(IgxStepperSampleTestComponent); fix.detectChanges(); @@ -108,15 +95,15 @@ describe('Rendering Tests', () => { }); it('should not allow activating a step with next/prev methods when disabled is set to true', fakeAsync(() => { - const serviceExpandSpy = spyOn((stepper as any).stepperService, 'expand').and.callThrough(); - const serviceCollapseSpy = spyOn((stepper as any).stepperService, 'collapse').and.callThrough(); + const serviceExpandSpy = vi.spyOn((stepper as any).stepperService, 'expand'); + const serviceCollapseSpy = vi.spyOn((stepper as any).stepperService, 'collapse'); stepper.orientation = IgxStepperOrientation.Horizontal; stepper.steps[0].active = true; stepper.steps[1].disabled = true; fix.detectChanges(); tick(); - expect(stepper.steps[1].nativeElement).toHaveClass('igx-stepper__step--disabled'); + expect(stepper.steps[1].nativeElement.classList.contains('igx-stepper__step--disabled')).toBe(true); stepper.next(); fix.detectChanges(); @@ -125,11 +112,13 @@ describe('Rendering Tests', () => { expect(stepper.steps[1].active).toBeFalsy(); expect(stepper.steps[2].isAccessible).toBeTruthy(); expect(stepper.steps[2].active).toBeTruthy(); - expect(serviceExpandSpy).toHaveBeenCalledOnceWith(stepper.steps[2]); - expect(serviceCollapseSpy).toHaveBeenCalledOnceWith(stepper.steps[0]); + expect(serviceExpandSpy).toHaveBeenCalledTimes(1); + expect(serviceExpandSpy).toHaveBeenCalledWith(stepper.steps[2]); + expect(serviceCollapseSpy).toHaveBeenCalledTimes(1); + expect(serviceCollapseSpy).toHaveBeenCalledWith(stepper.steps[0]); - serviceExpandSpy.calls.reset(); - serviceCollapseSpy.calls.reset(); + serviceExpandSpy.mockClear(); + serviceCollapseSpy.mockClear(); stepper.orientation = IgxStepperOrientation.Vertical; stepper.steps[0].active = true; @@ -144,8 +133,10 @@ describe('Rendering Tests', () => { expect(stepper.steps[1].active).toBeFalsy(); expect(stepper.steps[2].isAccessible).toBeTruthy(); expect(stepper.steps[2].active).toBeTruthy(); - expect(serviceExpandSpy).toHaveBeenCalledOnceWith(stepper.steps[2]); - expect(serviceCollapseSpy).toHaveBeenCalledOnceWith(stepper.steps[0]); + expect(serviceExpandSpy).toHaveBeenCalledTimes(1); + expect(serviceExpandSpy).toHaveBeenCalledWith(stepper.steps[2]); + expect(serviceCollapseSpy).toHaveBeenCalledTimes(1); + expect(serviceCollapseSpy).toHaveBeenCalledWith(stepper.steps[0]); })); it('should calculate disabled steps properly when the stepper is initially in linear mode', fakeAsync(() => { @@ -153,7 +144,7 @@ describe('Rendering Tests', () => { fixture.detectChanges(); const linearStepper = fixture.componentInstance.stepper; - const serviceExpandSpy = spyOn((linearStepper as any).stepperService, 'expand').and.callThrough(); + const serviceExpandSpy = vi.spyOn((linearStepper as any).stepperService, 'expand'); linearStepper.next(); fixture.detectChanges(); tick(); @@ -165,7 +156,7 @@ describe('Rendering Tests', () => { })); it('should not allow moving forward to next step in linear mode if the previous step is invalid', fakeAsync(() => { - const serviceExpandSpy = spyOn((stepper as any).stepperService, 'expand').and.callThrough(); + const serviceExpandSpy = vi.spyOn((stepper as any).stepperService, 'expand'); stepper.orientation = IgxStepperOrientation.Horizontal; stepper.linear = true; stepper.steps[0].isValid = false; @@ -222,10 +213,10 @@ describe('Rendering Tests', () => { })); it('should emit ing and ed events when a step is activated', fakeAsync(() => { - const changingSpy = spyOn(stepper.activeStepChanging, 'emit').and.callThrough(); - const changedSpy = spyOn(stepper.activeStepChanged, 'emit').and.callThrough(); - const serviceExpandSpy = spyOn((stepper as any).stepperService, 'expand').and.callThrough(); - const serviceCollapseSpy = spyOn((stepper as any).stepperService, 'collapse').and.callThrough(); + const changingSpy = vi.spyOn(stepper.activeStepChanging, 'emit'); + const changedSpy = vi.spyOn(stepper.activeStepChanged, 'emit'); + const serviceExpandSpy = vi.spyOn((stepper as any).stepperService, 'expand'); + const serviceCollapseSpy = vi.spyOn((stepper as any).stepperService, 'collapse'); expect(changingSpy).not.toHaveBeenCalled(); expect(changedSpy).not.toHaveBeenCalled(); @@ -257,16 +248,20 @@ describe('Rendering Tests', () => { tick(); expect(stepper.steps[1].active).toBeTruthy(); - expect(changingSpy).toHaveBeenCalledOnceWith(argsIng); - expect(changedSpy).toHaveBeenCalledOnceWith(argsEd); - expect(serviceExpandSpy).toHaveBeenCalledOnceWith(stepper.steps[1]); - expect(serviceCollapseSpy).toHaveBeenCalledOnceWith(stepper.steps[0]); + expect(changingSpy).toHaveBeenCalledTimes(1); + expect(changingSpy).toHaveBeenCalledWith(argsIng); + expect(changedSpy).toHaveBeenCalledTimes(1); + expect(changedSpy).toHaveBeenCalledWith(argsEd); + expect(serviceExpandSpy).toHaveBeenCalledTimes(1); + expect(serviceExpandSpy).toHaveBeenCalledWith(stepper.steps[1]); + expect(serviceCollapseSpy).toHaveBeenCalledTimes(1); + expect(serviceCollapseSpy).toHaveBeenCalledWith(stepper.steps[0]); })); it('should be able to cancel the activeStepChanging event', fakeAsync(() => { - const changingSpy = spyOn(stepper.activeStepChanging, 'emit').and.callThrough(); - const serviceExpandSpy = spyOn((stepper as any).stepperService, 'expand').and.callThrough(); - const serviceCollapseSpy = spyOn((stepper as any).stepperService, 'collapse').and.callThrough(); + const changingSpy = vi.spyOn(stepper.activeStepChanging, 'emit'); + const serviceExpandSpy = vi.spyOn((stepper as any).stepperService, 'expand'); + const serviceCollapseSpy = vi.spyOn((stepper as any).stepperService, 'collapse'); expect(changingSpy).not.toHaveBeenCalled(); @@ -287,34 +282,38 @@ describe('Rendering Tests', () => { expect(stepper.steps[1].active).toBeFalsy(); expect(stepper.steps[0].active).toBeTruthy(); - expect(changingSpy).toHaveBeenCalledOnceWith(argsIng); - expect(serviceExpandSpy).toHaveBeenCalledOnceWith(stepper.steps[1]); + expect(changingSpy).toHaveBeenCalledTimes(1); + expect(changingSpy).toHaveBeenCalledWith(argsIng); + expect(serviceExpandSpy).toHaveBeenCalledTimes(1); + expect(serviceExpandSpy).toHaveBeenCalledWith(stepper.steps[1]); expect(serviceCollapseSpy).not.toHaveBeenCalled(); })); it('a step should emit activeChange event when its active property changes', fakeAsync(() => { - const fourthActiveChangeSpy = spyOn(stepper.steps[3].activeChange, 'emit').and.callThrough(); - const fifthActiveChangeSpy = spyOn(stepper.steps[4].activeChange, 'emit').and.callThrough(); - const serviceExpandAPISpy = spyOn((stepper as any).stepperService, 'expandThroughApi').and.callThrough(); + const fourthActiveChangeSpy = vi.spyOn(stepper.steps[3].activeChange, 'emit'); + const fifthActiveChangeSpy = vi.spyOn(stepper.steps[4].activeChange, 'emit'); + const serviceExpandAPISpy = vi.spyOn((stepper as any).stepperService, 'expandThroughApi'); expect(fourthActiveChangeSpy).not.toHaveBeenCalled(); expect(fifthActiveChangeSpy).not.toHaveBeenCalled(); stepper.steps[0].active = true; fix.detectChanges(); - expect(serviceExpandAPISpy).toHaveBeenCalledOnceWith(stepper.steps[0]); + expect(serviceExpandAPISpy).toHaveBeenCalledTimes(1); + expect(serviceExpandAPISpy).toHaveBeenCalledWith(stepper.steps[0]); stepper.steps[3].active = true; fix.detectChanges(); tick(); expect(stepper.steps[3].active).toBeTruthy(); - expect(stepper.steps[3].activeChange.emit).toHaveBeenCalledOnceWith(true); + expect(stepper.steps[3].activeChange.emit).toHaveBeenCalledTimes(1); + expect(stepper.steps[3].activeChange.emit).toHaveBeenCalledWith(true); expect(fifthActiveChangeSpy).not.toHaveBeenCalled(); - expect(serviceExpandAPISpy.calls.mostRecent().args[0]).toBe(stepper.steps[3]); + expect(vi.mocked(serviceExpandAPISpy).mock.lastCall[0]).toBe(stepper.steps[3]); - fourthActiveChangeSpy.calls.reset(); - serviceExpandAPISpy.calls.reset(); + fourthActiveChangeSpy.mockClear(); + serviceExpandAPISpy.mockClear(); stepper.steps[4].active = true; fix.detectChanges(); @@ -322,38 +321,33 @@ describe('Rendering Tests', () => { expect(stepper.steps[4].active).toBeTruthy(); expect(stepper.steps[3].active).toBeFalsy(); - expect(fifthActiveChangeSpy).toHaveBeenCalledOnceWith(true); - expect(fourthActiveChangeSpy).toHaveBeenCalledOnceWith(false); - expect(serviceExpandAPISpy).toHaveBeenCalledOnceWith(stepper.steps[4]); + expect(fifthActiveChangeSpy).toHaveBeenCalledTimes(1); + expect(fifthActiveChangeSpy).toHaveBeenCalledWith(true); + expect(fourthActiveChangeSpy).toHaveBeenCalledTimes(1); + expect(fourthActiveChangeSpy).toHaveBeenCalledWith(false); + expect(serviceExpandAPISpy).toHaveBeenCalledTimes(1); + expect(serviceExpandAPISpy).toHaveBeenCalledWith(stepper.steps[4]); })); }); describe('Appearance', () => { - beforeAll(() => { - jasmine.getEnv().allowRespy(true); - }); - - afterAll(() => { - jasmine.getEnv().allowRespy(false); - }); - it('should apply the appropriate class to a stepper in horizontal mode', () => { stepper.orientation = IgxStepperOrientation.Horizontal; fix.detectChanges(); - expect(stepper.nativeElement).toHaveClass('igx-stepper--horizontal'); + expect(stepper.nativeElement.classList.contains('igx-stepper--horizontal')).toBe(true); // no css class is applied when the stepper is in vertical mode }); it('should indicate the currently active step', () => { const step0Header = stepper.steps[0].nativeElement.querySelector(`.${STEP_HEADER}`); const step1Header = stepper.steps[1].nativeElement.querySelector(`.${STEP_HEADER}`); - const serviceExpandSpy = spyOn((stepper as any).stepperService, 'expand').and.callThrough(); + const serviceExpandSpy = vi.spyOn((stepper as any).stepperService, 'expand'); stepper.steps[0].active = true; fix.detectChanges(); - expect(step0Header).toHaveClass(CURRENT_CLASS); + expect(step0Header.classList.contains(CURRENT_CLASS)).toBe(true); stepper.steps[1].active = true; stepper.steps[1].nativeElement.focus(); @@ -362,9 +356,10 @@ describe('Rendering Tests', () => { UIInteractions.triggerKeyDownEvtUponElem(' ', stepper.steps[1].nativeElement); fix.detectChanges(); - expect(step0Header).not.toHaveClass(CURRENT_CLASS); - expect(step1Header).toHaveClass(CURRENT_CLASS); - expect(serviceExpandSpy).toHaveBeenCalledOnceWith(stepper.steps[1]); + expect(step0Header.classList.contains(CURRENT_CLASS)).toBe(false); + expect(step1Header.classList.contains(CURRENT_CLASS)).toBe(true); + expect(serviceExpandSpy).toHaveBeenCalledTimes(1); + expect(serviceExpandSpy).toHaveBeenCalledWith(stepper.steps[1]); }); it('should indicate that a step is completed', () => { @@ -372,17 +367,17 @@ describe('Rendering Tests', () => { fix.detectChanges(); expect(stepper.steps[0].completed).toBeFalsy(); - expect(stepper.steps[0].nativeElement).not.toHaveClass(COMPLETED_CLASS); + expect(stepper.steps[0].nativeElement.classList.contains(COMPLETED_CLASS)).toBe(false); stepper.steps[0].completed = true; fix.detectChanges(); - expect(stepper.steps[0].nativeElement).toHaveClass(COMPLETED_CLASS); + expect(stepper.steps[0].nativeElement.classList.contains(COMPLETED_CLASS)).toBe(true); stepper.steps[1].completed = true; fix.detectChanges(); - expect(stepper.steps[1].nativeElement).toHaveClass(COMPLETED_CLASS); + expect(stepper.steps[1].nativeElement.classList.contains(COMPLETED_CLASS)).toBe(true); }); it('should indicate that a step is invalid', () => { @@ -390,24 +385,24 @@ describe('Rendering Tests', () => { stepper.steps[0].isValid = true; fix.detectChanges(); - expect(step0Header).not.toHaveClass(INVALID_CLASS); + expect(step0Header.classList.contains(INVALID_CLASS)).toBe(false); stepper.steps[0].isValid = false; fix.detectChanges(); - expect(step0Header).not.toHaveClass(INVALID_CLASS); + expect(step0Header.classList.contains(INVALID_CLASS)).toBe(false); stepper.steps[1].active = true; fix.detectChanges(); - expect(step0Header).toHaveClass(INVALID_CLASS); + expect(step0Header.classList.contains(INVALID_CLASS)).toBe(true); //indicate that a step is disabled without indicating that it is also invalid stepper.steps[0].disabled = true; fix.detectChanges(); - expect(step0Header).not.toHaveClass(INVALID_CLASS); - expect(stepper.steps[0].nativeElement).toHaveClass(DISABLED_CLASS); + expect(step0Header.classList.contains(INVALID_CLASS)).toBe(false); + expect(stepper.steps[0].nativeElement.classList.contains(DISABLED_CLASS)).toBe(true); }); it('should render the visual step element according to the specified stepType', () => { @@ -471,7 +466,7 @@ describe('Rendering Tests', () => { for (const step of stepper.steps) { expect(step.titlePosition).toBe(stepper._defaultTitlePosition); expect(step.titlePosition).toBe(IgxStepperTitlePosition.Bottom); - expect(step.nativeElement).toHaveClass(`igx-stepper__step--${stepper._defaultTitlePosition}`); + expect(step.nativeElement.classList.contains(`igx-stepper__step--${stepper._defaultTitlePosition}`)).toBe(true); } const positions = getStepperPositions(); @@ -480,7 +475,7 @@ describe('Rendering Tests', () => { fix.detectChanges(); for (const step of stepper.steps) { - expect(step.nativeElement).toHaveClass(`igx-stepper__step--${pos}`); + expect(step.nativeElement.classList.contains(`igx-stepper__step--${pos}`)).toBe(true); } }); @@ -492,7 +487,7 @@ describe('Rendering Tests', () => { for (const step of stepper.steps) { expect(step.titlePosition).toBe(stepper._defaultTitlePosition); expect(step.titlePosition).toBe(IgxStepperTitlePosition.End); - expect(step.nativeElement).toHaveClass(`igx-stepper__step--${stepper._defaultTitlePosition}`); + expect(step.nativeElement.classList.contains(`igx-stepper__step--${stepper._defaultTitlePosition}`)).toBe(true); } positions.forEach((pos: IgxStepperTitlePosition) => { @@ -500,7 +495,7 @@ describe('Rendering Tests', () => { fix.detectChanges(); for (const step of stepper.steps) { - expect(step.nativeElement).toHaveClass(`igx-stepper__step--${pos}`); + expect(step.nativeElement.classList.contains(`igx-stepper__step--${pos}`)).toBe(true); } }); }); @@ -528,9 +523,9 @@ describe('Rendering Tests', () => { const step0Header = stepper.steps[0].nativeElement.querySelector(`.${STEP_HEADER}`); let indicatorElement = step0Header.querySelector(`.${STEP_INDICATOR_CLASS}`).children[0]; - expect(step0Header).not.toHaveClass(INVALID_CLASS); - expect(step0Header).toHaveClass(CURRENT_CLASS); - expect(stepper.steps[0].nativeElement).not.toHaveClass(COMPLETED_CLASS); + expect(step0Header.classList.contains(INVALID_CLASS)).toBe(false); + expect(step0Header.classList.contains(CURRENT_CLASS)).toBe(true); + expect(stepper.steps[0].nativeElement.classList.contains(COMPLETED_CLASS)).toBe(false); expect(indicatorElement.tagName).toBe('IGX-ICON'); expect(indicatorElement.textContent).toBe('edit'); @@ -541,9 +536,9 @@ describe('Rendering Tests', () => { indicatorElement = step0Header.querySelector(`.${STEP_INDICATOR_CLASS}`).children[0]; - expect(step0Header).toHaveClass(INVALID_CLASS); - expect(step0Header).not.toHaveClass(CURRENT_CLASS); - expect(stepper.steps[0].nativeElement).not.toHaveClass(COMPLETED_CLASS); + expect(step0Header.classList.contains(INVALID_CLASS)).toBe(true); + expect(step0Header.classList.contains(CURRENT_CLASS)).toBe(false); + expect(stepper.steps[0].nativeElement.classList.contains(COMPLETED_CLASS)).toBe(false); expect(indicatorElement.tagName).toBe('IGX-ICON'); expect(indicatorElement.textContent).toBe('error'); @@ -553,9 +548,9 @@ describe('Rendering Tests', () => { indicatorElement = step0Header.querySelector(`.${STEP_INDICATOR_CLASS}`).children[0]; - expect(step0Header).not.toHaveClass(INVALID_CLASS); - expect(step0Header).not.toHaveClass(CURRENT_CLASS); - expect(stepper.steps[0].nativeElement).toHaveClass(COMPLETED_CLASS); + expect(step0Header.classList.contains(INVALID_CLASS)).toBe(false); + expect(step0Header.classList.contains(CURRENT_CLASS)).toBe(false); + expect(stepper.steps[0].nativeElement.classList.contains(COMPLETED_CLASS)).toBe(true); expect(indicatorElement.tagName).toBe('IGX-ICON'); expect(indicatorElement.textContent).toBe('check'); }); @@ -565,14 +560,14 @@ describe('Rendering Tests', () => { fix.detectChanges(); expect(stepper.contentTop).toBeFalsy(); - expect(stepper.nativeElement.children[0]).toHaveClass(STEPPER_HEADER); - expect(stepper.nativeElement.children[1]).toHaveClass(STEPPER_BODY); + expect(stepper.nativeElement.children[0].classList.contains(STEPPER_HEADER)).toBe(true); + expect(stepper.nativeElement.children[1].classList.contains(STEPPER_BODY)).toBe(true); stepper.contentTop = true; fix.detectChanges(); - expect(stepper.nativeElement.children[0]).toHaveClass(STEPPER_BODY); - expect(stepper.nativeElement.children[1]).toHaveClass(STEPPER_HEADER); + expect(stepper.nativeElement.children[0].classList.contains(STEPPER_BODY)).toBe(true); + expect(stepper.nativeElement.children[1].classList.contains(STEPPER_HEADER)).toBe(true); }); it('should allow modifying animationSettings that are used for transitioning between steps ', fakeAsync(() => { @@ -726,8 +721,8 @@ describe('Rendering Tests', () => { describe('Keyboard navigation', () => { it('should navigate to first/last step on Home/End key press', fakeAsync(() => { - const serviceExpandSpy = spyOn((stepper as any).stepperService, 'expand').and.callThrough(); - const serviceCollapseSpy = spyOn((stepper as any).stepperService, 'collapse').and.callThrough(); + const serviceExpandSpy = vi.spyOn((stepper as any).stepperService, 'expand'); + const serviceCollapseSpy = vi.spyOn((stepper as any).stepperService, 'collapse'); stepper.steps[3].active = true; stepper.steps[3].nativeElement.focus(); @@ -751,7 +746,7 @@ describe('Rendering Tests', () => { })); it('should activate the currently focused step on Enter/Space key press', fakeAsync(() => { - const serviceExpandSpy = spyOn((stepper as any).stepperService, 'expand').and.callThrough(); + const serviceExpandSpy = vi.spyOn((stepper as any).stepperService, 'expand'); stepper.steps[0].active = true; fix.detectChanges(); @@ -767,7 +762,8 @@ describe('Rendering Tests', () => { expect(stepper.steps[3].nativeElement as Element).toBe(document.activeElement); expect(stepper.steps[3].active).toBeTruthy(); - expect(serviceExpandSpy).toHaveBeenCalledOnceWith(stepper.steps[3]); + expect(serviceExpandSpy).toHaveBeenCalledTimes(1); + expect(serviceExpandSpy).toHaveBeenCalledWith(stepper.steps[3]); stepper.steps[4].nativeElement.focus(); fix.detectChanges(); @@ -779,7 +775,7 @@ describe('Rendering Tests', () => { fix.detectChanges(); expect(stepper.steps[4].active).toBeTruthy(); - expect(serviceExpandSpy.calls.mostRecent().args[0]).toBe(stepper.steps[4]); + expect(vi.mocked(serviceExpandSpy).mock.lastCall[0]).toBe(stepper.steps[4]); })); it('should navigate to the next/previous step in horizontal orientation on Arrow Right/Left key press', fakeAsync(() => { @@ -938,14 +934,6 @@ describe('Stepper service unit tests', () => { let steps: IgxStepComponent[] = []; let stepper: IgxStepperComponent; - beforeAll(() => { - jasmine.getEnv().allowRespy(true); - }); - - afterAll(() => { - jasmine.getEnv().allowRespy(false); - }); - beforeEach(() => { mockElement = { style: { visibility: '', cursor: '', transitionDuration: '' }, @@ -1041,27 +1029,28 @@ describe('Stepper service unit tests', () => { }); it('should expand a step by activating it and firing the step\'s activeChange event', () => { - spyOnProperty(stepper, 'orientation', 'get').and.returnValue(IgxStepperOrientation.Horizontal); - spyOnProperty(stepper, 'steps', 'get').and.returnValue(steps); + vi.spyOn(stepper, 'orientation', 'get').mockReturnValue(IgxStepperOrientation.Horizontal); + vi.spyOn(stepper, 'steps', 'get').mockReturnValue(steps); stepperService.activeStep = steps[0]; steps[0].contentContainer = mockElementRef; steps[1].contentContainer = mockElementRef; - spyOn(steps[0].activeChange, 'emit').and.callThrough(); - spyOn(steps[1].activeChange, 'emit').and.callThrough(); + vi.spyOn(steps[0].activeChange, 'emit'); + vi.spyOn(steps[1].activeChange, 'emit'); stepperService.expand(steps[1]); expect(stepperService.activeStep).toBe(steps[1]); expect(steps[1].activeChange.emit).toHaveBeenCalledTimes(1); expect(steps[1].activeChange.emit).toHaveBeenCalledWith(true); - spyOnProperty(stepper, 'orientation', 'get').and.returnValue(IgxStepperOrientation.Vertical); + vi.spyOn(stepper, 'orientation', 'get').mockReturnValue(IgxStepperOrientation.Vertical); stepperService.expand(steps[0]); expect(stepperService.activeStep).toBe(steps[0]); - expect(steps[0].activeChange.emit).toHaveBeenCalledOnceWith(true); + expect(steps[0].activeChange.emit).toHaveBeenCalledTimes(1); + expect(steps[0].activeChange.emit).toHaveBeenCalledWith(true); const testValues = [null, undefined, [], {}, 'sampleString']; @@ -1073,21 +1062,23 @@ describe('Stepper service unit tests', () => { }); it('should expand a step through API by activating it and firing the step\'s activeChange event', () => { - spyOnProperty(stepper, 'orientation', 'get').and.returnValue(IgxStepperOrientation.Horizontal); - spyOnProperty(stepper, 'steps', 'get').and.returnValue(steps); + vi.spyOn(stepper, 'orientation', 'get').mockReturnValue(IgxStepperOrientation.Horizontal); + vi.spyOn(stepper, 'steps', 'get').mockReturnValue(steps); stepperService.activeStep = steps[0]; - spyOn(steps[0].activeChange, 'emit'); - spyOn(steps[1].activeChange, 'emit'); + vi.spyOn(steps[0].activeChange, 'emit'); + vi.spyOn(steps[1].activeChange, 'emit'); stepperService.expandThroughApi(steps[1]); expect(stepperService.activeStep).toBe(steps[1]); - expect(steps[0].activeChange.emit).toHaveBeenCalledOnceWith(false); - expect(steps[1].activeChange.emit).toHaveBeenCalledOnceWith(true); + expect(steps[0].activeChange.emit).toHaveBeenCalledTimes(1); + expect(steps[0].activeChange.emit).toHaveBeenCalledWith(false); + expect(steps[1].activeChange.emit).toHaveBeenCalledTimes(1); + expect(steps[1].activeChange.emit).toHaveBeenCalledWith(true); - spyOnProperty(stepper, 'orientation', 'get').and.returnValue(IgxStepperOrientation.Vertical); + vi.spyOn(stepper, 'orientation', 'get').mockReturnValue(IgxStepperOrientation.Vertical); stepperService.expandThroughApi(steps[0]); expect(stepperService.activeStep).toBe(steps[0]); @@ -1106,8 +1097,8 @@ describe('Stepper service unit tests', () => { }); it('should collapse the currently active step and fire the change event', () => { - spyOnProperty(stepper, 'orientation', 'get').and.returnValue(IgxStepperOrientation.Horizontal); - spyOnProperty(stepper, 'steps', 'get').and.returnValue(steps); + vi.spyOn(stepper, 'orientation', 'get').mockReturnValue(IgxStepperOrientation.Horizontal); + vi.spyOn(stepper, 'steps', 'get').mockReturnValue(steps); stepperService.previousActiveStep = steps[0]; stepperService.activeStep = steps[1]; @@ -1116,18 +1107,19 @@ describe('Stepper service unit tests', () => { expect(stepperService.collapsingSteps).toContain(steps[0]); expect(stepperService.collapsingSteps).not.toContain(steps[1]); - spyOn(steps[0].activeChange, 'emit'); - spyOn(steps[1].activeChange, 'emit'); + vi.spyOn(steps[0].activeChange, 'emit'); + vi.spyOn(steps[1].activeChange, 'emit'); stepperService.collapse(steps[0]); expect(stepperService.collapsingSteps).not.toContain(steps[0]); expect(stepperService.activeStep).not.toBe(steps[0]); expect(stepperService.activeStep).toBe(steps[1]); - expect(steps[0].activeChange.emit).toHaveBeenCalledOnceWith(false); + expect(steps[0].activeChange.emit).toHaveBeenCalledTimes(1); + expect(steps[0].activeChange.emit).toHaveBeenCalledWith(false); expect(steps[1].activeChange.emit).not.toHaveBeenCalled(); - spyOnProperty(stepper, 'orientation', 'get').and.returnValue(IgxStepperOrientation.Vertical); + vi.spyOn(stepper, 'orientation', 'get').mockReturnValue(IgxStepperOrientation.Vertical); stepperService.previousActiveStep = steps[1]; stepperService.activeStep = steps[0]; @@ -1142,7 +1134,9 @@ describe('Stepper service unit tests', () => { expect(stepperService.activeStep).not.toBe(steps[1]); expect(stepperService.activeStep).toBe(steps[0]); - expect(steps[1].activeChange.emit).toHaveBeenCalledOnceWith(false); + expect(steps[1].activeChange.emit).toHaveBeenCalledTimes(1); + + expect(steps[1].activeChange.emit).toHaveBeenCalledWith(false); expect(steps[0].activeChange.emit).not.toHaveBeenCalledTimes(2); const testValues = [null, undefined, [], {}, 'sampleString']; @@ -1155,7 +1149,7 @@ describe('Stepper service unit tests', () => { }); it('should determine the steps that are marked as visited based on the active step', () => { - spyOnProperty(stepper, 'steps', 'get').and.returnValue(steps); + vi.spyOn(stepper, 'steps', 'get').mockReturnValue(steps); let sampleSet: Set; stepperService.activeStep = steps[0]; @@ -1178,15 +1172,15 @@ describe('Stepper service unit tests', () => { }); it('should determine the steps that should be disabled in linear mode based on the validity of the active step', () => { - spyOnProperty(stepper, 'orientation', 'get').and.returnValue(IgxStepperOrientation.Horizontal); - spyOnProperty(stepper, 'steps').and.returnValue(steps); + vi.spyOn(stepper, 'orientation', 'get').mockReturnValue(IgxStepperOrientation.Horizontal); + vi.spyOn(stepper, 'steps').mockReturnValue(steps); for (const step of steps) { - spyOnProperty(step, 'isValid').and.returnValue(false); + vi.spyOn(step, 'isValid').mockReturnValue(false); } - spyOnProperty(stepper, 'linear').and.returnValue(true); + vi.spyOn(stepper, 'linear').mockReturnValue(true); stepperService.activeStep = steps[0]; - spyOnProperty(steps[0], 'active').and.returnValue(true); + vi.spyOn(steps[0], 'active').mockReturnValue(true); expect(stepperService.linearDisabledSteps.size).toBe(0); stepperService.calculateLinearDisabledSteps(); @@ -1194,19 +1188,19 @@ describe('Stepper service unit tests', () => { let sampleSet = new Set([steps[1], steps[2], steps[3]]); expect(stepperService.linearDisabledSteps).toEqual(sampleSet); - spyOnProperty(steps[0], 'isValid').and.returnValue(true); + vi.spyOn(steps[0], 'isValid').mockReturnValue(true); stepperService.calculateLinearDisabledSteps(); sampleSet = new Set([steps[2], steps[3]]); expect(stepperService.linearDisabledSteps.size).toBe(2); expect(stepperService.linearDisabledSteps).toEqual(sampleSet); - spyOnProperty(steps[1], 'active').and.returnValue(true); - spyOnProperty(steps[1], 'isValid').and.returnValue(false); + vi.spyOn(steps[1], 'active').mockReturnValue(true); + vi.spyOn(steps[1], 'isValid').mockReturnValue(false); stepperService.calculateLinearDisabledSteps(); expect(stepperService.linearDisabledSteps.size).toBe(2); expect(stepperService.linearDisabledSteps).toEqual(sampleSet); - spyOnProperty(steps[1], 'isValid').and.returnValue(true); + vi.spyOn(steps[1], 'isValid').mockReturnValue(true); stepperService.activeStep = steps[1]; sampleSet = new Set([steps[3]]); stepperService.calculateLinearDisabledSteps(); @@ -1214,8 +1208,8 @@ describe('Stepper service unit tests', () => { expect(stepperService.linearDisabledSteps).toEqual(sampleSet); expect(stepperService.linearDisabledSteps).toContain(steps[3]); - spyOnProperty(steps[2], 'isValid').and.returnValue(true); - spyOnProperty(steps[3], 'isValid').and.returnValue(true); + vi.spyOn(steps[2], 'isValid').mockReturnValue(true); + vi.spyOn(steps[3], 'isValid').mockReturnValue(true); stepperService.activeStep = steps[3]; stepperService.calculateLinearDisabledSteps(); expect(stepperService.linearDisabledSteps.size).toBe(0); @@ -1223,9 +1217,9 @@ describe('Stepper service unit tests', () => { }); it('should emit activating event', () => { - spyOnProperty(stepper, 'orientation', 'get').and.returnValue(IgxStepperOrientation.Horizontal); - spyOnProperty(stepper, 'steps').and.returnValue(steps); - const activeChangingSpy = spyOn(stepper.activeStepChanging, 'emit'); + vi.spyOn(stepper, 'orientation', 'get').mockReturnValue(IgxStepperOrientation.Horizontal); + vi.spyOn(stepper, 'steps').mockReturnValue(steps); + const activeChangingSpy = vi.spyOn(stepper.activeStepChanging, 'emit'); stepperService.activeStep = steps[0]; let activeChangingEventArgs: any = { @@ -1237,9 +1231,10 @@ describe('Stepper service unit tests', () => { let result: boolean = stepperService.emitActivatingEvent(steps[1]); expect(result).toEqual(false); - expect(activeChangingSpy).toHaveBeenCalledOnceWith(activeChangingEventArgs); + expect(activeChangingSpy).toHaveBeenCalledTimes(1); + expect(activeChangingSpy).toHaveBeenCalledWith(activeChangingEventArgs); - activeChangingSpy.calls.reset(); + activeChangingSpy.mockClear(); stepperService.activeStep = steps[1]; stepperService.previousActiveStep = steps[0]; @@ -1351,13 +1346,13 @@ describe('Stepper service unit tests', () => { ] }) export class IgxStepperSampleTestComponent { - @ViewChild(IgxStepperComponent) public stepper: IgxStepperComponent; + @ViewChild(IgxStepperComponent) + public stepper: IgxStepperComponent; public horizontalAnimationType: HorizontalAnimationType = 'slide'; public verticalAnimationType: VerticalAnimationType = 'grow'; public animationDuration = 300; public displayHiddenStep = false; - } @Component({ @@ -1376,5 +1371,6 @@ export class IgxStepperSampleTestComponent { imports: [IgxStepperComponent, IgxStepComponent] }) export class IgxStepperLinearComponent { - @ViewChild(IgxStepperComponent) public stepper: IgxStepperComponent; + @ViewChild(IgxStepperComponent) + public stepper: IgxStepperComponent; } diff --git a/projects/igniteui-angular/switch/src/switch/switch.component.spec.ts b/projects/igniteui-angular/switch/src/switch/switch.component.spec.ts index f7776837d07..5a882ec4c39 100644 --- a/projects/igniteui-angular/switch/src/switch/switch.component.spec.ts +++ b/projects/igniteui-angular/switch/src/switch/switch.component.spec.ts @@ -5,6 +5,7 @@ import { By } from '@angular/platform-browser'; import { IgxSwitchComponent } from './switch.component'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { describe, it, expect, beforeEach } from 'vitest'; describe('IgxSwitch', () => { @@ -308,7 +309,8 @@ describe('IgxSwitch', () => { imports: [IgxSwitchComponent] }) class InitSwitchComponent { - @ViewChild('switch', { static: true }) public switch: IgxSwitchComponent; + @ViewChild('switch', { static: true }) + public switch: IgxSwitchComponent; } @Component({ @@ -317,7 +319,8 @@ class InitSwitchComponent { imports: [FormsModule, IgxSwitchComponent] }) class SwitchSimpleComponent { - @ViewChild('switch', { static: true }) public switch: IgxSwitchComponent; + @ViewChild('switch', { static: true }) + public switch: IgxSwitchComponent; public changeEventCalled = false; public subscribed = false; public clickCounter = 0; @@ -334,7 +337,8 @@ class SwitchSimpleComponent { imports: [IgxSwitchComponent] }) class SwitchRequiredComponent { - @ViewChild('switch', { static: true }) public switch: IgxSwitchComponent; + @ViewChild('switch', { static: true }) + public switch: IgxSwitchComponent; } @Component({ @@ -343,7 +347,8 @@ class SwitchRequiredComponent { imports: [IgxSwitchComponent] }) class SwitchExternalLabelComponent { - @ViewChild('switch', { static: true }) public switch: IgxSwitchComponent; + @ViewChild('switch', { static: true }) + public switch: IgxSwitchComponent; public label = 'My Label'; } @@ -352,7 +357,8 @@ class SwitchExternalLabelComponent { imports: [IgxSwitchComponent] }) class SwitchInvisibleLabelComponent { - @ViewChild('switch', { static: true }) public switch: IgxSwitchComponent; + @ViewChild('switch', { static: true }) + public switch: IgxSwitchComponent; public label = 'Invisible Label'; } @@ -363,7 +369,8 @@ class SwitchInvisibleLabelComponent { class SwitchFormGroupComponent { private fb = inject(UntypedFormBuilder); - @ViewChild('switch', { static: true }) public switch: IgxSwitchComponent; + @ViewChild('switch', { static: true }) + public switch: IgxSwitchComponent; public myForm = this.fb.group({ switch: ['', Validators.required] }); } diff --git a/projects/igniteui-angular/tabs/src/tabs/tabs/tabs.component.spec.ts b/projects/igniteui-angular/tabs/src/tabs/tabs/tabs.component.spec.ts index fd25641aa9a..120eb936b03 100644 --- a/projects/igniteui-angular/tabs/src/tabs/tabs/tabs.component.spec.ts +++ b/projects/igniteui-angular/tabs/src/tabs/tabs/tabs.component.spec.ts @@ -8,17 +8,12 @@ import { By } from '@angular/platform-browser'; import { RouterTestingModule } from '@angular/router/testing'; import { Router } from '@angular/router'; import { Location } from '@angular/common'; -import { - AddingSelectedTabComponent, TabsContactsComponent, TabsDisabledTestComponent, TabsRoutingDisabledTestComponent, - TabsRoutingGuardTestComponent, TabsRoutingTestComponent, TabsRtlComponent, TabsTabsOnlyModeTest1Component, - TabsTest2Component, TabsTestBug4420Component, TabsTestComponent, TabsTestCustomStylesComponent, - TabsTestHtmlAttributesComponent, TabsTestSelectedTabComponent, TabsWithPrefixSuffixTestComponent, - TemplatedTabsTestComponent -} from '../../../../test-utils/tabs-components.spec'; +import { AddingSelectedTabComponent, TabsContactsComponent, TabsDisabledTestComponent, TabsRoutingDisabledTestComponent, TabsRoutingGuardTestComponent, TabsRoutingTestComponent, TabsRtlComponent, TabsTabsOnlyModeTest1Component, TabsTest2Component, TabsTestBug4420Component, TabsTestComponent, TabsTestCustomStylesComponent, TabsTestHtmlAttributesComponent, TabsTestSelectedTabComponent, TabsWithPrefixSuffixTestComponent, TemplatedTabsTestComponent } from '../../../../test-utils/tabs-components.spec'; import { UIInteractions, wait } from '../../../../test-utils/ui-interactions.spec'; import { IgxTabContentComponent } from './tab-content.component'; import { RoutingTestGuard } from '../../../../test-utils/routing-test-guard.spec'; import { RoutingView1Component, RoutingView2Component, RoutingView3Component, RoutingView4Component, RoutingView5Component } from '../../../../test-utils/routing-view-components.spec'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; const KEY_RIGHT_EVENT = new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }); const KEY_LEFT_EVENT = new KeyboardEvent('keydown', { key: 'ArrowLeft', bubbles: true }); @@ -913,9 +908,9 @@ describe('IgxTabs', () => { tabs = fixture.componentInstance.tabs; tabItems = tabs.items.toArray(); headers = tabItems.map(item => item.headerComponent.nativeElement); - itemChangeSpy = spyOn(tabs.selectedItemChange, 'emit').and.callThrough(); - indexChangeSpy = spyOn(tabs.selectedIndexChange, 'emit').and.callThrough(); - indexChangingSpy = spyOn(tabs.selectedIndexChanging, 'emit').and.callThrough(); + itemChangeSpy = vi.spyOn(tabs.selectedItemChange, 'emit'); + indexChangeSpy = vi.spyOn(tabs.selectedIndexChange, 'emit'); + indexChangingSpy = vi.spyOn(tabs.selectedIndexChanging, 'emit'); })); it('Validate the fired events on clicking tab headers.', fakeAsync(() => { @@ -1054,9 +1049,9 @@ describe('IgxTabs', () => { fixture.detectChanges(); tabItems = tabs.items.toArray(); headers = tabItems.map(item => item.headerComponent.nativeElement); - itemChangeSpy = spyOn(tabs.selectedItemChange, 'emit'); - indexChangeSpy = spyOn(tabs.selectedIndexChange, 'emit'); - indexChangingSpy = spyOn(tabs.selectedIndexChanging, 'emit'); + itemChangeSpy = vi.spyOn(tabs.selectedItemChange, 'emit'); + indexChangeSpy = vi.spyOn(tabs.selectedIndexChange, 'emit'); + indexChangingSpy = vi.spyOn(tabs.selectedIndexChanging, 'emit'); })); it('Validate the events are not fired on clicking tab headers before pressing enter/space key.', fakeAsync(() => { @@ -1093,141 +1088,139 @@ describe('IgxTabs', () => { }); })); - it('Validate the events are not fired when navigating between tabs with arrow keys before pressing enter/space key.', - fakeAsync(() => { - tabs.activation = 'manual'; - tick(); - fixture.detectChanges(); - - tick(100); - headers[0].focus(); - - headers[0].dispatchEvent(KEY_LEFT_EVENT); - tick(200); - fixture.detectChanges(); - - expect(indexChangingSpy).not.toHaveBeenCalled(); - expect(indexChangeSpy).not.toHaveBeenCalled(); - expect(itemChangeSpy).not.toHaveBeenCalled(); - - headers[2].dispatchEvent(KEY_ENTER_EVENT); - tick(200); - fixture.detectChanges(); - - expect(indexChangingSpy).toHaveBeenCalledWith({ - owner: tabs, - cancel: false, - oldIndex: -1, - newIndex: 2 - }); - expect(indexChangeSpy).toHaveBeenCalledWith(2); - expect(itemChangeSpy).toHaveBeenCalledWith({ - owner: tabs, - oldItem: undefined, - newItem: tabItems[2] - }); - - expect(indexChangingSpy).toHaveBeenCalledTimes(1); - expect(indexChangeSpy).toHaveBeenCalledTimes(1); - expect(itemChangeSpy).toHaveBeenCalledTimes(1); - - headers[2].dispatchEvent(KEY_RIGHT_EVENT); - tick(200); - fixture.detectChanges(); - - expect(indexChangingSpy).toHaveBeenCalledTimes(1); - expect(indexChangeSpy).toHaveBeenCalledTimes(1); - expect(itemChangeSpy).toHaveBeenCalledTimes(1); - - headers[0].dispatchEvent(KEY_SPACE_EVENT); - tick(200); - fixture.detectChanges(); - - expect(indexChangingSpy).toHaveBeenCalledWith({ - owner: tabs, - cancel: false, - oldIndex: 2, - newIndex: 0 - }); - expect(indexChangeSpy).toHaveBeenCalledWith(0); - expect(itemChangeSpy).toHaveBeenCalledWith({ - owner: tabs, - oldItem: tabItems[2], - newItem: tabItems[0] - }); - - expect(indexChangingSpy).toHaveBeenCalledTimes(2); - expect(indexChangeSpy).toHaveBeenCalledTimes(2); - expect(itemChangeSpy).toHaveBeenCalledTimes(2); - })); - - it('Validate the events are not fired when navigating between tabs with home/end before pressing enter/space key.', - fakeAsync(() => { - tabs.activation = 'manual'; - tick(); - fixture.detectChanges(); - - tick(100); - headers[0].focus(); - - headers[0].dispatchEvent(KEY_END_EVENT); - tick(200); - fixture.detectChanges(); - - expect(indexChangingSpy).not.toHaveBeenCalled(); - expect(indexChangeSpy).not.toHaveBeenCalled(); - expect(itemChangeSpy).not.toHaveBeenCalled(); - - headers[2].dispatchEvent(KEY_ENTER_EVENT); - tick(200); - fixture.detectChanges(); - - expect(indexChangingSpy).toHaveBeenCalledWith({ - owner: tabs, - cancel: false, - oldIndex: -1, - newIndex: 2 - }); - expect(indexChangeSpy).toHaveBeenCalledWith(2); - expect(itemChangeSpy).toHaveBeenCalledWith({ - owner: tabs, - oldItem: undefined, - newItem: tabItems[2] - }); - - expect(indexChangingSpy).toHaveBeenCalledTimes(1); - expect(indexChangeSpy).toHaveBeenCalledTimes(1); - expect(itemChangeSpy).toHaveBeenCalledTimes(1); - - headers[2].dispatchEvent(KEY_HOME_EVENT); - tick(200); - fixture.detectChanges(); - - expect(indexChangingSpy).toHaveBeenCalledTimes(1); - expect(indexChangeSpy).toHaveBeenCalledTimes(1); - expect(itemChangeSpy).toHaveBeenCalledTimes(1); - - headers[0].dispatchEvent(KEY_SPACE_EVENT); - tick(200); - fixture.detectChanges(); - - expect(indexChangingSpy).toHaveBeenCalledWith({ - owner: tabs, - cancel: false, - oldIndex: 2, - newIndex: 0 - }); - expect(indexChangeSpy).toHaveBeenCalledWith(0); - expect(itemChangeSpy).toHaveBeenCalledWith({ - owner: tabs, - oldItem: tabItems[2], - newItem: tabItems[0] - }); - - expect(indexChangingSpy).toHaveBeenCalledTimes(2); - expect(indexChangeSpy).toHaveBeenCalledTimes(2); - expect(itemChangeSpy).toHaveBeenCalledTimes(2); - })); + it('Validate the events are not fired when navigating between tabs with arrow keys before pressing enter/space key.', fakeAsync(() => { + tabs.activation = 'manual'; + tick(); + fixture.detectChanges(); + + tick(100); + headers[0].focus(); + + headers[0].dispatchEvent(KEY_LEFT_EVENT); + tick(200); + fixture.detectChanges(); + + expect(indexChangingSpy).not.toHaveBeenCalled(); + expect(indexChangeSpy).not.toHaveBeenCalled(); + expect(itemChangeSpy).not.toHaveBeenCalled(); + + headers[2].dispatchEvent(KEY_ENTER_EVENT); + tick(200); + fixture.detectChanges(); + + expect(indexChangingSpy).toHaveBeenCalledWith({ + owner: tabs, + cancel: false, + oldIndex: -1, + newIndex: 2 + }); + expect(indexChangeSpy).toHaveBeenCalledWith(2); + expect(itemChangeSpy).toHaveBeenCalledWith({ + owner: tabs, + oldItem: undefined, + newItem: tabItems[2] + }); + + expect(indexChangingSpy).toHaveBeenCalledTimes(1); + expect(indexChangeSpy).toHaveBeenCalledTimes(1); + expect(itemChangeSpy).toHaveBeenCalledTimes(1); + + headers[2].dispatchEvent(KEY_RIGHT_EVENT); + tick(200); + fixture.detectChanges(); + + expect(indexChangingSpy).toHaveBeenCalledTimes(1); + expect(indexChangeSpy).toHaveBeenCalledTimes(1); + expect(itemChangeSpy).toHaveBeenCalledTimes(1); + + headers[0].dispatchEvent(KEY_SPACE_EVENT); + tick(200); + fixture.detectChanges(); + + expect(indexChangingSpy).toHaveBeenCalledWith({ + owner: tabs, + cancel: false, + oldIndex: 2, + newIndex: 0 + }); + expect(indexChangeSpy).toHaveBeenCalledWith(0); + expect(itemChangeSpy).toHaveBeenCalledWith({ + owner: tabs, + oldItem: tabItems[2], + newItem: tabItems[0] + }); + + expect(indexChangingSpy).toHaveBeenCalledTimes(2); + expect(indexChangeSpy).toHaveBeenCalledTimes(2); + expect(itemChangeSpy).toHaveBeenCalledTimes(2); + })); + + it('Validate the events are not fired when navigating between tabs with home/end before pressing enter/space key.', fakeAsync(() => { + tabs.activation = 'manual'; + tick(); + fixture.detectChanges(); + + tick(100); + headers[0].focus(); + + headers[0].dispatchEvent(KEY_END_EVENT); + tick(200); + fixture.detectChanges(); + + expect(indexChangingSpy).not.toHaveBeenCalled(); + expect(indexChangeSpy).not.toHaveBeenCalled(); + expect(itemChangeSpy).not.toHaveBeenCalled(); + + headers[2].dispatchEvent(KEY_ENTER_EVENT); + tick(200); + fixture.detectChanges(); + + expect(indexChangingSpy).toHaveBeenCalledWith({ + owner: tabs, + cancel: false, + oldIndex: -1, + newIndex: 2 + }); + expect(indexChangeSpy).toHaveBeenCalledWith(2); + expect(itemChangeSpy).toHaveBeenCalledWith({ + owner: tabs, + oldItem: undefined, + newItem: tabItems[2] + }); + + expect(indexChangingSpy).toHaveBeenCalledTimes(1); + expect(indexChangeSpy).toHaveBeenCalledTimes(1); + expect(itemChangeSpy).toHaveBeenCalledTimes(1); + + headers[2].dispatchEvent(KEY_HOME_EVENT); + tick(200); + fixture.detectChanges(); + + expect(indexChangingSpy).toHaveBeenCalledTimes(1); + expect(indexChangeSpy).toHaveBeenCalledTimes(1); + expect(itemChangeSpy).toHaveBeenCalledTimes(1); + + headers[0].dispatchEvent(KEY_SPACE_EVENT); + tick(200); + fixture.detectChanges(); + + expect(indexChangingSpy).toHaveBeenCalledWith({ + owner: tabs, + cancel: false, + oldIndex: 2, + newIndex: 0 + }); + expect(indexChangeSpy).toHaveBeenCalledWith(0); + expect(itemChangeSpy).toHaveBeenCalledWith({ + owner: tabs, + oldItem: tabItems[2], + newItem: tabItems[0] + }); + + expect(indexChangingSpy).toHaveBeenCalledTimes(2); + expect(indexChangeSpy).toHaveBeenCalledTimes(2); + expect(itemChangeSpy).toHaveBeenCalledTimes(2); + })); }); }); diff --git a/projects/igniteui-angular/test-utils/bottom-nav-components.spec.ts b/projects/igniteui-angular/test-utils/bottom-nav-components.spec.ts index 6cd132ce3cf..3b2797a9dd7 100644 --- a/projects/igniteui-angular/test-utils/bottom-nav-components.spec.ts +++ b/projects/igniteui-angular/test-utils/bottom-nav-components.spec.ts @@ -55,8 +55,10 @@ import { IgxTabHeaderIconDirective, IgxTabHeaderLabelDirective } from 'igniteui- imports: [IgxBottomNavComponent, IgxBottomNavItemComponent, IgxBottomNavHeaderComponent, IgxTabHeaderIconDirective, IgxTabHeaderLabelDirective, IgxBottomNavContentComponent] }) export class TabBarTestComponent { - @ViewChild(IgxBottomNavComponent, { static: true }) public bottomNav: IgxBottomNavComponent; - @ViewChild('wrapperDiv', { static: true }) public wrapperDiv: any; + @ViewChild(IgxBottomNavComponent, { static: true }) + public bottomNav: IgxBottomNavComponent; + @ViewChild('wrapperDiv', { static: true }) + public wrapperDiv: any; } @Component({ @@ -110,8 +112,10 @@ export class TabBarTestComponent { imports: [IgxBottomNavComponent, IgxBottomNavItemComponent, IgxBottomNavHeaderComponent, IgxTabHeaderIconDirective, IgxTabHeaderLabelDirective, IgxBottomNavContentComponent] }) export class BottomTabBarTestComponent { - @ViewChild(IgxBottomNavComponent, { static: true }) public bottomNav: IgxBottomNavComponent; - @ViewChild('wrapperDiv', { static: true }) public wrapperDiv: any; + @ViewChild(IgxBottomNavComponent, { static: true }) + public bottomNav: IgxBottomNavComponent; + @ViewChild('wrapperDiv', { static: true }) + public wrapperDiv: any; } @Component({ @@ -287,5 +291,6 @@ export class BottomNavRoutingGuardTestComponent { imports: [IgxBottomNavComponent, IgxBottomNavItemComponent, IgxBottomNavHeaderComponent, IgxTabHeaderLabelDirective, IgxBottomNavContentComponent] }) export class BottomNavTestHtmlAttributesComponent { - @ViewChild(IgxBottomNavComponent, { static: true }) public bottomNav: IgxBottomNavComponent; + @ViewChild(IgxBottomNavComponent, { static: true }) + public bottomNav: IgxBottomNavComponent; } diff --git a/projects/igniteui-angular/test-utils/calendar-helper-utils.ts b/projects/igniteui-angular/test-utils/calendar-helper-utils.ts index 324a4baef13..12da67f4789 100644 --- a/projects/igniteui-angular/test-utils/calendar-helper-utils.ts +++ b/projects/igniteui-angular/test-utils/calendar-helper-utils.ts @@ -1,5 +1,6 @@ import { ComponentFixture } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; +import { expect } from 'vitest'; export class HelperTestFunctions { public static DAYS_VIEW = 'igx-days-view'; diff --git a/projects/igniteui-angular/test-utils/configure-suite.ts b/projects/igniteui-angular/test-utils/configure-suite.ts index 8643c2c0286..e44b6447d51 100644 --- a/projects/igniteui-angular/test-utils/configure-suite.ts +++ b/projects/igniteui-angular/test-utils/configure-suite.ts @@ -71,8 +71,6 @@ export const configureTestSuite = (configureActionOrOptions?: (() => TestBed) | return fixture; }; } - - jasmine.getEnv().allowRespy(true); }); if (configureAction) { diff --git a/projects/igniteui-angular/test-utils/controls-functions.spec.ts b/projects/igniteui-angular/test-utils/controls-functions.spec.ts index b2d5595140f..c24fd967d3d 100644 --- a/projects/igniteui-angular/test-utils/controls-functions.spec.ts +++ b/projects/igniteui-angular/test-utils/controls-functions.spec.ts @@ -3,6 +3,7 @@ import { DebugElement } from '@angular/core'; import { ComponentFixture } from '@angular/core/testing'; import { UIInteractions } from './ui-interactions.spec'; import { IgxCheckboxComponent } from 'igniteui-angular/checkbox'; +import { expect } from 'vitest'; const CHIP_REMOVE_BUTTON = '.igx-chip__remove'; const DROP_DOWN_SELECTED_ITEM_CLASS = '.igx-drop-down__item--selected'; @@ -51,8 +52,7 @@ export class ControlsFunction { public static getCheckboxElement(name: string, element: DebugElement) { const checkboxElements = element.queryAll(By.css('igx-checkbox')); - const chkElement = checkboxElements.find((el) => - (el.context as IgxCheckboxComponent).placeholderLabel.nativeElement.innerText === name); + const chkElement = checkboxElements.find((el) => (el.context as IgxCheckboxComponent).placeholderLabel.nativeElement.innerText === name); return chkElement; } diff --git a/projects/igniteui-angular/test-utils/grid-base-components.spec.ts b/projects/igniteui-angular/test-utils/grid-base-components.spec.ts index 0e718e53aae..11e4a39e639 100644 --- a/projects/igniteui-angular/test-utils/grid-base-components.spec.ts +++ b/projects/igniteui-angular/test-utils/grid-base-components.spec.ts @@ -4,6 +4,7 @@ import { ColumnDefinitions, GridTemplateStrings } from './template-strings.spec' import { IgxPaginatorComponent } from 'igniteui-angular/paginator'; import { IgxGridComponent } from 'igniteui-angular/grids/grid'; import { IgxCellTemplateDirective, IgxColumnActionsComponent, IgxColumnComponent, IgxColumnGroupComponent, IgxColumnHidingDirective, IgxColumnPinningDirective, IgxGridToolbarActionsComponent, IgxGridToolbarComponent, IgxGridToolbarHidingComponent, IgxGridToolbarPinningComponent } from 'igniteui-angular/grids/core'; +import { GridPagingMode } from 'igniteui-angular/grids/core'; @Component({ template: ` @@ -71,8 +72,8 @@ export class GridNxMComponent extends GridWithSizeComponent implements OnInit { public ngOnInit() { this.columns = (this.hasEditableColumns) ? - SampleTestData.generateEditableColumns(this.colsCount, this.columnsType, this.columnNamePrefix) - : SampleTestData.generateColumnsByType(this.colsCount, this.columnsType, this.columnNamePrefix); + SampleTestData.generateEditableColumns(this.colsCount, this.columnsType, this.columnNamePrefix) + : SampleTestData.generateColumnsByType(this.colsCount, this.columnsType, this.columnNamePrefix); this.data = SampleTestData.generateDataForColumns(this.columns, this.rowsCount, this.startFromOne); } @@ -83,8 +84,7 @@ export class GridNxMComponent extends GridWithSizeComponent implements OnInit { } @Component({ - template: GridTemplateStrings.declareGrid('', '', ColumnDefinitions.idNameJobHireDate, '', - `@if (paging) { + template: GridTemplateStrings.declareGrid('', '', ColumnDefinitions.idNameJobHireDate, '', `@if (paging) { }`), imports: [IgxGridComponent, IgxColumnComponent, IgxPaginatorComponent] @@ -96,8 +96,7 @@ export class BasicGridSearchComponent extends GridWithSizeComponent { } @Component({ - template: GridTemplateStrings.declareGrid(``, - '', ColumnDefinitions.idNameJobTitle, '', `@if (paging) { + template: GridTemplateStrings.declareGrid(``, '', ColumnDefinitions.idNameJobTitle, '', `@if (paging) { }`), imports: [IgxGridComponent, IgxColumnComponent, IgxPaginatorComponent] @@ -113,7 +112,7 @@ export class PagingComponent extends GridWithSizeComponent { imports: [IgxGridComponent, IgxColumnComponent, IgxPaginatorComponent] }) export class RemotePagingComponent extends GridWithSizeComponent { - public pagingMode = 'remote'; + public pagingMode: GridPagingMode = GridPagingMode.Remote; public perPage = 3; public totalRecords = 10; public override data = SampleTestData.personJobDataFull(); @@ -128,15 +127,13 @@ export class SelectionComponent extends BasicGridComponent { } @Component({ - template: GridTemplateStrings.declareGrid(` [autoGenerate]="true" [exportExcel]="exportExcel" [exportCsv]="exportCsv"`, '', ''), + template: GridTemplateStrings.declareGrid(` [autoGenerate]="true"`, '', ''), imports: [IgxGridComponent] }) export class GridWithToolbarComponent extends GridWithSizeComponent { public showToolbar = true; public columnHiding = true; public columnPinning = true; - public exportExcel = true; - public exportCsv = true; public override data = SampleTestData.contactInfoData(); } @@ -165,8 +162,7 @@ export class GridRowConditionalStylingComponent extends GridWithSizeComponent { [grid]="grid" [hideFilter]="hideFilter"> } - ${GridTemplateStrings.declareGrid('#grid [height]="height" [width]="width"', '', ColumnDefinitions.productHidable, - '' + '' + + ${GridTemplateStrings.declareGrid('#grid [height]="height" [width]="width"', '', ColumnDefinitions.productHidable, '' + '' + '', '@if (paging) { }')}
`, imports: [ @@ -214,7 +210,8 @@ export class ColumnHidingTestComponent extends GridWithSizeComponent implements imports: [IgxGridComponent, IgxColumnComponent, IgxColumnActionsComponent, IgxColumnGroupComponent, IgxColumnHidingDirective] }) export class ColumnGroupsHidingTestComponent extends ColumnHidingTestComponent { - @ViewChild(IgxGridComponent, { static: true }) public override grid: IgxGridComponent; + @ViewChild(IgxGridComponent, { static: true }) + public override grid: IgxGridComponent; public hasGroupColumns = false; public override data = SampleTestData.contactInfoDataFull(); @@ -225,17 +222,17 @@ export class ColumnGroupsHidingTestComponent extends ColumnHidingTestComponent { @if (showInline) { } - ${GridTemplateStrings.declareGrid('#grid [height]="height" [width]="width"', '', ColumnDefinitions.productFilterable, - '' + - '' + - '')} + ${GridTemplateStrings.declareGrid('#grid [height]="height" [width]="width"', '', ColumnDefinitions.productFilterable, '' + + '' + + '')}
`, imports: [IgxGridComponent, IgxColumnComponent, IgxColumnActionsComponent, IgxColumnPinningDirective, IgxGridToolbarComponent, IgxGridToolbarPinningComponent, IgxGridToolbarActionsComponent] }) export class ColumnPinningTestComponent extends GridWithSizeComponent implements AfterViewInit, OnInit { private cdr = inject(ChangeDetectorRef); - @ViewChild(IgxColumnActionsComponent) public chooser: IgxColumnActionsComponent; + @ViewChild(IgxColumnActionsComponent) + public chooser: IgxColumnActionsComponent; public override height = '500px'; public override width = '500px'; @@ -278,8 +275,7 @@ export class ColumnPinningWithTemplateTestComponent extends ColumnPinningTestCom @if (showInline) { } - ${ GridTemplateStrings.declareGrid(' #grid [height]="height" [moving]="true"', '', ColumnDefinitions.contactInfoGroupableColumns, - '')} + ${GridTemplateStrings.declareGrid(' #grid [height]="height" [moving]="true"', '', ColumnDefinitions.contactInfoGroupableColumns, '')}
`, imports: [IgxGridComponent, IgxColumnComponent, IgxColumnGroupComponent, IgxGridToolbarComponent, IgxColumnActionsComponent, IgxColumnPinningDirective] }) diff --git a/projects/igniteui-angular/test-utils/grid-functions.spec.ts b/projects/igniteui-angular/test-utils/grid-functions.spec.ts index a46159be685..03e3a43b58b 100644 --- a/projects/igniteui-angular/test-utils/grid-functions.spec.ts +++ b/projects/igniteui-angular/test-utils/grid-functions.spec.ts @@ -13,6 +13,7 @@ import { CellType, GridType, IgxColumnComponent, IgxColumnGroupComponent, IgxCol import { IgxPivotGridComponent } from 'igniteui-angular/grids/pivot-grid'; import { IgxGridComponent, IgxGridExpandableCellComponent, IgxGridRowComponent } from 'igniteui-angular/grids/grid'; import { IgxPivotRowComponent } from 'igniteui-angular/grids/pivot-grid/src/pivot-row.component'; +import { expect } from 'vitest'; const SUMMARY_LABEL_CLASS = '.igx-grid-summary__label'; const SUMMARY_ROW = 'igx-grid-summary-row'; @@ -235,13 +236,12 @@ export class GridFunctions { return element.getBoundingClientRect().top >= gridTop && element.getBoundingClientRect().bottom <= gridBottom; } - public static toggleMasterRowByClick = - async (fix, row: IgxGridRowComponent, debounceTime) => { - const icon = row.element.nativeElement.querySelector('igx-icon'); - UIInteractions.simulateClickAndSelectEvent(icon.parentElement); - await wait(debounceTime); - fix.detectChanges(); - }; + public static toggleMasterRowByClick = async (fix, row: IgxGridRowComponent, debounceTime) => { + const icon = row.element.nativeElement.querySelector('igx-icon'); + UIInteractions.simulateClickAndSelectEvent(icon.parentElement); + await wait(debounceTime); + fix.detectChanges(); + }; public static toggleMasterRow(fix: ComponentFixture, row: IgxRowDirective) { const rowDE = fix.debugElement.queryAll(By.directive(IgxRowDirective)).find(el => el.componentInstance === row); @@ -307,29 +307,29 @@ export class GridFunctions { } public static verifyColumnIsHidden(column, isHidden: boolean, visibleColumnsCount: number) { - expect(column.hidden).toBe(isHidden, 'Hidden is not ' + isHidden); + expect(column.hidden, 'Hidden is not ' + isHidden).toBe(isHidden); const visibleColumns = column.grid.visibleColumns; - expect(visibleColumns.length).toBe(visibleColumnsCount, 'Unexpected visible columns count!'); - expect(visibleColumns.findIndex((col) => col === column) > -1).toBe(!isHidden, 'Unexpected result for visibleColumns collection!'); + expect(visibleColumns.length, 'Unexpected visible columns count!').toBe(visibleColumnsCount); + expect(visibleColumns.findIndex((col) => col === column) > -1, 'Unexpected result for visibleColumns collection!').toBe(!isHidden); } public static verifyColumnsAreHidden(columns, isHidden: boolean, visibleColumnsCount: number) { const visibleColumns = columns[0].grid.visibleColumns; columns.forEach(column => { - expect(column.hidden).toBe(isHidden, 'Hidden is not ' + isHidden); - expect(visibleColumns.findIndex((col) => col === column) > -1) - .toBe(!isHidden, 'Unexpected result for visibleColumns collection!'); + expect(column.hidden, 'Hidden is not ' + isHidden).toBe(isHidden); + expect(visibleColumns.findIndex((col) => col === column) > -1, 'Unexpected result for visibleColumns collection!') + .toBe(!isHidden); }); - expect(visibleColumns.length).toBe(visibleColumnsCount, 'Unexpected visible columns count!'); + expect(visibleColumns.length, 'Unexpected visible columns count!').toBe(visibleColumnsCount); } public static verifyColumnIsPinned(column, isPinned: boolean, pinnedColumnsCount: number) { - expect(column.pinned).toBe(isPinned, 'Pinned is not ' + isPinned); + expect(column.pinned, 'Pinned is not ' + isPinned).toBe(isPinned); const pinnedColumns = column.grid.pinnedColumns; - expect(pinnedColumns.length).toBe(pinnedColumnsCount, 'Unexpected pinned columns count!'); - expect(pinnedColumns.findIndex((col) => col === column) > -1).toBe(isPinned, 'Unexpected result for pinnedColumns collection!'); + expect(pinnedColumns.length, 'Unexpected pinned columns count!').toBe(pinnedColumnsCount); + expect(pinnedColumns.findIndex((col) => col === column) > -1, 'Unexpected result for pinnedColumns collection!').toBe(isPinned); } public static verifyUnpinnedAreaWidth(grid: GridType, expectedWidth: number, includeScrollWidth = true) { @@ -359,20 +359,15 @@ export class GridFunctions { public static createDateFilterConditions(grid: IgxGridComponent, today) { const expectedResults = []; // day + 15 - const dateItem0 = GridFunctions.generateICalendarDate(grid.data[0].ReleaseDate, - today.getFullYear(), today.getMonth()); + const dateItem0 = GridFunctions.generateICalendarDate(grid.data[0].ReleaseDate, today.getFullYear(), today.getMonth()); // month - 1 - const dateItem1 = GridFunctions.generateICalendarDate(grid.data[1].ReleaseDate, - today.getFullYear(), today.getMonth()); + const dateItem1 = GridFunctions.generateICalendarDate(grid.data[1].ReleaseDate, today.getFullYear(), today.getMonth()); // day - 1 - const dateItem3 = GridFunctions.generateICalendarDate(grid.data[3].ReleaseDate, - today.getFullYear(), today.getMonth()); + const dateItem3 = GridFunctions.generateICalendarDate(grid.data[3].ReleaseDate, today.getFullYear(), today.getMonth()); // day + 1 - const dateItem5 = GridFunctions.generateICalendarDate(grid.data[5].ReleaseDate, - today.getFullYear(), today.getMonth()); + const dateItem5 = GridFunctions.generateICalendarDate(grid.data[5].ReleaseDate, today.getFullYear(), today.getMonth()); // month + 1 - const dateItem6 = GridFunctions.generateICalendarDate(grid.data[6].ReleaseDate, - today.getFullYear(), today.getMonth()); + const dateItem6 = GridFunctions.generateICalendarDate(grid.data[6].ReleaseDate, today.getFullYear(), today.getMonth()); let thisMonthCountItems = 1; let nextMonthCountItems = 1; @@ -934,8 +929,7 @@ export class GridFunctions { return expr.querySelectorAll('.igx-input-group__input').item(1) as HTMLInputElement; } - public static getExcelFilteringDDInput(fix: ComponentFixture, - expressionIndex = 0, isDate = false): HTMLInputElement { + public static getExcelFilteringDDInput(fix: ComponentFixture, expressionIndex = 0, isDate = false): HTMLInputElement { const allExpressions = isDate ? GridFunctions.getExcelCustomFilteringDateExpressions(fix) : GridFunctions.getExcelCustomFilteringDefaultExpressions(fix); return allExpressions[expressionIndex].querySelectorAll('.igx-input-group__input').item(0) as HTMLInputElement; @@ -1001,8 +995,7 @@ export class GridFunctions { */ public static clickFilterConditionChip(fix: ComponentFixture, index: number) { const filterUIRow = fix.debugElement.query(By.css(FILTER_UI_ROW)); - const conditionChips = GridFunctions.sortNativeElementsHorizontally( - filterUIRow.queryAll(By.directive(IgxChipComponent)).map((ch) => ch.nativeElement)); + const conditionChips = GridFunctions.sortNativeElementsHorizontally(filterUIRow.queryAll(By.directive(IgxChipComponent)).map((ch) => ch.nativeElement)); conditionChips[index].click(); } @@ -1012,8 +1005,7 @@ export class GridFunctions { public static clickChipOperator(fix: ComponentFixture, index: number) { const filterUIRow = fix.debugElement.query(By.css(FILTER_UI_ROW)); const allIcons = filterUIRow.queryAll(By.css('igx-icon')).map((icon) => icon.nativeElement); - const operatorIcons = GridFunctions.sortNativeElementsHorizontally( - allIcons.filter((icon) => icon.innerText === 'expand_more')); + const operatorIcons = GridFunctions.sortNativeElementsHorizontally(allIcons.filter((icon) => icon.innerText === 'expand_more')); const operatorIcon = operatorIcons[index]; operatorIcon.click(); } @@ -1023,8 +1015,7 @@ export class GridFunctions { */ public static clickChipOperatorValue(fix: ComponentFixture, operatorValue: string) { const gridNativeElement = fix.debugElement.query(By.css('igx-grid')).nativeElement; - const operators = GridFunctions.sortNativeElementsVertically( - Array.from(gridNativeElement.querySelectorAll('.igx-drop-down__item'))); + const operators = GridFunctions.sortNativeElementsVertically(Array.from(gridNativeElement.querySelectorAll('.igx-drop-down__item'))); const operator = operators.find((op) => op.innerText.toLowerCase() === operatorValue.toLowerCase()); operator.click(); fix.detectChanges(); @@ -1284,8 +1275,7 @@ export class GridFunctions { public static getAllFilterConditionChips(fix) { const filterUIRow = fix.debugElement.query(By.css(FILTER_UI_ROW)); - const conditionChips = GridFunctions.sortNativeElementsHorizontally( - filterUIRow.queryAll(By.directive(IgxChipComponent)).map((ch) => ch.nativeElement)); + const conditionChips = GridFunctions.sortNativeElementsHorizontally(filterUIRow.queryAll(By.directive(IgxChipComponent)).map((ch) => ch.nativeElement)); return conditionChips; } @@ -1327,8 +1317,7 @@ export class GridFunctions { public static getExcelCustomFilteringDateExpressions(fix: ComponentFixture) { const customFilterMenu = GridFunctions.getExcelStyleCustomFilteringDialog(fix); - return GridFunctions.sortNativeElementsVertically( - Array.from(customFilterMenu.querySelectorAll(ESF_DATE_EXPR))); + return GridFunctions.sortNativeElementsVertically(Array.from(customFilterMenu.querySelectorAll(ESF_DATE_EXPR))); } public static clickAdvancedFilteringButton(fix: ComponentFixture) { @@ -1535,8 +1524,7 @@ export class GridFunctions { expandInd.dispatchEvent(new Event('click', {})); } - public static simulateGridContentKeydown(fix: ComponentFixture, keyName: string, - altKey = false, shiftKey = false, ctrlKey = false) { + public static simulateGridContentKeydown(fix: ComponentFixture, keyName: string, altKey = false, shiftKey = false, ctrlKey = false) { const gridContent = GridFunctions.getGridContent(fix); UIInteractions.triggerEventHandlerKeyDown(keyName, gridContent, altKey, shiftKey, ctrlKey); } @@ -1838,18 +1826,17 @@ export class GridSummaryFunctions { } } export class GridSelectionFunctions { - public static selectCellsRange = - async (fix, startCell, endCell, ctrl = false, shift = false) => { - UIInteractions.simulatePointerOverElementEvent('pointerdown', startCell.nativeElement, shift, ctrl); - fix.detectChanges(); - await wait(); - fix.detectChanges(); - - UIInteractions.simulatePointerOverElementEvent('pointerenter', endCell.nativeElement, shift, ctrl); - UIInteractions.simulatePointerOverElementEvent('pointerup', endCell.nativeElement, shift, ctrl); - await wait(); - fix.detectChanges(); - }; + public static selectCellsRange = async (fix, startCell, endCell, ctrl = false, shift = false) => { + UIInteractions.simulatePointerOverElementEvent('pointerdown', startCell.nativeElement, shift, ctrl); + fix.detectChanges(); + await wait(); + fix.detectChanges(); + + UIInteractions.simulatePointerOverElementEvent('pointerenter', endCell.nativeElement, shift, ctrl); + UIInteractions.simulatePointerOverElementEvent('pointerup', endCell.nativeElement, shift, ctrl); + await wait(); + fix.detectChanges(); + }; public static selectCellsRangeNoWait(fix, startCell, endCell, ctrl = false, shift = false) { UIInteractions.simulatePointerOverElementEvent('pointerdown', startCell.nativeElement, shift, ctrl); @@ -1860,16 +1847,15 @@ export class GridSelectionFunctions { fix.detectChanges(); } - public static selectCellsRangeWithShiftKey = - async (fix, startCell, endCell) => { - UIInteractions.simulateClickAndSelectEvent(startCell); - await wait(); - fix.detectChanges(); + public static selectCellsRangeWithShiftKey = async (fix, startCell, endCell) => { + UIInteractions.simulateClickAndSelectEvent(startCell); + await wait(); + fix.detectChanges(); - UIInteractions.simulateClickAndSelectEvent(endCell, true); - await wait(); - fix.detectChanges(); - }; + UIInteractions.simulateClickAndSelectEvent(endCell, true); + await wait(); + fix.detectChanges(); + }; public static selectCellsRangeWithShiftKeyNoWait(fix, startCell, endCell) { UIInteractions.simulateClickAndSelectEvent(startCell); diff --git a/projects/igniteui-angular/test-utils/grid-mch-sample.spec.ts b/projects/igniteui-angular/test-utils/grid-mch-sample.spec.ts index b133118e0b7..82fe64bd6fc 100644 --- a/projects/igniteui-angular/test-utils/grid-mch-sample.spec.ts +++ b/projects/igniteui-angular/test-utils/grid-mch-sample.spec.ts @@ -39,7 +39,8 @@ export class OneGroupOneColGridComponent { imports: [IgxGridComponent, IgxColumnGroupComponent, IgxColumnComponent] }) export class OneGroupThreeColsGridComponent { - @ViewChild('grid', { static: true }) public grid: IgxGridComponent; + @ViewChild('grid', { static: true }) + public grid: IgxGridComponent; public gridWrapperWidthPx = '900'; public gridHeight = '500px'; public columnWidth: string; @@ -168,11 +169,11 @@ export class ColumnGroupFourLevelTestComponent implements OnInit { public ngOnInit() { this.genInfoColsAndGroups = [this.genInfoColGroup, this.companyNameCol, this.pDetailsColGroup, - this.contactNameCol, this.contactTitleCol]; + this.contactNameCol, this.contactTitleCol]; this.addressColsAndGroups = [this.addrInfoColGroup, this.locationColGroup, this.countryCol, - this.regionCol, this.locCityColGroup, this.cityCol, this.addressCol, this.contactInfoColGroup, - this.phoneCol, this.faxCol, this.postalCodeColGroup, this.postalCodeCol]; + this.regionCol, this.locCityColGroup, this.cityCol, this.addressCol, this.contactInfoColGroup, + this.phoneCol, this.faxCol, this.postalCodeColGroup, this.postalCodeCol]; this.colsAndGroupsNaturalOrder = [this.idCol].concat(this.genInfoColsAndGroups) .concat(this.addressColsAndGroups); @@ -427,7 +428,7 @@ export class StegosaurusGridComponent implements OnInit { public ngOnInit() { this.genInfoColList = [this.genInfoColGroup, this.companyNameCol, this.pDetailsColGroup, - this.contactNameCol, this.contactTitleCol]; + this.contactNameCol, this.contactTitleCol]; this.postalCodeColList = [this.postalCodeColGroup, this.postalCodeCol]; this.cityColList = [this.cityColGroup, this.cityCol]; this.countryColList = [this.countryColGroup, this.countryCol]; @@ -689,4 +690,5 @@ export class NestedColGroupsWithTemplatesGridComponent { `, imports: [IgxGridComponent, IgxColumnGroupComponent, IgxColumnComponent] }) -export class ColumnGroupHiddenInTemplateComponent extends ColumnGroupTestComponent { } +export class ColumnGroupHiddenInTemplateComponent extends ColumnGroupTestComponent { +} diff --git a/projects/igniteui-angular/test-utils/grid-samples.spec.ts b/projects/igniteui-angular/test-utils/grid-samples.spec.ts index 05685a5cd69..ebc4dc52593 100644 --- a/projects/igniteui-angular/test-utils/grid-samples.spec.ts +++ b/projects/igniteui-angular/test-utils/grid-samples.spec.ts @@ -1,14 +1,12 @@ import { Component, TemplateRef, ViewChild, Input, AfterViewInit, QueryList, ViewChildren, OnInit } from '@angular/core'; -import { - BasicGridComponent, BasicGridSearchComponent, GridAutoGenerateComponent, - GridWithSizeComponent, PagingComponent -} from './grid-base-components.spec'; +import { BasicGridComponent, BasicGridSearchComponent, GridAutoGenerateComponent, GridWithSizeComponent, PagingComponent } from './grid-base-components.spec'; import { IGridSelection } from './grid-interfaces.spec'; import { SampleTestData, DataParent } from './sample-test-data.spec'; import { ColumnDefinitions, GridTemplateStrings, EventSubscriptions, TemplateDefinitions, ExternalTemplateDefinitions } from './template-strings.spec'; import { ColumnPinningPosition, ColumnType, FilteringExpressionsTree, FilteringLogic, FilteringStrategy, FormattedValuesSortingStrategy, IDataCloneStrategy, IFilteringExpressionsTree, IgxFilteringOperand, IgxFilterItem, IgxNumberFilteringOperand, IgxSummaryResult, ISortingOptions, ISortingStrategy, OverlaySettings, SortingDirection } from 'igniteui-angular/core'; +import { GridColumnDataType } from 'igniteui-angular/core'; import { IgxActionStripComponent } from 'igniteui-angular/action-strip'; import { IgxPaginatorComponent } from 'igniteui-angular/paginator'; import { IgxIconComponent } from 'igniteui-angular/icon'; @@ -17,6 +15,7 @@ import { IgxCheckboxComponent } from 'igniteui-angular/checkbox'; import { IgxButtonDirective, IgxFocusDirective } from 'igniteui-angular/directives'; import { IgxGridComponent } from 'igniteui-angular/grids/grid'; import { CellType, IGridCellEventArgs, IgxAdvancedFilteringDialogComponent, IgxCellEditorTemplateDirective, IgxCellHeaderTemplateDirective, IgxCellTemplateDirective, IgxCollapsibleIndicatorTemplateDirective, IgxColumnComponent, IgxColumnGroupComponent, IgxColumnLayoutComponent, IgxDateSummaryOperand, IgxExcelStyleColumnOperationsTemplateDirective, IgxExcelStyleConditionalFilterComponent, IgxExcelStyleFilterOperationsTemplateDirective, IgxExcelStyleHeaderIconDirective, IgxExcelStyleMovingComponent, IgxExcelStylePinningComponent, IgxExcelStyleSearchComponent, IgxExcelStyleSelectingComponent, IgxFilterCellTemplateDirective, IgxGridEditingActionsComponent, IgxGridExcelStyleFilteringComponent, IgxGridToolbarActionsComponent, IgxGridToolbarAdvancedFilteringComponent, IgxGridToolbarComponent, IgxGridToolbarHidingComponent, IgxGroupByRowSelectorDirective, IgxHeadSelectorDirective, IgxNumberSummaryOperand, IgxRowAddTextDirective, IgxRowEditActionsDirective, IgxRowEditTabStopDirective, IgxRowEditTemplateDirective, IgxRowEditTextDirective, IgxRowSelectorDirective, IgxSortAscendingHeaderIconDirective, IgxSortDescendingHeaderIconDirective, IgxSortHeaderIconDirective } from 'igniteui-angular/grids/core'; +import { GridSelectionMode } from 'igniteui-angular/grids/core'; @Component({ template: GridTemplateStrings.declareGrid('', '', ``), @@ -51,7 +50,8 @@ export class GridAddColumnComponent extends BasicGridComponent implements OnInit { field: 'CompanyName', width: 150, type: 'string' }, { field: 'ContactName', width: 150, type: 'string' }, { field: 'ContactTitle', width: 150, type: 'string' }, - { field: 'Address', width: 150, type: 'string' }]; + { field: 'Address', width: 150, type: 'string' } + ]; } } @@ -66,7 +66,10 @@ export class ColumnCellFormatterComponent extends BasicGridComponent { return `${value * value}`; } - public containsY(_: number, data: { ID: number; Name: string }) { + public containsY(_: number, data: { + ID: number; + Name: string; + }) { return data.Name.includes('y') ? 'true' : 'false'; } @@ -84,9 +87,7 @@ export class FilteringComponent extends BasicGridComponent { } @Component({ - template: GridTemplateStrings.declareGrid( - ` [width]="width" [height]="height" [rowSelection]="'multiple'" [primaryKey]="'ProductID'" [selectedRows]="selectedRows"`, - '', ColumnDefinitions.productBasicNumberID, '', '@if (paging) { }'), + template: GridTemplateStrings.declareGrid(` [width]="width" [height]="height" [rowSelection]="'multiple'" [primaryKey]="'ProductID'" [selectedRows]="selectedRows"`, '', ColumnDefinitions.productBasicNumberID, '', '@if (paging) { }'), imports: [IgxGridComponent, IgxColumnComponent, IgxPaginatorComponent] }) export class RowSelectionComponent extends BasicGridComponent { @@ -173,7 +174,8 @@ export class ProductsComponent extends BasicGridComponent { imports: [IgxGridComponent, IgxColumnComponent] }) export class GridDeclaredColumnsComponent extends BasicGridComponent { - @ViewChild('nameColumn', { static: true }) public nameColumn; + @ViewChild('nameColumn', { static: true }) + public nameColumn; public override data = SampleTestData.personIDNameRegionData(); } @@ -268,13 +270,10 @@ export class GridPinningMRLComponent extends PinOnInitAndSelectionComponent { } @Component({ - template: GridTemplateStrings.declareGrid(` [height]="height" [width]="width"`, - `${EventSubscriptions.selected}${EventSubscriptions.columnPin}`, - ColumnDefinitions.generatedWithWidth), + template: GridTemplateStrings.declareGrid(` [height]="height" [width]="width"`, `${EventSubscriptions.selected}${EventSubscriptions.columnPin}`, ColumnDefinitions.generatedWithWidth), imports: [IgxGridComponent, IgxColumnComponent] }) -export class PinningComponent extends GridWithSizeComponent - implements IGridSelection { +export class PinningComponent extends GridWithSizeComponent implements IGridSelection { public column: IgxColumnComponent; public columns = [ @@ -310,14 +309,10 @@ export class PinningComponent extends GridWithSizeComponent }) export class GridFeaturesComponent extends BasicGridComponent { public override data = SampleTestData.productInfoData(); - } @Component({ - template: GridTemplateStrings.declareGrid( - ` columnWidth="200" `, - '', ColumnDefinitions.idNameJobHireDate, '', - '@if (paging) { }'), + template: GridTemplateStrings.declareGrid(` columnWidth="200" `, '', ColumnDefinitions.idNameJobHireDate, '', '@if (paging) { }'), imports: [IgxGridComponent, IgxColumnComponent, IgxPaginatorComponent] }) export class ScrollableGridSearchComponent extends BasicGridSearchComponent { @@ -326,10 +321,7 @@ export class ScrollableGridSearchComponent extends BasicGridSearchComponent { } @Component({ - template: GridTemplateStrings.declareGrid( - ` columnWidth="200" [height]="null" `, - '', ColumnDefinitions.idNameJobTitleCompany, '', - '@if (paging) { }'), + template: GridTemplateStrings.declareGrid(` columnWidth="200" [height]="null" `, '', ColumnDefinitions.idNameJobTitleCompany, '', '@if (paging) { }'), imports: [IgxGridComponent, IgxColumnComponent, IgxPaginatorComponent] }) export class GroupableGridSearchComponent extends ScrollableGridSearchComponent { @@ -344,7 +336,6 @@ export class GroupableGridSearchComponent extends ScrollableGridSearchComponent export class GridAllFeaturesComponent extends GridWithSizeComponent { @Input() public columnWidth = 200; - } @Component({ @@ -400,7 +391,7 @@ export class GridHireDateComponent extends BasicGridComponent { export class MovableColumnsComponent extends BasicGridComponent { public override data = SampleTestData.personIDNameRegionData(); public autoGenerate = false; - public rowSelection = 'none'; + public rowSelection: GridSelectionMode = GridSelectionMode.none; public isFilterable = false; public isSortable = false; public isResizable = false; @@ -450,12 +441,13 @@ export class MovableTemplatedColumnsComponent extends BasicGridComponent { public isFilterable = false; public isSortable = false; public isResizable = false; + public isEditable = false; + public isHidden = false; + public isGroupable = false; } @Component({ - template: GridTemplateStrings.declareGrid(`height="300px" width="500px" [moving]="true" [autoGenerate]="autoGenerate"`, - EventSubscriptions.columnInit, '', '', - '@if (paging) { }'), + template: GridTemplateStrings.declareGrid(`height="300px" width="500px" [moving]="true" [autoGenerate]="autoGenerate"`, EventSubscriptions.columnInit, '', '', '@if (paging) { }'), imports: [IgxGridComponent, IgxPaginatorComponent] }) export class MovableColumnsLargeComponent extends GridAutoGenerateComponent { @@ -464,6 +456,7 @@ export class MovableColumnsLargeComponent extends GridAutoGenerateComponent { public width = '500px'; public height = '400px'; + public paging = false; public columnInit(column: IgxColumnComponent) { column.sortable = true; @@ -506,9 +499,7 @@ export class GridWithAvatarComponent extends GridWithSizeComponent { @Component({ - template: GridTemplateStrings.declareGrid(`height="1000px" width="900px" primaryKey="ID"`, '', - ColumnDefinitions.summariesGroupByColumns, '', - '@if (paging) { }'), + template: GridTemplateStrings.declareGrid(`height="1000px" width="900px" primaryKey="ID"`, '', ColumnDefinitions.summariesGroupByColumns, '', '@if (paging) { }'), imports: [IgxGridComponent, IgxColumnComponent, IgxPaginatorComponent] }) export class SummariesGroupByComponent extends BasicGridComponent { @@ -568,8 +559,7 @@ class AgeSummaryTest extends IgxNumberSummaryOperand { } @Component({ - template: GridTemplateStrings.declareGrid(`[height]="gridHeight" [columnWidth]="defaultWidth" [width]="gridWidth"`, - `${EventSubscriptions.selected}`, ColumnDefinitions.generatedWithWidth), + template: GridTemplateStrings.declareGrid(`[height]="gridHeight" [columnWidth]="defaultWidth" [width]="gridWidth"`, `${EventSubscriptions.selected}`, ColumnDefinitions.generatedWithWidth), imports: [IgxGridComponent, IgxColumnComponent] }) export class VirtualGridComponent extends BasicGridComponent { @@ -629,9 +619,7 @@ export class GridWithPrimaryKeyComponent extends BasicGridSearchComponent { } @Component({ - template: GridTemplateStrings.declareGrid(`height="300px" width="600px" primaryKey="ID"`, '', - ColumnDefinitions.selectionWithScrollsColumns, '', - '@if (paging) { }'), + template: GridTemplateStrings.declareGrid(`height="300px" width="600px" primaryKey="ID"`, '', ColumnDefinitions.selectionWithScrollsColumns, '', '@if (paging) { }'), imports: [IgxGridComponent, IgxColumnComponent, IgxPaginatorComponent] }) export class SelectionWithScrollsComponent extends BasicGridComponent { @@ -666,11 +654,11 @@ export class CustomFilter extends IgxFilteringOperand { private constructor() { super(); this.operations = [{ - name: 'custom', - isUnary: false, - logic: (target: string): boolean => target === 'custom', - iconName: 'custom' - }]; + name: 'custom', + isUnary: false, + logic: (target: string): boolean => target === 'custom', + iconName: 'custom' + }]; } } @Component({ @@ -839,8 +827,7 @@ export class CustomFilteringStrategyComponent extends BasicGridComponent { export class LoadOnDemandFilterStrategy extends FilteringStrategy { public override getFilterItems(column: ColumnType, tree: IFilteringExpressionsTree): Promise { - return new Promise(resolve => setTimeout(() => - resolve(super.getFilterItems(column, tree)), 1000)); + return new Promise(resolve => setTimeout(() => resolve(super.getFilterItems(column, tree)), 1000)); } } @@ -862,9 +849,7 @@ export class IgxGridFilteringESFLoadOnDemandComponent extends BasicGridComponent private _filteringStrategy = new FilteringStrategy(); - public columnValuesStrategy = (column: IgxColumnComponent, - columnExprTree: IFilteringExpressionsTree, - done: (uniqueValues: any[]) => void) => { + public columnValuesStrategy = (column: IgxColumnComponent, columnExprTree: IFilteringExpressionsTree, done: (uniqueValues: any[]) => void) => { setTimeout(() => { const filteredData = this._filteringStrategy.filter(this.data, columnExprTree, null, null); const columnValues = filteredData.map(record => record[column.field]); @@ -958,7 +943,7 @@ export class IgxGridFilteringESFTemplatesComponent extends BasicGridComponent { public resizable = false; public filterable = true; public override data = SampleTestData.excelFilteringData(); - @ViewChild('template', {read: TemplateRef }) + @ViewChild('template', { read: TemplateRef }) public customExcelHeaderIcon: TemplateRef; } @@ -1068,7 +1053,8 @@ export class IgxGridFilteringTemplateComponent extends BasicGridComponent { `, imports: [IgxGridComponent, IgxColumnComponent] }) -export class IgxGridFilteringScrollComponent extends IgxGridFilteringComponent { } +export class IgxGridFilteringScrollComponent extends IgxGridFilteringComponent { +} @Component({ template: ` @@ -1089,7 +1075,8 @@ export class IgxGridFilteringScrollComponent extends IgxGridFilteringComponent { `, imports: [IgxGridComponent, IgxColumnComponent, IgxColumnGroupComponent] }) -export class IgxGridFilteringMCHComponent extends IgxGridFilteringComponent { } +export class IgxGridFilteringMCHComponent extends IgxGridFilteringComponent { +} @Component({ template: ` @@ -1155,18 +1142,18 @@ export class IgxGridAdvancedFilteringWithToolbarComponent extends BasicGridCompo `, imports: [IgxGridComponent, IgxColumnComponent, IgxGridToolbarComponent] }) -export class IgxGridAdvancedFilteringDynamicColumnsComponent extends BasicGridComponent implements OnInit { +export class IgxGridAdvancedFilteringDynamicColumnsComponent extends BasicGridComponent implements OnInit { public override data = []; - public columns = []; + public columns: Array<{ field: string; header: string; width: string; type: GridColumnDataType }> = []; public ngOnInit(): void { this.columns = [ - { field: 'ID', header: 'HeaderID', width: '100px', type: 'number' }, - { field: 'ProductName', header: 'Product Name', width: '200px', type: 'string'}, - { field: 'Downloads', header: 'Downloads', width: '100px', type: 'number' }, - { field: 'Released', header: 'Released', width: '100px', type: 'boolean' }, - { field: 'ReleaseDate', header: 'Release Date', width: '200px', type: 'date' }, - { field: 'AnotherField', header: 'Another Field', width: '200px', type: 'string' }, + { field: 'ID', header: 'HeaderID', width: '100px', type: GridColumnDataType.Number }, + { field: 'ProductName', header: 'Product Name', width: '200px', type: GridColumnDataType.String }, + { field: 'Downloads', header: 'Downloads', width: '100px', type: GridColumnDataType.Number }, + { field: 'Released', header: 'Released', width: '100px', type: GridColumnDataType.Boolean }, + { field: 'ReleaseDate', header: 'Release Date', width: '200px', type: GridColumnDataType.Date }, + { field: 'AnotherField', header: 'Another Field', width: '200px', type: GridColumnDataType.String }, ]; this.data = SampleTestData.excelFilteringData(); } @@ -1272,8 +1259,7 @@ export class IgxGridClipboardComponent extends BasicGridComponent { } @Component({ - template: GridTemplateStrings.declareGrid(`id="testGridSum" [height]="height" [width]="width"`, ``, - ColumnDefinitions.generatedWithDataType), + template: GridTemplateStrings.declareGrid(`id="testGridSum" [height]="height" [width]="width"`, ``, ColumnDefinitions.generatedWithDataType), imports: [IgxGridComponent, IgxColumnComponent] }) export class DynamicColumnsComponent extends GridWithSizeComponent { @@ -1327,13 +1313,13 @@ export class GridCustomSelectorsComponent extends BasicGridComponent implements public override grid: IgxGridComponent; public rowCheckboxClick: any; public headerCheckboxClick: any; - @ViewChild('customRow', {read: TemplateRef, static: true }) + @ViewChild('customRow', { read: TemplateRef, static: true }) public customRowTemplate: TemplateRef; - @ViewChild('customHeader', {read: TemplateRef, static: true }) + @ViewChild('customHeader', { read: TemplateRef, static: true }) public customHeaderTemplate: TemplateRef; - @ViewChild('customGroupRow', {read: TemplateRef, static: true }) + @ViewChild('customGroupRow', { read: TemplateRef, static: true }) public customGroupRowTemplate: TemplateRef; public ngOnInit(): void { @@ -1483,7 +1469,8 @@ export class IgxGridWithEditingAndFeaturesComponent extends BasicGridComponent { imports: [IgxGridComponent, IgxColumnComponent, IgxRowEditTabStopDirective, IgxRowEditTemplateDirective, IgxButtonDirective] }) export class IgxGridCustomOverlayComponent extends BasicGridComponent { - @ViewChildren(IgxRowEditTabStopDirective) public buttons: QueryList; + @ViewChildren(IgxRowEditTabStopDirective) + public buttons: QueryList; public override data = SampleTestData.foodProductData(); public get gridAPI() { @@ -1549,13 +1536,13 @@ export class IgxGridEmptyRowEditTemplateComponent extends BasicGridComponent { }) export class IgxGridCustomRowEditTemplateComponent extends BasicGridComponent { public override data = SampleTestData.foodProductData(); - @ViewChild('editActions', {read: TemplateRef }) + @ViewChild('editActions', { read: TemplateRef }) public editActions: TemplateRef; - @ViewChild('addText', {read: TemplateRef }) + @ViewChild('addText', { read: TemplateRef }) public addText: TemplateRef; - @ViewChild('editText', {read: TemplateRef }) + @ViewChild('editText', { read: TemplateRef }) public editText: TemplateRef; } @@ -1754,7 +1741,8 @@ export class IgxGridGroupByComponent extends DataParent implements OnInit { imports: [IgxGridComponent, IgxColumnComponent, IgxCellEditorTemplateDirective, IgxFocusDirective] }) export class CellEditingCustomEditorTestComponent extends BasicGridComponent { - @ViewChild('cellEdit', { read: TemplateRef }) public templateCell; + @ViewChild('cellEdit', { read: TemplateRef }) + public templateCell; public override data = [ { personNumber: 0, fullName: 'John Brown', age: 20, isActive: true, birthday: new Date('08/08/2001') }, { personNumber: 1, fullName: 'Ben Affleck', age: 30, isActive: false, birthday: new Date('08/08/1991') }, @@ -2136,25 +2124,25 @@ export class IgxGridAdvancedFilteringSerializedTreeComponent extends BasicGridCo "operator": 0 }`); - this.filterTreeObject = { + this.filterTreeObject = { "filteringOperands": [ - { - "fieldName": "ProductName", - "condition": { - "name": "contains", - "isUnary": false, - "iconName": "filter_contains" - }, - "conditionName": "contains", - "ignoreCase": true, - "searchVal": "Ig", - "searchTree": null - } + { + "fieldName": "ProductName", + "condition": { + "name": "contains", + "isUnary": false, + "iconName": "filter_contains" + }, + "conditionName": "contains", + "ignoreCase": true, + "searchVal": "Ig", + "searchTree": null + } ], "operator": 1, "returnFields": [ - "ID", - "ProductName" + "ID", + "ProductName" ] }; } @@ -2198,14 +2186,14 @@ export class NoColumnWidthGridComponent extends BasicGridComponent { imports: [IgxGridComponent, IgxColumnComponent, IgxIconComponent, IgxSortHeaderIconDirective, IgxSortAscendingHeaderIconDirective, IgxSortDescendingHeaderIconDirective] }) export class SortByParityComponent extends GridDeclaredColumnsComponent implements ISortingStrategy { - @ViewChild('sortIcon', {read: TemplateRef }) - public sortIconTemplate: TemplateRef; + @ViewChild('sortIcon', { read: TemplateRef }) + public sortIconTemplate: TemplateRef; - @ViewChild('sortAscIcon', {read: TemplateRef }) - public sortAscIconTemplate: TemplateRef; + @ViewChild('sortAscIcon', { read: TemplateRef }) + public sortAscIconTemplate: TemplateRef; - @ViewChild('sortDescIcon', {read: TemplateRef }) - public sortDescIconTemplate: TemplateRef; + @ViewChild('sortDescIcon', { read: TemplateRef }) + public sortDescIconTemplate: TemplateRef; public sort(data: any[], fieldName: string, dir: SortingDirection) { const key = fieldName; @@ -2247,8 +2235,8 @@ export class SortByAnotherColumnComponent extends GridDeclaredColumnsComponent i imports: [IgxGridComponent, IgxColumnComponent] }) export class SortOnInitComponent extends GridDeclaredColumnsComponent implements OnInit { - public sortingOptions: ISortingOptions = { mode: 'single' }; - public ngOnInit(): void { + public sortingOptions: ISortingOptions = { mode: 'single' }; + public ngOnInit(): void { this.grid.sortingExpressions = [{ fieldName: 'Name', dir: SortingDirection.Asc }]; } } @@ -2277,7 +2265,7 @@ export class IgxGridFormattedValuesSortingComponent extends BasicGridComponent { } const prefix = value.length > 10 ? 'a' : 'b'; return `${prefix}-${value}`; - } + }; public formatQuantity = (value: string) => { if (!value) { @@ -2285,7 +2273,7 @@ export class IgxGridFormattedValuesSortingComponent extends BasicGridComponent { } const prefix = value.length > 10 ? 'c' : 'd'; return `${prefix}-${value}`; - } + }; } @Component({ @@ -2459,7 +2447,8 @@ export class GridWithThreeLevelsOfMultiColumnHeadersAndTwoRowsExportComponent ex imports: [IgxGridComponent, IgxColumnComponent] }) export class GridWithEmptyColumnsComponent { - @ViewChild('grid1', { static: true }) public grid: IgxGridComponent; + @ViewChild('grid1', { static: true }) + public grid: IgxGridComponent; public data = SampleTestData.personJobDataFull(); } @@ -2471,7 +2460,8 @@ export class GridWithEmptyColumnsComponent { imports: [IgxGridComponent] }) export class EmptyGridComponent { - @ViewChild('grid1', { static: true }) public grid: IgxGridComponent; + @ViewChild('grid1', { static: true }) + public grid: IgxGridComponent; } /** Issue 9872 */ @@ -2486,14 +2476,13 @@ export class ColumnsAddedOnInitComponent extends BasicGridComponent implements O this.columns = [ { field: 'CompanyName' }, { field: 'ContactName' }, - { field: 'Address' }]; + { field: 'Address' } + ]; this.data = SampleTestData.contactInfoData(); for (let i = 0; i < 3; i++) { this.columns.push({ field: i.toString() }); //add columns for the horizon - this.data.forEach( - c => (c[i] = i * 2500) - ); //add random quantity to each customer for each period in the horizon + this.data.forEach(c => (c[i] = i * 2500)); //add random quantity to each customer for each period in the horizon } } } @@ -2545,15 +2534,15 @@ class CustomSummaryWithNullAndZero { const result = []; result.push({ - key: 'total', - label: null, - summaryResult: 0, + key: 'total', + label: null, + summaryResult: 0, }); result.push({ - key: 'totalDiscontinued', - label: 0, - summaryResult: null, + key: 'totalDiscontinued', + label: 0, + summaryResult: null, }); return result; } @@ -2564,15 +2553,15 @@ class CustomSummaryWithUndefinedZeroAndValidNumber { const result = []; result.push({ - key: 'total', - label: undefined, - summaryResult: 0, + key: 'total', + label: undefined, + summaryResult: 0, }); result.push({ - key: 'totalDiscontinued', - label: 23, - summaryResult: undefined, + key: 'totalDiscontinued', + label: 23, + summaryResult: undefined, }); return result; } @@ -2583,15 +2572,15 @@ class CustomSummaryWithUndefinedAndNull { const result = []; result.push({ - key: 'total', - label: undefined, - summaryResult: null, + key: 'total', + label: undefined, + summaryResult: null, }); result.push({ - key: 'totalDiscontinued', - label: null, - summaryResult: undefined, + key: 'totalDiscontinued', + label: null, + summaryResult: undefined, }); return result; } @@ -2609,9 +2598,7 @@ class DiscontinuedSummary { result.push({ key: 'totalDiscontinued', - label: IgxNumberSummaryOperand.sum( - allData.filter((rec) => rec['Discontinued']).map((r) => r[fieldName]) - ).toString(), + label: IgxNumberSummaryOperand.sum(allData.filter((rec) => rec['Discontinued']).map((r) => r[fieldName])).toString(), summaryResult: '', }); return result; @@ -2742,7 +2729,7 @@ export class ObjectCloneStrategy implements IDataCloneStrategy { if (data) { const clone = Object.defineProperties({}, Object.getOwnPropertyDescriptors(data)); for (const key in clone) { - clonedData[key] = clone[key] + clonedData[key] = clone[key]; } clonedData['cloned'] = true; diff --git a/projects/igniteui-angular/test-utils/grid-validation-samples.spec.ts b/projects/igniteui-angular/test-utils/grid-validation-samples.spec.ts index 34e76960d3c..9ec54b55b25 100644 --- a/projects/igniteui-angular/test-utils/grid-validation-samples.spec.ts +++ b/projects/igniteui-angular/test-utils/grid-validation-samples.spec.ts @@ -7,6 +7,7 @@ import { GridColumnDataType } from 'igniteui-angular/core'; import { IgxGridComponent } from 'igniteui-angular/grids/grid'; import { IGX_GRID_VALIDATION_DIRECTIVES, IgxCellEditorTemplateDirective, IgxCellValidationErrorDirective, IgxColumnComponent } from 'igniteui-angular/grids/core'; import { IgxTreeGridComponent } from 'igniteui-angular/grids/tree-grid'; +import { test } from 'vitest'; @Directive({ selector: '[igxAppForbiddenName]', @@ -55,7 +56,8 @@ export class IgxGridValidationTestBaseComponent { ]; public data = [...data]; - @ViewChild('grid', { read: IgxGridComponent, static: true }) public grid: IgxGridComponent; + @ViewChild('grid', { read: IgxGridComponent, static: true }) + public grid: IgxGridComponent; } @Component({ @@ -105,10 +107,10 @@ export class IgxGridValidationTestCustomErrorComponent extends IgxGridValidation imports: [IgxGridComponent, IgxColumnComponent, IgxCellEditorTemplateDirective, ForbiddenValidatorDirective, IGX_GRID_VALIDATION_DIRECTIVES, ReactiveFormsModule, FormsModule] }) export class IgxGridCustomEditorsComponent extends IgxGridValidationTestCustomErrorComponent { - @ViewChild('modelTemplate', {read: TemplateRef }) + @ViewChild('modelTemplate', { read: TemplateRef }) public modelTemplate: TemplateRef; - @ViewChild('formControlTemplate', {read: TemplateRef }) + @ViewChild('formControlTemplate', { read: TemplateRef }) public formControlTemplate: TemplateRef; } @@ -146,5 +148,6 @@ export class IgxTreeGridValidationTestComponent { ]; public data = [...SampleTestData.employeeSmallTreeData()]; - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; } diff --git a/projects/igniteui-angular/test-utils/helper-utils.spec.ts b/projects/igniteui-angular/test-utils/helper-utils.spec.ts index c7c81b44849..d0817399635 100644 --- a/projects/igniteui-angular/test-utils/helper-utils.spec.ts +++ b/projects/igniteui-angular/test-utils/helper-utils.spec.ts @@ -3,27 +3,24 @@ import { ComponentFixture } from '@angular/core/testing'; import { GridType } from 'igniteui-angular/grids/core'; import { IgxHierarchicalGridComponent } from 'igniteui-angular/grids/hierarchical-grid'; import { Subscription } from 'rxjs'; +import { expect, beforeEach, afterEach, vi } from 'vitest'; /** * Global beforeEach and afterEach checks to ensure test fails on specific warnings - * Use direct env because karma-parallel's wrap ignores these in secondary shards - * https://github.com/joeljeske/karma-parallel/issues/64 + * Note: Vitest doesn't support global hooks like Jasmine's getEnv(). + * These checks should be implemented in individual test suites as needed. */ -(jasmine.getEnv() as any).beforeEach(() => { - spyOn(console, 'warn').and.callThrough(); +beforeEach(() => { + vi.spyOn(console, 'warn'); }); -(jasmine.getEnv() as any).afterEach(() => { - expect(console.warn) - .withContext('Components & tests should be free of @for track duplicated keys warnings') - .not.toHaveBeenCalledWith(jasmine.stringContaining('NG0955')); - expect(console.warn) - .withContext('Components & tests should be free of @for track DOM re-creation warnings') - .not.toHaveBeenCalledWith(jasmine.stringContaining('NG0956')); +afterEach(() => { + expect(console.warn, 'Components & tests should be free of @for track duplicated keys warnings').not.toHaveBeenCalledWith(expect.stringContaining('NG0955')); + expect(console.warn, 'Components & tests should be free of @for track DOM re-creation warnings').not.toHaveBeenCalledWith(expect.stringContaining('NG0956')); }); -export let gridsubscriptions: Subscription [] = []; +export let gridsubscriptions: Subscription[] = []; export const setupGridScrollDetection = (fixture: ComponentFixture, grid: GridType) => { gridsubscriptions.push(grid.verticalScrollContainer.chunkLoad.subscribe(() => fixture.detectChanges())); @@ -49,7 +46,7 @@ export const setupHierarchicalGridScrollDetection = (fixture: ComponentFixture { gridsubscriptions.forEach(sub => sub.unsubscribe()); gridsubscriptions = []; -} +}; /** * Sets element size as a inline style @@ -86,7 +83,7 @@ export class TestNgZone extends NgZone { public override onStable: EventEmitter = new EventEmitter(false); constructor() { - super({enableLongStackTrace: false, shouldCoalesceEventChangeDetection: false}); + super({ enableLongStackTrace: false, shouldCoalesceEventChangeDetection: false }); } public override run(fn: () => void): any { @@ -105,25 +102,9 @@ export class TestNgZone extends NgZone { /* eslint-disable no-console */ // TODO: enable on re-run by selecting enable debug logging // https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/troubleshooting-workflows/enabling-debug-logging +// Note: Vitest uses a different reporter system. Custom reporters should be configured in vitest.config.ts const shardLogging = false; if (shardLogging) { - const myReporter = { - suiteStarted: function(result) { - const id = new URLSearchParams(window.parent.location.search).get('id'); - console.log(`[${id}] Suite started: ${result.fullName}`); - }, - suiteDone: function(result) { - const id = new URLSearchParams(window.parent.location.search).get('id'); - console.log(`[${id}] Suite: ${result.fullName} has ${result.status}`); - for (const expectation of result.failedExpectations) { - console.log('Suite ' + expectation.message); - console.log(expectation.stack); - } - var memory = (performance as any).memory; - console.log(`[${id}] totalJSHeapSize: ${memory['totalJSHeapSize']} usedJSHeapSize: ${memory['usedJSHeapSize']} jsHeapSizeLimit: ${memory['jsHeapSizeLimit']}`); - if (memory['totalJSHeapSize'] >= memory['jsHeapSizeLimit'] ) - console.log( '--------------------Heap Size limit reached!!!-------------------'); - }, - }; - jasmine.getEnv().addReporter(myReporter); + // Vitest reporter configuration should be done in vitest.config.ts, not at runtime + console.log('Shard logging is enabled. Configure custom reporters in vitest.config.ts'); } diff --git a/projects/igniteui-angular/test-utils/hierarchical-grid-components.spec.ts b/projects/igniteui-angular/test-utils/hierarchical-grid-components.spec.ts index 1e3bbef5bc5..6759c1f0a39 100644 --- a/projects/igniteui-angular/test-utils/hierarchical-grid-components.spec.ts +++ b/projects/igniteui-angular/test-utils/hierarchical-grid-components.spec.ts @@ -184,9 +184,12 @@ export class IgxHierarchicalGridWithTransactionProviderComponent { imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent] }) export class IgxHierarchicalGridRowSelectionComponent { - @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) public hgrid: IgxHierarchicalGridComponent; - @ViewChild('rowIsland', { read: IgxRowIslandComponent, static: true }) public rowIsland: IgxRowIslandComponent; - @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) public rowIsland2: IgxRowIslandComponent; + @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) + public hgrid: IgxHierarchicalGridComponent; + @ViewChild('rowIsland', { read: IgxRowIslandComponent, static: true }) + public rowIsland: IgxRowIslandComponent; + @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) + public rowIsland2: IgxRowIslandComponent; public data; public selectedRows = []; @@ -216,9 +219,12 @@ export class IgxHierarchicalGridRowSelectionComponent { imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent] }) export class IgxHierarchicalGridRowSelectionTestSelectRowOnClickComponent { - @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) public hgrid: IgxHierarchicalGridComponent; - @ViewChild('rowIsland', { read: IgxRowIslandComponent, static: true }) public rowIsland: IgxRowIslandComponent; - @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) public rowIsland2: IgxRowIslandComponent; + @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) + public hgrid: IgxHierarchicalGridComponent; + @ViewChild('rowIsland', { read: IgxRowIslandComponent, static: true }) + public rowIsland: IgxRowIslandComponent; + @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) + public rowIsland2: IgxRowIslandComponent; public data; public selectedRows = []; @@ -249,9 +255,12 @@ export class IgxHierarchicalGridRowSelectionTestSelectRowOnClickComponent { imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent] }) export class IgxHierarchicalGridRowSelectionNoTransactionsComponent { - @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) public hgrid: IgxHierarchicalGridComponent; - @ViewChild('rowIsland', { read: IgxRowIslandComponent, static: true }) public rowIsland: IgxRowIslandComponent; - @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) public rowIsland2: IgxRowIslandComponent; + @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) + public hgrid: IgxHierarchicalGridComponent; + @ViewChild('rowIsland', { read: IgxRowIslandComponent, static: true }) + public rowIsland: IgxRowIslandComponent; + @ViewChild('rowIsland2', { read: IgxRowIslandComponent, static: true }) + public rowIsland2: IgxRowIslandComponent; public data; constructor() { @@ -358,7 +367,8 @@ export class IgxHierarchicalGridCustomSelectorsComponent implements OnInit { `, imports: [IgxHierarchicalGridComponent, IgxGridToolbarComponent, IgxGridToolbarDirective, IgxRowIslandComponent, IgxButtonDirective] }) -export class IgxHierarchicalGridTestCustomToolbarComponent extends IgxHierarchicalGridTestBaseComponent { } +export class IgxHierarchicalGridTestCustomToolbarComponent extends IgxHierarchicalGridTestBaseComponent { +} @Component({ template: ` @@ -380,7 +390,8 @@ export class IgxHierarchicalGridTestCustomToolbarComponent extends IgxHierarchic `, imports: [IgxHierarchicalGridComponent, IgxGridToolbarComponent, IgxRowIslandComponent, IgxButtonDirective] }) -export class IgxHierarchicalGridTestInputToolbarComponent extends IgxHierarchicalGridTestBaseComponent { } +export class IgxHierarchicalGridTestInputToolbarComponent extends IgxHierarchicalGridTestBaseComponent { +} @Component({ template: ` @@ -403,7 +414,8 @@ export class IgxHierarchicalGridTestInputToolbarComponent extends IgxHierarchica `, imports: [IgxHierarchicalGridComponent, IgxGridToolbarComponent, IgxPaginatorComponent, IgxPaginatorContentDirective, IgxRowIslandComponent, IgxButtonDirective] }) -export class IgxHierarchicalGridTestInputPaginatorComponent extends IgxHierarchicalGridTestBaseComponent { } +export class IgxHierarchicalGridTestInputPaginatorComponent extends IgxHierarchicalGridTestBaseComponent { +} @Component({ template: ` @@ -513,7 +525,8 @@ export class IgxHierGridExternalAdvancedFilteringComponent extends IgxHierarchic imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent] }) export class IgxHierarchicalGridExportComponent { - @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) public hGrid: IgxHierarchicalGridComponent; + @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) + public hGrid: IgxHierarchicalGridComponent; public data = SampleTestData.hierarchicalGridExportData(); public shouldDisplayArtist = false; } @@ -569,7 +582,8 @@ export class IgxHierarchicalGridExportComponent { imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxColumnGroupComponent, IgxRowIslandComponent] }) export class IgxHierarchicalGridMultiColumnHeadersExportComponent { - @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) public hGrid: IgxHierarchicalGridComponent; + @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) + public hGrid: IgxHierarchicalGridComponent; public data = HIERARCHICAL_SAMPLE_DATA; } @@ -595,7 +609,8 @@ export class IgxHierarchicalGridMultiColumnHeadersExportComponent { imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxColumnGroupComponent, IgxRowIslandComponent] }) export class IgxHierarchicalGridMCHCollapsibleComponent { - @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) public hGrid: IgxHierarchicalGridComponent; + @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) + public hGrid: IgxHierarchicalGridComponent; public data = HIERARCHICAL_SAMPLE_DATA; } @@ -630,7 +645,8 @@ export class IgxHierarchicalGridMCHCollapsibleComponent { imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxColumnGroupComponent, IgxRowIslandComponent] }) export class IgxHierarchicalGridMultiColumnHeaderIslandsExportComponent { - @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) public hGrid: IgxHierarchicalGridComponent; + @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) + public hGrid: IgxHierarchicalGridComponent; public data = HIERARCHICAL_SAMPLE_DATA_SHORT; } @@ -661,7 +677,8 @@ export class IgxHierarchicalGridMultiColumnHeaderIslandsExportComponent { imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent] }) export class IgxHierarchicalGridSummariesExportComponent { - @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) public hGrid: IgxHierarchicalGridComponent; + @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) + public hGrid: IgxHierarchicalGridComponent; public data = SampleTestData.hierarchicalGridExportData(); public mySummary = MySummary; @@ -669,25 +686,22 @@ export class IgxHierarchicalGridSummariesExportComponent { } -class MySummary { +class MySummary { public operate(data?: any[]): IgxSummaryResult[] { const result = []; - result.push( - { + result.push({ key: 'min', label: 'Min', summaryResult: IgxNumberSummaryOperand.min(data) - }, - { + }, { key: 'max', label: 'Max', summaryResult: IgxNumberSummaryOperand.max(data) - }, - { - key: 'avg', - label: 'Avg', - summaryResult: IgxNumberSummaryOperand.average(data) + }, { + key: 'avg', + label: 'Avg', + summaryResult: IgxNumberSummaryOperand.average(data) }); return result; } @@ -696,8 +710,7 @@ class MyChildSummary { public operate(data?: any[]): IgxSummaryResult[] { const result = []; - result.push( - { + result.push({ key: 'count', label: 'Count', summaryResult: IgxNumberSummaryOperand.count(data) @@ -764,7 +777,8 @@ export class IgxHierarchicalGridDefaultComponent { imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent] }) export class IgxHierarchicalGridEmptyDataExportComponent { - @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) public hGrid: IgxHierarchicalGridComponent; + @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) + public hGrid: IgxHierarchicalGridComponent; public data = []; } @@ -783,7 +797,8 @@ export class IgxHierarchicalGridEmptyDataExportComponent { imports: [IgxHierarchicalGridComponent, IgxColumnComponent, IgxRowIslandComponent] }) export class IgxHierarchicalGridMissingChildDataExportComponent { - @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) public hGrid: IgxHierarchicalGridComponent; + @ViewChild('hierarchicalGrid', { read: IgxHierarchicalGridComponent, static: true }) + public hGrid: IgxHierarchicalGridComponent; // Data without the 'Albums' key that the row island expects public data = [ { Artist: 'Artist1', Debut: 2000, GrammyNominations: 5, GrammyAwards: 2 } diff --git a/projects/igniteui-angular/test-utils/list-components.spec.ts b/projects/igniteui-angular/test-utils/list-components.spec.ts index 05c7b2095b3..6308e7a068a 100644 --- a/projects/igniteui-angular/test-utils/list-components.spec.ts +++ b/projects/igniteui-angular/test-utils/list-components.spec.ts @@ -44,8 +44,10 @@ export class ListDirectivesComponent { imports: [IgxListComponent, IgxListItemComponent] }) export class BasicListComponent { - @ViewChild(IgxListComponent, { static: true }) public list: IgxListComponent; - @ViewChild('wrapper', { static: true }) public wrapper; + @ViewChild(IgxListComponent, { static: true }) + public list: IgxListComponent; + @ViewChild('wrapper', { static: true }) + public wrapper; } @Component({ @@ -221,24 +223,24 @@ export class ListWithPanningTemplatesComponent extends ListWithPanningComponent imports: [IgxListComponent, IgxListItemComponent, IgxForOfDirective] }) export class ListWithIgxForAndScrollingComponent { - @ViewChild('forOfList', {read: IgxListComponent, static: true }) + @ViewChild('forOfList', { read: IgxListComponent, static: true }) public forOfList: IgxListComponent; @ViewChild(IgxForOfDirective) public igxFor: IgxForOfDirective; public data = [ - {key: 1, name: 'John'}, - {key: 2, name: 'Brian'}, - {key: 3, name: 'Christian'}, - {key: 4, name: 'Mark'}, - {key: 5, name: 'William'}, - {key: 6, name: 'Dave'}, - {key: 7, name: 'Riley'}, - {key: 8, name: 'Terrance'}, - {key: 9, name: 'Erick'}, - {key: 10, name: 'Victor'}, - {key: 11, name: 'Rick'}, - {key: 12, name: 'Stefan'} + { key: 1, name: 'John' }, + { key: 2, name: 'Brian' }, + { key: 3, name: 'Christian' }, + { key: 4, name: 'Mark' }, + { key: 5, name: 'William' }, + { key: 6, name: 'Dave' }, + { key: 7, name: 'Riley' }, + { key: 8, name: 'Terrance' }, + { key: 9, name: 'Erick' }, + { key: 10, name: 'Victor' }, + { key: 11, name: 'Rick' }, + { key: 12, name: 'Stefan' } ]; } diff --git a/projects/igniteui-angular/test-utils/pivot-grid-functions.spec.ts b/projects/igniteui-angular/test-utils/pivot-grid-functions.spec.ts index 3f9f455d4c1..0abfe813205 100644 --- a/projects/igniteui-angular/test-utils/pivot-grid-functions.spec.ts +++ b/projects/igniteui-angular/test-utils/pivot-grid-functions.spec.ts @@ -1,8 +1,9 @@ import { IPivotGridRecord } from 'igniteui-angular/grids/core'; +import { expect } from 'vitest'; export class PivotGridFunctions { - public static checkUniqueValuesCount(data: any[], value: string, count:number) { + public static checkUniqueValuesCount(data: any[], value: string, count: number) { expect(data.filter(x => x === data).length).toBe(count); } diff --git a/projects/igniteui-angular/test-utils/pivot-grid-samples.spec.ts b/projects/igniteui-angular/test-utils/pivot-grid-samples.spec.ts index c553226cc3c..c405597bf0e 100644 --- a/projects/igniteui-angular/test-utils/pivot-grid-samples.spec.ts +++ b/projects/igniteui-angular/test-utils/pivot-grid-samples.spec.ts @@ -24,10 +24,14 @@ import { IgxPivotDataSelectorComponent, IgxPivotGridComponent } from 'igniteui-a }) export class IgxPivotGridTestBaseComponent { public defaultExpand = true; - @ViewChild('emptyTemplate', { read: TemplateRef, static: true }) public emptyTemplate: TemplateRef; - @ViewChild('chipValue', { read: TemplateRef, static: true }) public chipValueTemplate: TemplateRef; - @ViewChild('grid', { read: IgxPivotGridComponent, static: true }) public pivotGrid: IgxPivotGridComponent; - @ViewChild('selector', { read: IgxPivotDataSelectorComponent, static: true }) public dataSelector: IgxPivotDataSelectorComponent; + @ViewChild('emptyTemplate', { read: TemplateRef, static: true }) + public emptyTemplate: TemplateRef; + @ViewChild('chipValue', { read: TemplateRef, static: true }) + public chipValueTemplate: TemplateRef; + @ViewChild('grid', { read: IgxPivotGridComponent, static: true }) + public pivotGrid: IgxPivotGridComponent; + @ViewChild('selector', { read: IgxPivotDataSelectorComponent, static: true }) + public dataSelector: IgxPivotDataSelectorComponent; public data; public cellClasses; @@ -67,7 +71,8 @@ export class IgxPivotGridTestBaseComponent { { ProductCategory: 'Clothing', UnitPrice: 16.05, SellerName: 'Walter', Country: 'Bulgaria', Date: '02/19/2020', UnitsSold: 492 - }]; + } + ]; this.cellClasses = { test: this.callback, @@ -76,20 +81,20 @@ export class IgxPivotGridTestBaseComponent { this.pivotConfigHierarchy = { columns: [{ - memberName: 'Country', - enabled: true - }, + memberName: 'Country', + enabled: true + }, ], rows: [{ - memberName: 'All', - memberFunction: () => 'All', - enabled: true, - childLevel: { - memberName: 'ProductCategory', - memberFunction: (data) => data.ProductCategory, - enabled: true - } - }], + memberName: 'All', + memberFunction: () => 'All', + enabled: true, + childLevel: { + memberName: 'ProductCategory', + memberFunction: (data) => data.ProductCategory, + enabled: true + } + }], values: [ { member: 'UnitsSold', @@ -130,7 +135,8 @@ export class IgxPivotGridTestBaseComponent { imports: [IgxPivotGridComponent] }) export class IgxPivotGridTestComplexHierarchyComponent extends IgxPivotGridTestBaseComponent { - @ViewChild('grid', { read: IgxPivotGridComponent, static: true }) public override pivotGrid: IgxPivotGridComponent; + @ViewChild('grid', { read: IgxPivotGridComponent, static: true }) + public override pivotGrid: IgxPivotGridComponent; public override defaultExpand = true; constructor() { @@ -163,7 +169,8 @@ export class IgxPivotGridTestComplexHierarchyComponent extends IgxPivotGridTestB { ProductCategory: 'Components', UnitPrice: 16.05, SellerName: 'Walter Pang', Country: 'Bulgaria', City: 'Sofia', Date: '02/19/2013', UnitsSold: 492 - }]; + } + ]; this.pivotConfigHierarchy = { columns: [ @@ -171,27 +178,25 @@ export class IgxPivotGridTestComplexHierarchyComponent extends IgxPivotGridTestB memberName: 'Country', enabled: true } - ] - , + ], rows: [{ - memberName: 'All cities', - memberFunction: () => 'All Cities', - enabled: true, - childLevel: { - memberName: 'City', - enabled: true - } - }, { - memberFunction: () => 'AllProducts', - memberName: 'AllProducts', - enabled: true, - childLevel: - { - memberFunction: (data) => data.ProductCategory, - memberName: 'ProductCategory', - enabled: true - } - }], + memberName: 'All cities', + memberFunction: () => 'All Cities', + enabled: true, + childLevel: { + memberName: 'City', + enabled: true + } + }, { + memberFunction: () => 'AllProducts', + memberName: 'AllProducts', + enabled: true, + childLevel: { + memberFunction: (data) => data.ProductCategory, + memberName: 'ProductCategory', + enabled: true + } + }], values: [ { member: 'UnitsSold', @@ -225,8 +230,10 @@ export class IgxPivotGridTestComplexHierarchyComponent extends IgxPivotGridTestB imports: [IgxPivotGridComponent, IgxGridStateDirective] }) export class IgxPivotGridPersistanceComponent { - @ViewChild(IgxGridStateDirective, { static: true }) public state: IgxGridStateDirective; - @ViewChild('grid', { read: IgxPivotGridComponent, static: true }) public pivotGrid: IgxPivotGridComponent; + @ViewChild(IgxGridStateDirective, { static: true }) + public state: IgxGridStateDirective; + @ViewChild('grid', { read: IgxPivotGridComponent, static: true }) + public pivotGrid: IgxPivotGridComponent; public data = [ { ProductCategory: 'Clothing', UnitPrice: 12.81, SellerName: 'Stanley Brooker', @@ -255,15 +262,15 @@ export class IgxPivotGridPersistanceComponent { { ProductCategory: 'Components', UnitPrice: 16.05, SellerName: 'Walter Pang', Country: 'Bulgaria', City: 'Sofia', Date: '02/19/2013', UnitsSold: 492 - }]; + } + ]; public pivotConfigHierarchy = { columns: [ { memberName: 'Country', enabled: true } - ] - , + ], rows: [ { memberName: 'City', @@ -272,7 +279,8 @@ export class IgxPivotGridPersistanceComponent { { memberName: 'ProductCategory', enabled: true - }], + } + ], values: [ { member: 'UnitsSold', @@ -294,27 +302,28 @@ export class IgxPivotGridPersistanceComponent { imports: [IgxPivotGridComponent] }) export class IgxPivotGridMultipleRowComponent extends IgxPivotGridTestBaseComponent { - @ViewChild('grid', { read: IgxPivotGridComponent, static: true }) public override pivotGrid: IgxPivotGridComponent; + @ViewChild('grid', { read: IgxPivotGridComponent, static: true }) + public override pivotGrid: IgxPivotGridComponent; constructor() { super(); this.pivotConfigHierarchy = { columns: [{ - memberName: 'SellerName', - enabled: true - }, + memberName: 'SellerName', + enabled: true + }, ], rows: [{ - memberName: 'ProductCategory', - memberFunction: (data) => data.ProductCategory, - enabled: true - }, { - memberName: 'Country', - enabled: true - }, { - memberName: 'Date', - enabled: true - }], + memberName: 'ProductCategory', + memberFunction: (data) => data.ProductCategory, + enabled: true + }, { + memberName: 'Country', + enabled: true + }, { + memberName: 'Date', + enabled: true + }], values: [ { member: 'UnitsSold', @@ -366,12 +375,11 @@ export class IgxPivotGridMultipleRowComponent extends IgxPivotGridTestBaseCompon standalone: true, imports: [IgxPivotGridComponent] }) -export class IgxPivotGridFlexContainerComponent extends IgxPivotGridTestBaseComponent{ +export class IgxPivotGridFlexContainerComponent extends IgxPivotGridTestBaseComponent { } export class IgxTotalSaleAggregate { - public static totalSale: PivotAggregation = (members, data: any) => - data.reduce((accumulator, value) => accumulator + value.UnitPrice * value.UnitsSold, 0); + public static totalSale: PivotAggregation = (members, data: any) => data.reduce((accumulator, value) => accumulator + value.UnitPrice * value.UnitsSold, 0); public static totalMin: PivotAggregation = (members, data: any) => { let min = 0; @@ -394,7 +402,7 @@ export class IgxTotalSaleAggregate { }; } -export const SALES_DATA =[ +export const SALES_DATA = [ { "JOBS": 35, "INV_SALES": 2497.11, diff --git a/projects/igniteui-angular/test-utils/routing-test-guard.spec.ts b/projects/igniteui-angular/test-utils/routing-test-guard.spec.ts index f960b3a2d4e..cb6f7dce73d 100644 --- a/projects/igniteui-angular/test-utils/routing-test-guard.spec.ts +++ b/projects/igniteui-angular/test-utils/routing-test-guard.spec.ts @@ -3,7 +3,7 @@ import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; @Injectable() export class RoutingTestGuard { - public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { + public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { if (state.url === '/view5') { return false; } else { diff --git a/projects/igniteui-angular/test-utils/sample-test-data.spec.ts b/projects/igniteui-angular/test-utils/sample-test-data.spec.ts index d94b76511b6..eac46880209 100644 --- a/projects/igniteui-angular/test-utils/sample-test-data.spec.ts +++ b/projects/igniteui-angular/test-utils/sample-test-data.spec.ts @@ -7,7 +7,7 @@ export class SampleTestData { public static timeGenerator: Calendar = new Calendar(); public static today: Date = new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate(), 0, 0, 0); - public static todayFullDate: Date = new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate(), 10, 15, 35); + public static todayFullDate: Date = new Date(new Date().getFullYear(), new Date().getMonth(), new Date().getDate(), 10, 15, 35); public static stringArray = () => ([ 'Terrance Orta', @@ -188,28 +188,25 @@ export class SampleTestData { /* Data fields: ID: number, Name: string, JobTitle: string, WokingHours: number, HireDate: string, Performance: array; 3 items, sorted by ID. */ public static personJobHoursDataPerformance = () => ([ - { ID: 1, Name: 'Casey Houston', JobTitle: 'Vice President', WorkingHours: 4, HireDate: '2017-06-19T11:43:07.714Z', Performance: - [ - {Points: 3, Week: 1}, - {Points: 6, Week: 2}, - {Points: 1, Week: 3}, - {Points: 12, Week: 4} + { ID: 1, Name: 'Casey Houston', JobTitle: 'Vice President', WorkingHours: 4, HireDate: '2017-06-19T11:43:07.714Z', Performance: [ + { Points: 3, Week: 1 }, + { Points: 6, Week: 2 }, + { Points: 1, Week: 3 }, + { Points: 12, Week: 4 } ] }, - { ID: 2, Name: 'Gilberto Todd', JobTitle: 'Director', WorkingHours: 6, HireDate: '2015-12-18T11:23:17.714Z', Performance: - [ - {Points: 8, Week: 1}, - {Points: 7, Week: 2}, - {Points: 4, Week: 3}, - {Points: 9, Week: 4} + { ID: 2, Name: 'Gilberto Todd', JobTitle: 'Director', WorkingHours: 6, HireDate: '2015-12-18T11:23:17.714Z', Performance: [ + { Points: 8, Week: 1 }, + { Points: 7, Week: 2 }, + { Points: 4, Week: 3 }, + { Points: 9, Week: 4 } ] }, - { ID: 3, Name: 'Tanya Bennett', JobTitle: 'Director', WorkingHours: 8, HireDate: '2005-11-18T11:23:17.714Z', Performance: - [ - {Points: 1, Week: 1}, - {Points: 3, Week: 2}, - {Points: 14, Week: 3}, - {Points: 29, Week: 4} + { ID: 3, Name: 'Tanya Bennett', JobTitle: 'Director', WorkingHours: 8, HireDate: '2005-11-18T11:23:17.714Z', Performance: [ + { Points: 1, Week: 1 }, + { Points: 3, Week: 2 }, + { Points: 14, Week: 3 }, + { Points: 29, Week: 4 } ] } ]); @@ -228,7 +225,7 @@ export class SampleTestData { { Name: 'Gilberto Todd', BirthDate: new Date(1985, 4, 17), LastLogin: new Date(2023, 3, 14).setHours(14, 25, 23), MeetingTime: new Date(2023, 6, 7).setHours(9, 35, 31), AttendanceRate: 0.46 }, { Name: 'Tanya Bennett', BirthDate: new Date(1987, 6, 19), LastLogin: new Date(2023, 2, 23).setHours(19, 7, 13), MeetingTime: new Date(2023, 6, 7).setHours(13, 10, 36), AttendanceRate: 0.289 }, { Name: 'Jack Simon', BirthDate: new Date(1995, 8, 23), LastLogin: new Date(2023, 1, 27).setHours(17, 17, 41), MeetingTime: new Date(2023, 6, 7).setHours(14, 50, 47), AttendanceRate: 1 }, - { Name: 'Celia Martinez', BirthDate: new Date(1994, 10, 27), LastLogin: new Date(2023, 2, 14).setHours(1, 31, 49), MeetingTime: new Date(2023, 6, 7).setHours(7, 0, 17), AttendanceRate: 0.384} + { Name: 'Celia Martinez', BirthDate: new Date(1994, 10, 27), LastLogin: new Date(2023, 2, 14).setHours(1, 31, 49), MeetingTime: new Date(2023, 6, 7).setHours(7, 0, 17), AttendanceRate: 0.384 } ]); /* Data fields: ID: number, Name: string, JobTitle: string; 10 items, sorted by ID. */ @@ -263,14 +260,14 @@ export class SampleTestData { JobTitle: string, Company: string; 10 items, sorted by ID. */ public static personNameObjectJobCompany = () => ([ { ID: 1, Name: { FirstName: 'Casey', LastName: 'Houston' }, JobTitle: 'Vice President', Company: 'Company A' }, - { ID: 2, Name: { FirstName: 'Gilberto', LastName: 'Todd' } , JobTitle: 'Director', Company: 'Company C' }, - { ID: 3, Name: { FirstName: 'Tanya', LastName: 'Bennett' } , JobTitle: 'Director', Company: 'Company A' }, + { ID: 2, Name: { FirstName: 'Gilberto', LastName: 'Todd' }, JobTitle: 'Director', Company: 'Company C' }, + { ID: 3, Name: { FirstName: 'Tanya', LastName: 'Bennett' }, JobTitle: 'Director', Company: 'Company A' }, { ID: 4, Name: { FirstName: 'Jack', LastName: 'Simon' }, JobTitle: 'Software Developer', Company: 'Company D' }, { ID: 5, Name: { FirstName: 'Celia', LastName: 'Martinez' }, JobTitle: 'Senior Software DEVELOPER', Company: 'Company B' }, { ID: 6, Name: { FirstName: 'Erma', LastName: 'Walsh' }, JobTitle: 'CEO', Company: 'Company C' }, - { ID: 7, Name: { FirstName: 'Debra', LastName: 'Morton' } , JobTitle: 'Associate Software Developer', Company: 'Company B' }, - { ID: 8, Name: { FirstName: 'Erika', LastName: 'Wells' } , JobTitle: 'Software Development Team Lead', Company: 'Company A' }, - { ID: 9, Name: { FirstName: 'Leslie', LastName: 'Hansen' } , JobTitle: 'Associate Software Developer', Company: 'Company D' }, + { ID: 7, Name: { FirstName: 'Debra', LastName: 'Morton' }, JobTitle: 'Associate Software Developer', Company: 'Company B' }, + { ID: 8, Name: { FirstName: 'Erika', LastName: 'Wells' }, JobTitle: 'Software Development Team Lead', Company: 'Company A' }, + { ID: 9, Name: { FirstName: 'Leslie', LastName: 'Hansen' }, JobTitle: 'Associate Software Developer', Company: 'Company D' }, { ID: 10, Name: { FirstName: 'Eduardo', LastName: 'Ramirez' }, JobTitle: 'Manager', Company: 'Company E' } ]); /* Data fields: ID: number, CompanyName: string, ContactName: string, ContactTitle: string, Address: string, @@ -497,18 +494,18 @@ export class SampleTestData { /* Data fields: ID: number, CompanyName: string, ContactName: string, ContactTitle: string, Address: string, City: string, Region: string, PostalCode: string, Country: string, Phone: string, Fax: string; 1 item. */ public static contactMariaAndersData = () => ([{ - ID: 'ALFKI', - CompanyName: 'Alfreds Futterkiste', - ContactName: 'Maria Anders', - ContactTitle: 'Sales Representative', - Address: 'Obere Str. 57', - City: 'Berlin', - Region: null, - PostalCode: '12209', - Country: 'Germany', - Phone: '030-0074321', - Fax: '030-0076545' - }]); + ID: 'ALFKI', + CompanyName: 'Alfreds Futterkiste', + ContactName: 'Maria Anders', + ContactTitle: 'Sales Representative', + Address: 'Obere Str. 57', + City: 'Berlin', + Region: null, + PostalCode: '12209', + Country: 'Germany', + Phone: '030-0074321', + Fax: '030-0076545' + }]); /* Data fields: Downloads: number, ID: number, ProductName: string, ReleaseDate: Date, Released: boolean; 8 items, sorted by ID. */ @@ -676,23 +673,23 @@ export class SampleTestData { { ProductID: 1, ProductName: 'Chai', InStock: true, UnitsInStock: 2760, OrderDate: new Date(2015, 9, 1, 11, 37, 22), ReceiveTime: new Date(2015, 10, 1, 8, 37, 11), ProducedDate: new Date(2014, 9, 1, 11, 37, 22) }, { ProductID: 2, ProductName: 'Aniseed Syrup', InStock: false, UnitsInStock: 198, OrderDate: new Date(2016, 7, 18, 11, 17, 22), - ReceiveTime: new Date(2016, 10, 8, 12, 12, 2), ProducedDate: new Date(2015, 7, 18, 11, 17, 22) }, + ReceiveTime: new Date(2016, 10, 8, 12, 12, 2), ProducedDate: new Date(2015, 7, 18, 11, 17, 22) }, { ProductID: 3, ProductName: 'Antons Cajun Seasoning', InStock: true, UnitsInStock: 52, OrderDate: new Date(2021, 4, 11, 7, 47, 1), - ReceiveTime: new Date(2021, 4, 29, 14, 7, 12), ProducedDate: new Date(2020, 4, 11, 7, 47, 1) }, + ReceiveTime: new Date(2021, 4, 29, 14, 7, 12), ProducedDate: new Date(2020, 4, 11, 7, 47, 1) }, { ProductID: 4, ProductName: 'Boysenberry Spread', InStock: false, UnitsInStock: 0, OrderDate: new Date(2021, 4, 11, 18, 37, 2), - ReceiveTime: new Date(2021, 4, 27, 6, 40, 18), ProducedDate: new Date(2020, 4, 11, 18, 37, 2) }, + ReceiveTime: new Date(2021, 4, 27, 6, 40, 18), ProducedDate: new Date(2020, 4, 11, 18, 37, 2) }, { ProductID: 5, ProductName: 'Uncle Bobs Dried Pears', InStock: false, UnitsInStock: 0, OrderDate: new Date(2019, 3, 17, 5, 5, 15), - ReceiveTime: new Date(2019, 3, 31, 12, 47, 42), ProducedDate: new Date(2018, 3, 17, 5, 5, 15) }, + ReceiveTime: new Date(2019, 3, 31, 12, 47, 42), ProducedDate: new Date(2018, 3, 17, 5, 5, 15) }, { ProductID: 6, ProductName: 'Cranberry Sauce', InStock: true, UnitsInStock: 1098, OrderDate: new Date(2019, 9, 30, 16, 17, 27), - ReceiveTime: new Date(2019, 10, 11, 12, 47, 42), ProducedDate: new Date(2018, 9, 30, 16, 17, 27) }, + ReceiveTime: new Date(2019, 10, 11, 12, 47, 42), ProducedDate: new Date(2018, 9, 30, 16, 17, 27) }, { ProductID: 7, ProductName: 'Queso Cabrales', InStock: false, UnitsInStock: 0, OrderDate: new Date(2015, 2, 12, 21, 31, 22), - ReceiveTime: new Date(2015, 3, 3, 20, 20, 24), ProducedDate: new Date(2014, 2, 12, 21, 31, 22) }, + ReceiveTime: new Date(2015, 3, 3, 20, 20, 24), ProducedDate: new Date(2014, 2, 12, 21, 31, 22) }, { ProductID: 8, ProductName: 'Tofu', InStock: true, UnitsInStock: 7898, OrderDate: new Date(2018, 6, 14, 17, 27, 23), - ReceiveTime: new Date(2018, 6, 18, 15, 30, 30), ProducedDate: new Date(2017, 6, 14, 17, 27, 23) }, + ReceiveTime: new Date(2018, 6, 18, 15, 30, 30), ProducedDate: new Date(2017, 6, 14, 17, 27, 23) }, { ProductID: 9, ProductName: 'Chocolate Biscuits', InStock: true, UnitsInStock: 6998, OrderDate: new Date(2021, 7, 3, 15, 15, 0), - ReceiveTime: new Date(2021, 7, 7, 15, 30, 22), ProducedDate: new Date(2020, 7, 3, 15, 15, 0) }, + ReceiveTime: new Date(2021, 7, 7, 15, 30, 22), ProducedDate: new Date(2020, 7, 3, 15, 15, 0) }, { ProductID: 10, ProductName: 'Chocolate', InStock: true, UnitsInStock: 20000, OrderDate: new Date(2021, 7, 3, 15, 15, 0), - ReceiveTime: new Date(2021, 7, 11, 14, 30, 0), ProducedDate: new Date(2020, 7, 3, 15, 15, 0) } + ReceiveTime: new Date(2021, 7, 11, 14, 30, 0), ProducedDate: new Date(2020, 7, 3, 15, 15, 0) } ]); public static foodPercentProductData = () => ([ @@ -700,11 +697,11 @@ export class SampleTestData { { ProductID: 2, ProductName: 'Syrup', InStock: false, UnitsInStock: 198, OrderDate: ymd('2008-01-15'), Discount: 0.83 }, { ProductID: 3, ProductName: 'Seasoning', InStock: true, UnitsInStock: 5, OrderDate: ymd('2010-11-20'), Discount: -0.7 }, { ProductID: 4, ProductName: 'Spread', InStock: false, UnitsInStock: 0, OrderDate: ymd('2007-10-11'), Discount: 11 }, - { ProductID: 5, ProductName: 'Bobs Pears', InStock: false, UnitsInStock: 0, OrderDate: ymd('2001-07-27'), Discount: -0.5}, + { ProductID: 5, ProductName: 'Bobs Pears', InStock: false, UnitsInStock: 0, OrderDate: ymd('2001-07-27'), Discount: -0.5 }, { ProductID: 6, ProductName: 'Sauce', InStock: true, UnitsInStock: 1098, OrderDate: ymd('1990-05-17'), Discount: 0.027 }, { ProductID: 7, ProductName: 'Queso Cabrale', InStock: false, UnitsInStock: 0, OrderDate: ymd('2005-03-03'), Discount: 0.099 }, { ProductID: 8, ProductName: 'Tofu', InStock: true, UnitsInStock: 7898, OrderDate: ymd('2017-09-09'), Discount: 10 }, - { ProductID: 9, ProductName: 'Chocolate', InStock: true, UnitsInStock: 698, OrderDate: ymd('2025-12-25'), Discount: .123}, + { ProductID: 9, ProductName: 'Chocolate', InStock: true, UnitsInStock: 698, OrderDate: ymd('2025-12-25'), Discount: .123 }, { ProductID: 10, ProductName: 'Biscuits', InStock: true, UnitsInStock: 20000, OrderDate: ymd('2018-03-01'), Discount: 0.39 } ]); @@ -928,24 +925,24 @@ export class SampleTestData { Certain characters serving as delimiters can be changed. Mostly used in CSV exporters tests. */ public static getContactsFunkyData(delimiter) { return [{ - name: 'Terrance Mc\'Orta', - phone: '(+359)770-504-2217 | 2218' - }, { - name: 'Richard Mahoney /LongerName/', - phone: '' - }, { - name: 'Donna' + delimiter + ' \/; Price', - phone: '859 496 28**' - }, { - name: '\r\n', - phone: '901-747-3428' - }, { - name: 'Dorothy "H." Spencer', - phone: '573-394-9254[fax]' - }, { - name: 'Иван Иванов (1' + delimiter + '2)', - phone: '№ 573-394-9254' - }]; + name: 'Terrance Mc\'Orta', + phone: '(+359)770-504-2217 | 2218' + }, { + name: 'Richard Mahoney /LongerName/', + phone: '' + }, { + name: 'Donna' + delimiter + ' \/; Price', + phone: '859 496 28**' + }, { + name: '\r\n', + phone: '901-747-3428' + }, { + name: 'Dorothy "H." Spencer', + phone: '573-394-9254[fax]' + }, { + name: 'Иван Иванов (1' + delimiter + '2)', + phone: '№ 573-394-9254' + }]; } /* Tree data: Every employee node has ID, Name, HireDate, Age and Employees */ @@ -995,7 +992,8 @@ export class SampleTestData { OnPTO: false, } ] - }] + } + ] }, { ID: 847, @@ -1026,7 +1024,8 @@ export class SampleTestData { Age: 39 } ] - }] + } + ] }, { ID: 19, @@ -1042,7 +1041,8 @@ export class SampleTestData { Age: 44, OnPTO: true, Employees: [] - }] + } + ] }, { ID: 17, @@ -1088,7 +1088,8 @@ export class SampleTestData { HireDate: new Date(2016, 2, 19), OnPTO: false, Age: 27 - }] + } + ] } ]); @@ -1173,7 +1174,8 @@ export class SampleTestData { Age: 25 } ] - }] + } + ] }, { ID: 19, @@ -1192,7 +1194,8 @@ export class SampleTestData { Name: 'Elizabeth Richards', HireDate: new Date(2017, 11, 9), Age: 25 - }] + } + ] } ]); @@ -1323,7 +1326,8 @@ export class SampleTestData { Age: 25 } ] - }] + } + ] }, { ID: 19, @@ -1345,7 +1349,8 @@ export class SampleTestData { HireDate: new Date(2017, 11, 9), JobTitle: 'Software Developer', Age: 25 - }] + } + ] } ]); @@ -1403,7 +1408,8 @@ export class SampleTestData { OnPTO: false, } ] - }] + } + ] }, { ID: 19, @@ -1425,7 +1431,8 @@ export class SampleTestData { HireDate: new Date(2017, 11, 9), Age: 25, OnPTO: true - }] + } + ] } ]); @@ -2382,33 +2389,33 @@ export class SampleTestData { USBillboard200: 1, Artist: 'Naomí Yepes', Songs: [{ - Number: 1, - Title: 'Ambitious', - Released: new Date('28 Apr 2015'), - Genre: 'Dance-pop R&B', - Album: 'Initiation' - }, - { - Number: 2, - Title: 'My heart will go on', - Released: new Date('24 May 2015'), - Genre: 'Dance-pop R&B', - Album: 'Initiation' - }, - { - Number: 3, - Title: 'Sing to me', - Released: new Date('28 May 2015'), - Genre: 'Dance-pop R&B', - Album: 'Initiation' - }, - { - Number: 4, - Title: 'Want to dance with somebody', - Released: new Date('03 Jun 2015'), - Genre: 'Dance-pop R&B', - Album: 'Initiation' - }] + Number: 1, + Title: 'Ambitious', + Released: new Date('28 Apr 2015'), + Genre: 'Dance-pop R&B', + Album: 'Initiation' + }, + { + Number: 2, + Title: 'My heart will go on', + Released: new Date('24 May 2015'), + Genre: 'Dance-pop R&B', + Album: 'Initiation' + }, + { + Number: 3, + Title: 'Sing to me', + Released: new Date('28 May 2015'), + Genre: 'Dance-pop R&B', + Album: 'Initiation' + }, + { + Number: 4, + Title: 'Want to dance with somebody', + Released: new Date('03 Jun 2015'), + Genre: 'Dance-pop R&B', + Album: 'Initiation' + }] }, { Album: 'Dream Driven', @@ -2417,89 +2424,89 @@ export class SampleTestData { USBillboard200: 1, Artist: 'Naomí Yepes', Songs: [{ - Number: 1, - Title: 'Intro', - Released: null, - Genre: '*', - Album: 'Dream Driven' - }, - { - Number: 2, - Title: 'Ferocious', - Released: new Date('28 Apr 2014'), - Genre: 'Dance-pop R&B', - Album: 'Dream Driven' - }, - { - Number: 3, - Title: 'Going crazy', - Released: new Date('10 Feb 2015'), - Genre: 'Dance-pop EDM', - Album: 'Dream Driven' - }, - { - Number: 4, - Title: 'Future past', - Released: null, - Genre: '*', - Album: 'Dream Driven' - }, - { - Number: 5, - Title: 'Roaming like them', - Released: new Date('2 Jul 2014'), - Genre: 'Electro house Electropop', - Album: 'Dream Driven' - }, - { - Number: 6, - Title: 'Last Wishes', - Released: new Date('12 Aug 2014'), - Genre: 'R&B', - Album: 'Dream Driven' - }, - { - Number: 7, - Title: 'Stay where you are', - Released: null, - Genre: '*', - Album: 'Dream Driven' - }, - { - Number: 8, - Title: 'Imaginarium', - Released: null, - Genre: '*', - Album: 'Dream Driven' - }, - { - Number: 9, - Title: 'Tell me', - Released: new Date('30 Sep 2014'), - Genre: 'Synth-pop R&B', - Album: 'Dream Driven' - }, - { - Number: 10, - Title: 'Shredded into pieces', - Released: null, - Genre: '*', - Album: 'Dream Driven' - }, - { - Number: 11, - Title: 'Capture this moment', - Released: null, - Genre: '*', - Album: 'Dream Driven' - }, - { - Number: 12, - Title: 'Dream Driven', - Released: null, - Genre: '*', - Album: 'Dream Driven' - }] + Number: 1, + Title: 'Intro', + Released: null, + Genre: '*', + Album: 'Dream Driven' + }, + { + Number: 2, + Title: 'Ferocious', + Released: new Date('28 Apr 2014'), + Genre: 'Dance-pop R&B', + Album: 'Dream Driven' + }, + { + Number: 3, + Title: 'Going crazy', + Released: new Date('10 Feb 2015'), + Genre: 'Dance-pop EDM', + Album: 'Dream Driven' + }, + { + Number: 4, + Title: 'Future past', + Released: null, + Genre: '*', + Album: 'Dream Driven' + }, + { + Number: 5, + Title: 'Roaming like them', + Released: new Date('2 Jul 2014'), + Genre: 'Electro house Electropop', + Album: 'Dream Driven' + }, + { + Number: 6, + Title: 'Last Wishes', + Released: new Date('12 Aug 2014'), + Genre: 'R&B', + Album: 'Dream Driven' + }, + { + Number: 7, + Title: 'Stay where you are', + Released: null, + Genre: '*', + Album: 'Dream Driven' + }, + { + Number: 8, + Title: 'Imaginarium', + Released: null, + Genre: '*', + Album: 'Dream Driven' + }, + { + Number: 9, + Title: 'Tell me', + Released: new Date('30 Sep 2014'), + Genre: 'Synth-pop R&B', + Album: 'Dream Driven' + }, + { + Number: 10, + Title: 'Shredded into pieces', + Released: null, + Genre: '*', + Album: 'Dream Driven' + }, + { + Number: 11, + Title: 'Capture this moment', + Released: null, + Genre: '*', + Album: 'Dream Driven' + }, + { + Number: 12, + Title: 'Dream Driven', + Released: null, + Genre: '*', + Album: 'Dream Driven' + }] }, { Album: 'The dragon journey', @@ -2508,33 +2515,33 @@ export class SampleTestData { USBillboard200: 2, Artist: 'Naomí Yepes', Songs: [{ - Number: 1, - Title: 'My dream', - Released: new Date('13 Jan 2017'), - Genre: 'Dance-pop EDM', - Album: 'The dragon journey' - }, - { - Number: 2, - Title: 'My passion', - Released: new Date('23 Sep 2017'), - Genre: 'Crunk reggaeton', - Album: 'The dragon journey' - }, - { - Number: 3, - Title: 'What is love', - Released: new Date('28 Nov 2018'), - Genre: 'Dance-pop R&B', - Album: 'The dragon journey' - }, - { - Number: 4, - Title: 'Negative', - Released: new Date('01 Dec 2018'), - Genre: 'Dance-pop EDM', - Album: 'The dragon journey' - }] + Number: 1, + Title: 'My dream', + Released: new Date('13 Jan 2017'), + Genre: 'Dance-pop EDM', + Album: 'The dragon journey' + }, + { + Number: 2, + Title: 'My passion', + Released: new Date('23 Sep 2017'), + Genre: 'Crunk reggaeton', + Album: 'The dragon journey' + }, + { + Number: 3, + Title: 'What is love', + Released: new Date('28 Nov 2018'), + Genre: 'Dance-pop R&B', + Album: 'The dragon journey' + }, + { + Number: 4, + Title: 'Negative', + Released: new Date('01 Dec 2018'), + Genre: 'Dance-pop EDM', + Album: 'The dragon journey' + }] }, { Album: 'Organic me', @@ -2543,82 +2550,82 @@ export class SampleTestData { USBillboard200: 1, Artist: 'Naomí Yepes', Songs: [{ - Number: 1, - Title: 'I Love', - Released: new Date('11 May 2019'), - Genre: 'Crunk reggaeton', - Album: 'Organic me' - }, - { - Number: 2, - Title: 'Early Morning Compass', - Released: new Date('15 Jan 2020'), - Genre: 'mystical parody-bap ', - Album: 'Organic me' - }, - { - Number: 3, - Title: 'Key Fields Forever', - Released: new Date('2 Jan 2020'), - Genre: 'Dance-pop EDM', - Album: 'Organic me' - }, - { - Number: 4, - Title: 'Stand by Your Goblins', - Released: new Date('20 Nov 2019'), - Genre: '*', - Album: 'Organic me' - }, - { - Number: 5, - Title: 'Mad to Walk', - Released: new Date('12 May 2019'), - Genre: 'Electro house Electropop', - Album: 'Organic me' - }, - { - Number: 6, - Title: 'Alice\'s Waiting', - Released: new Date('28 Jan 2020'), - Genre: 'R&B', - Album: 'Organic me' - }, - { - Number: 7, - Title: 'We Shall Kiss', - Released: new Date('30 Oct 2019'), - Genre: '*', - Album: 'Organic me' - }, - { - Number: 8, - Title: 'Behind Single Ants', - Released: new Date('2 Oct 2019'), - Genre: '*', - Album: 'Organic me' - }, - { - Number: 9, - Title: 'Soap Autopsy', - Released: new Date('8 Aug 2019'), - Genre: 'Synth-pop R&B', - Album: 'Organic me' - }, - { - Number: 10, - Title: 'Have You Met Rich?', - Released: new Date('1 Jul 2019'), - Genre: 'ethno-tunes', - Album: 'Organic me' - }, - { - Number: 11, - Title: 'Livin\' on a Banana', - Released: new Date('22 Nov 2019'), - Genre: 'Crunk reggaeton', - Album: 'Organic me' - }] + Number: 1, + Title: 'I Love', + Released: new Date('11 May 2019'), + Genre: 'Crunk reggaeton', + Album: 'Organic me' + }, + { + Number: 2, + Title: 'Early Morning Compass', + Released: new Date('15 Jan 2020'), + Genre: 'mystical parody-bap ', + Album: 'Organic me' + }, + { + Number: 3, + Title: 'Key Fields Forever', + Released: new Date('2 Jan 2020'), + Genre: 'Dance-pop EDM', + Album: 'Organic me' + }, + { + Number: 4, + Title: 'Stand by Your Goblins', + Released: new Date('20 Nov 2019'), + Genre: '*', + Album: 'Organic me' + }, + { + Number: 5, + Title: 'Mad to Walk', + Released: new Date('12 May 2019'), + Genre: 'Electro house Electropop', + Album: 'Organic me' + }, + { + Number: 6, + Title: 'Alice\'s Waiting', + Released: new Date('28 Jan 2020'), + Genre: 'R&B', + Album: 'Organic me' + }, + { + Number: 7, + Title: 'We Shall Kiss', + Released: new Date('30 Oct 2019'), + Genre: '*', + Album: 'Organic me' + }, + { + Number: 8, + Title: 'Behind Single Ants', + Released: new Date('2 Oct 2019'), + Genre: '*', + Album: 'Organic me' + }, + { + Number: 9, + Title: 'Soap Autopsy', + Released: new Date('8 Aug 2019'), + Genre: 'Synth-pop R&B', + Album: 'Organic me' + }, + { + Number: 10, + Title: 'Have You Met Rich?', + Released: new Date('1 Jul 2019'), + Genre: 'ethno-tunes', + Album: 'Organic me' + }, + { + Number: 11, + Title: 'Livin\' on a Banana', + Released: new Date('22 Nov 2019'), + Genre: 'Crunk reggaeton', + Album: 'Organic me' + }] }, { Album: 'Curiosity', @@ -2627,47 +2634,47 @@ export class SampleTestData { USBillboard200: 12, Artist: 'Naomí Yepes', Songs: [{ - Number: 1, - Title: 'Goals', - Released: new Date('07 Dec 2019'), - Genre: '*', - Album: 'Curiosity' - }, - { - Number: 2, - Title: 'Explorer', - Released: new Date('08 Dec 2019'), - Genre: 'Crunk reggaeton', - Album: 'Curiosity' - }, - { - Number: 3, - Title: 'I need to know', - Released: new Date('09 Dec 2019'), - Genre: 'Dance-pop R&B', - Album: 'Curiosity' - }, - { - Number: 4, - Title: 'Finding my purpose', - Released: new Date('10 Dec 2019'), - Genre: 'Heavy metal', - Album: 'Curiosity' - }, - { - Number: 5, - Title: 'Faster than the speed of love', - Released: new Date('21 Dec 2019'), - Genre: 'Dance-pop EDM', - Album: 'Curiosity' - }, - { - Number: 6, - Title: 'I like it', - Released: new Date('01 Jan 2020'), - Genre: 'Dance-pop EDM', - Album: 'Curiosity' - }] + Number: 1, + Title: 'Goals', + Released: new Date('07 Dec 2019'), + Genre: '*', + Album: 'Curiosity' + }, + { + Number: 2, + Title: 'Explorer', + Released: new Date('08 Dec 2019'), + Genre: 'Crunk reggaeton', + Album: 'Curiosity' + }, + { + Number: 3, + Title: 'I need to know', + Released: new Date('09 Dec 2019'), + Genre: 'Dance-pop R&B', + Album: 'Curiosity' + }, + { + Number: 4, + Title: 'Finding my purpose', + Released: new Date('10 Dec 2019'), + Genre: 'Heavy metal', + Album: 'Curiosity' + }, + { + Number: 5, + Title: 'Faster than the speed of love', + Released: new Date('21 Dec 2019'), + Genre: 'Dance-pop EDM', + Album: 'Curiosity' + }, + { + Number: 6, + Title: 'I like it', + Released: new Date('01 Jan 2020'), + Genre: 'Dance-pop EDM', + Album: 'Curiosity' + }] } ] }, @@ -2713,7 +2720,8 @@ export class SampleTestData { Location: 'North America', Headliner: 'YES', TouredBy: 'Babila Ebwélé' - }], + } + ], Albums: [ { Album: 'Pushing up daisies', @@ -2722,75 +2730,75 @@ export class SampleTestData { USBillboard200: 42, Artist: 'Babila Ebwélé', Songs: [{ - Number: 1, - Title: 'Wood Shavings Forever', - Released: new Date('9 Jun 2019'), - Genre: '*', - Album: 'Pushing up daisies' - }, - { - Number: 2, - Title: 'Early Morning Drive', - Released: new Date('20 May 2019'), - Genre: '*', - Album: 'Pushing up daisies' - }, - { - Number: 3, - Title: 'Don\'t Natter', - Released: new Date('10 Jun 2019'), - Genre: 'adult calypso-industrial', - Album: 'Pushing up daisies' - }, - { - Number: 4, - Title: 'Stairway to Balloons', - Released: new Date('18 Jun 2019'), - Genre: 'calypso and mariachi', - Album: 'Pushing up daisies' - }, - { - Number: 5, - Title: 'The Number of your Apple', - Released: new Date('29 Oct 2019'), - Genre: '*', - Album: 'Pushing up daisies' - }, - { - Number: 6, - Title: 'Your Delightful Heart', - Released: new Date('24 Feb 2019'), - Genre: '*', - Album: 'Pushing up daisies' - }, - { - Number: 7, - Title: 'Nice Weather For Balloons', - Released: new Date('1 Aug 2019'), - Genre: 'rap-hop', - Album: 'Pushing up daisies' - }, - { - Number: 8, - Title: 'The Girl From Cornwall', - Released: new Date('4 May 2019'), - Genre: 'enigmatic rock-and-roll', - Album: 'Pushing up daisies' - }, - { - Number: 9, - Title: 'Here Without Jack', - Released: new Date('24 Oct 2019'), - Genre: '*', - Album: 'Pushing up daisies' - }, - { - Number: 10, - Title: 'Born Rancid', - Released: new Date('19 Mar 2019'), - Genre: '*', - Album: 'Pushing up daisies' - }] + Number: 1, + Title: 'Wood Shavings Forever', + Released: new Date('9 Jun 2019'), + Genre: '*', + Album: 'Pushing up daisies' + }, + { + Number: 2, + Title: 'Early Morning Drive', + Released: new Date('20 May 2019'), + Genre: '*', + Album: 'Pushing up daisies' + }, + { + Number: 3, + Title: 'Don\'t Natter', + Released: new Date('10 Jun 2019'), + Genre: 'adult calypso-industrial', + Album: 'Pushing up daisies' + }, + { + Number: 4, + Title: 'Stairway to Balloons', + Released: new Date('18 Jun 2019'), + Genre: 'calypso and mariachi', + Album: 'Pushing up daisies' + }, + { + Number: 5, + Title: 'The Number of your Apple', + Released: new Date('29 Oct 2019'), + Genre: '*', + Album: 'Pushing up daisies' + }, + { + Number: 6, + Title: 'Your Delightful Heart', + Released: new Date('24 Feb 2019'), + Genre: '*', + Album: 'Pushing up daisies' + }, + { + Number: 7, + Title: 'Nice Weather For Balloons', + Released: new Date('1 Aug 2019'), + Genre: 'rap-hop', + Album: 'Pushing up daisies' + }, + { + Number: 8, + Title: 'The Girl From Cornwall', + Released: new Date('4 May 2019'), + Genre: 'enigmatic rock-and-roll', + Album: 'Pushing up daisies' + }, + { + Number: 9, + Title: 'Here Without Jack', + Released: new Date('24 Oct 2019'), + Genre: '*', + Album: 'Pushing up daisies' + }, + { + Number: 10, + Title: 'Born Rancid', + Released: new Date('19 Mar 2019'), + Genre: '*', + Album: 'Pushing up daisies' + }] }, { Album: 'Death\'s dead', @@ -2799,83 +2807,84 @@ export class SampleTestData { USBillboard200: 95, Artist: 'Babila Ebwélé', Songs: [{ - Number: 1, - Title: 'Men Sound Better With You', - Released: new Date('20 Oct 2016'), - Genre: 'rap-hop', - Album: 'Death\'s dead' - }, - { - Number: 2, - Title: 'Ghost in My Rod', - Released: new Date('5 Oct 2016'), - Genre: 'enigmatic rock-and-roll', - Album: 'Death\'s dead' - }, - { - Number: 3, - Title: 'Bed of Men', - Released: new Date('14 Nov 2016'), - Genre: 'whimsical comedy-grass ', - Album: 'Death\'s dead' - }, - { - Number: 4, - Title: 'Don\'t Push', - Released: new Date('2 Jan 2017'), - Genre: 'unblack electronic-trip-hop', - Album: 'Death\'s dead' - }, - { - Number: 5, - Title: 'Nice Weather For Men', - Released: new Date('18 Dec 2017'), - Genre: '*', - Album: 'Death\'s dead' - }, - { - Number: 6, - Title: 'Rancid Rhapsody', - Released: new Date('10 Mar 2017'), - Genre: '*', - Album: 'Death\'s dead' - }, - { - Number: 7, - Title: 'Push, Push, Push!', - Released: new Date('21 Feb 2017'), - Genre: '*', - Album: 'Death\'s dead' - }, - { - Number: 8, - Title: 'My Name is Sarah', - Released: new Date('15 Nov 2017'), - Genre: '*', - Album: 'Death\'s dead' - }, - { - Number: 9, - Title: 'The Girl From My Hotel', - Released: new Date('6 Nov 2017'), - Genre: '*', - Album: 'Death\'s dead' - }, - { - Number: 10, - Title: 'Free Box', - Released: new Date('18 Apr 2017'), - Genre: 'splitter-funk', - Album: 'Death\'s dead' - }, - { - Number: 11, - Title: 'Hotel Cardiff', - Released: new Date('30 Dec 2017'), - Genre: 'guilty pleasure ebm', - Album: 'Death\'s dead' - }] - }] + Number: 1, + Title: 'Men Sound Better With You', + Released: new Date('20 Oct 2016'), + Genre: 'rap-hop', + Album: 'Death\'s dead' + }, + { + Number: 2, + Title: 'Ghost in My Rod', + Released: new Date('5 Oct 2016'), + Genre: 'enigmatic rock-and-roll', + Album: 'Death\'s dead' + }, + { + Number: 3, + Title: 'Bed of Men', + Released: new Date('14 Nov 2016'), + Genre: 'whimsical comedy-grass ', + Album: 'Death\'s dead' + }, + { + Number: 4, + Title: 'Don\'t Push', + Released: new Date('2 Jan 2017'), + Genre: 'unblack electronic-trip-hop', + Album: 'Death\'s dead' + }, + { + Number: 5, + Title: 'Nice Weather For Men', + Released: new Date('18 Dec 2017'), + Genre: '*', + Album: 'Death\'s dead' + }, + { + Number: 6, + Title: 'Rancid Rhapsody', + Released: new Date('10 Mar 2017'), + Genre: '*', + Album: 'Death\'s dead' + }, + { + Number: 7, + Title: 'Push, Push, Push!', + Released: new Date('21 Feb 2017'), + Genre: '*', + Album: 'Death\'s dead' + }, + { + Number: 8, + Title: 'My Name is Sarah', + Released: new Date('15 Nov 2017'), + Genre: '*', + Album: 'Death\'s dead' + }, + { + Number: 9, + Title: 'The Girl From My Hotel', + Released: new Date('6 Nov 2017'), + Genre: '*', + Album: 'Death\'s dead' + }, + { + Number: 10, + Title: 'Free Box', + Released: new Date('18 Apr 2017'), + Genre: 'splitter-funk', + Album: 'Death\'s dead' + }, + { + Number: 11, + Title: 'Hotel Cardiff', + Released: new Date('30 Dec 2017'), + Genre: 'guilty pleasure ebm', + Album: 'Death\'s dead' + }] + } + ] }, { ID: 2, @@ -2893,61 +2902,61 @@ export class SampleTestData { USBillboard200: 69, Artist: 'Ahmad Nazeri', Songs: [{ - Number: 1, - Title: 'I am machine', - Released: new Date('20 Oct 2004'), - Genre: 'Heavy metal', - Album: 'Emergency' - }, - { - Number: 2, - Title: 'I wish I knew', - Released: new Date('21 Oct 2004'), - Genre: 'rap-hop', - Album: 'Emergency' - }, - { - Number: 3, - Title: 'How I feel', - Released: new Date('22 Oct 2004'), - Genre: 'Heavy metal', - Album: 'Emergency' - }, - { - Number: 4, - Title: 'I am machine', - Released: new Date('30 Oct 2004'), - Genre: 'Heavy metal', - Album: 'Emergency' - }, - { - Number: 5, - Title: 'Monsters under my bed', - Released: new Date('01 Nov 2004'), - Genre: 'rap-hop', - Album: 'Emergency' - }, - { - Number: 6, - Title: 'I know what you want', - Released: new Date('20 Nov 2004'), - Genre: 'rap-hop', - Album: 'Emergency' - }, - { - Number: 7, - Title: 'Lies', - Released: new Date('21 Nov 2004'), - Genre: 'Heavy metal', - Album: 'Emergency' - }, - { - Number: 8, - Title: 'I did it for you', - Released: new Date('22 Nov 2004'), - Genre: 'rap-hop', - Album: 'Emergency' - }] + Number: 1, + Title: 'I am machine', + Released: new Date('20 Oct 2004'), + Genre: 'Heavy metal', + Album: 'Emergency' + }, + { + Number: 2, + Title: 'I wish I knew', + Released: new Date('21 Oct 2004'), + Genre: 'rap-hop', + Album: 'Emergency' + }, + { + Number: 3, + Title: 'How I feel', + Released: new Date('22 Oct 2004'), + Genre: 'Heavy metal', + Album: 'Emergency' + }, + { + Number: 4, + Title: 'I am machine', + Released: new Date('30 Oct 2004'), + Genre: 'Heavy metal', + Album: 'Emergency' + }, + { + Number: 5, + Title: 'Monsters under my bed', + Released: new Date('01 Nov 2004'), + Genre: 'rap-hop', + Album: 'Emergency' + }, + { + Number: 6, + Title: 'I know what you want', + Released: new Date('20 Nov 2004'), + Genre: 'rap-hop', + Album: 'Emergency' + }, + { + Number: 7, + Title: 'Lies', + Released: new Date('21 Nov 2004'), + Genre: 'Heavy metal', + Album: 'Emergency' + }, + { + Number: 8, + Title: 'I did it for you', + Released: new Date('22 Nov 2004'), + Genre: 'rap-hop', + Album: 'Emergency' + }] }, { Album: 'Bursting bubbles', @@ -2956,33 +2965,33 @@ export class SampleTestData { USBillboard200: 39, Artist: 'Ahmad Nazeri', Songs: [{ - Number: 1, - Title: 'Ghosts', - Released: new Date('20 Apr 2006'), - Genre: 'Hip-hop', - Album: 'Bursting bubbles' - }, - { - Number: 2, - Title: 'What goes around comes around', - Released: new Date('20 Apr 2006'), - Genre: 'Heavy metal', - Album: 'Bursting bubbles' - }, - { - Number: 3, - Title: 'I want nothing', - Released: new Date('21 Apr 2006'), - Genre: 'Heavy metal', - Album: 'Bursting bubbles' - }, - { - Number: 4, - Title: 'Me and you', - Released: new Date('22 Apr 2006'), - Genre: 'Rock', - Album: 'Bursting bubbles' - }] + Number: 1, + Title: 'Ghosts', + Released: new Date('20 Apr 2006'), + Genre: 'Hip-hop', + Album: 'Bursting bubbles' + }, + { + Number: 2, + Title: 'What goes around comes around', + Released: new Date('20 Apr 2006'), + Genre: 'Heavy metal', + Album: 'Bursting bubbles' + }, + { + Number: 3, + Title: 'I want nothing', + Released: new Date('21 Apr 2006'), + Genre: 'Heavy metal', + Album: 'Bursting bubbles' + }, + { + Number: 4, + Title: 'Me and you', + Released: new Date('22 Apr 2006'), + Genre: 'Rock', + Album: 'Bursting bubbles' + }] } ] }, @@ -3001,40 +3010,40 @@ export class SampleTestData { USBillboard200: 1, Artist: 'Kimmy McIlmorie', Songs: [{ - Number: 1, - Title: 'Same old love', - Released: new Date('20 Nov 2017'), - Genre: 'Hip-hop', - Album: 'Here we go again' - }, - { - Number: 2, - Title: 'Sick of it', - Released: new Date('20 Nov 2017'), - Genre: 'Hip-hop', - Album: 'Here we go again' - }, - { - Number: 3, - Title: 'No one', - Released: new Date('21 Nov 2017'), - Genre: 'Metal', - Album: 'Here we go again' - }, - { - Number: 4, - Title: 'Circles', - Released: new Date('22 Nov 2017'), - Genre: 'Heavy metal', - Album: 'Here we go again' - }, - { - Number: 5, - Title: 'Coming for you', - Released: new Date('30 Nov 2017'), - Genre: 'Hip-hop', - Album: 'Here we go again' - }] + Number: 1, + Title: 'Same old love', + Released: new Date('20 Nov 2017'), + Genre: 'Hip-hop', + Album: 'Here we go again' + }, + { + Number: 2, + Title: 'Sick of it', + Released: new Date('20 Nov 2017'), + Genre: 'Hip-hop', + Album: 'Here we go again' + }, + { + Number: 3, + Title: 'No one', + Released: new Date('21 Nov 2017'), + Genre: 'Metal', + Album: 'Here we go again' + }, + { + Number: 4, + Title: 'Circles', + Released: new Date('22 Nov 2017'), + Genre: 'Heavy metal', + Album: 'Here we go again' + }, + { + Number: 5, + Title: 'Coming for you', + Released: new Date('30 Nov 2017'), + Genre: 'Hip-hop', + Album: 'Here we go again' + }] } ] }, @@ -3053,40 +3062,40 @@ export class SampleTestData { USBillboard200: 2, Artist: 'Mar Rueda', Songs: [{ - Number: 1, - Title: 'You knew I was trouble', - Released: new Date('20 Nov 2017'), - Genre: 'Pop', - Album: 'Trouble' - }, - { - Number: 2, - Title: 'Cannot live without you', - Released: new Date('20 Nov 2017'), - Genre: 'Pop', - Album: 'Trouble' - }, - { - Number: 3, - Title: 'Lost you', - Released: new Date('21 Nov 2017'), - Genre: 'Metal', - Album: 'Trouble' - }, - { - Number: 4, - Title: 'Happiness starts with you', - Released: new Date('22 Nov 2017'), - Genre: '*', - Album: 'Trouble' - }, - { - Number: 5, - Title: 'I saw it coming', - Released: new Date('30 Dec 2017'), - Genre: 'Hip-hop', - Album: 'Trouble' - }] + Number: 1, + Title: 'You knew I was trouble', + Released: new Date('20 Nov 2017'), + Genre: 'Pop', + Album: 'Trouble' + }, + { + Number: 2, + Title: 'Cannot live without you', + Released: new Date('20 Nov 2017'), + Genre: 'Pop', + Album: 'Trouble' + }, + { + Number: 3, + Title: 'Lost you', + Released: new Date('21 Nov 2017'), + Genre: 'Metal', + Album: 'Trouble' + }, + { + Number: 4, + Title: 'Happiness starts with you', + Released: new Date('22 Nov 2017'), + Genre: '*', + Album: 'Trouble' + }, + { + Number: 5, + Title: 'I saw it coming', + Released: new Date('30 Dec 2017'), + Genre: 'Hip-hop', + Album: 'Trouble' + }] } ] }, @@ -3135,75 +3144,75 @@ export class SampleTestData { USBillboard200: 53, Artist: 'Izabella Tabakova', Songs: [{ - Number: 1, - Title: 'Whole Lotta Super Cats', - Released: new Date('21 May 2019'), - Genre: '*', - Album: 'Once bitten' - }, - { - Number: 2, - Title: 'Enter Becky', - Released: new Date('16 Jan 2020'), - Genre: '*', - Album: 'Once bitten' - }, - { - Number: 3, - Title: 'Your Cheatin\' Flamingo', - Released: new Date('14 Jan 2020'), - Genre: '*', - Album: 'Once bitten' - }, - { - Number: 4, - Title: 'Mad to Kiss', - Released: new Date('6 Nov 2019'), - Genre: 'Synth-pop R&B', - Album: 'Once bitten' - }, - { - Number: 5, - Title: 'Hotel Prague', - Released: new Date('20 Oct 2019'), - Genre: 'ethno-tunes', - Album: 'Once bitten' - }, - { - Number: 6, - Title: 'Jail on My Mind', - Released: new Date('31 May 2019'), - Genre: 'Crunk reggaeton', - Album: 'Once bitten' - }, - { - Number: 7, - Title: 'Amazing Blues', - Released: new Date('29 May 2019'), - Genre: 'mystical parody-bap ', - Album: 'Once bitten' - }, - { - Number: 8, - Title: 'Goody Two Iron Filings', - Released: new Date('4 Jul 2019'), - Genre: 'Electro house Electropop', - Album: 'Once bitten' - }, - { - Number: 9, - Title: 'I Love in Your Arms', - Released: new Date('7 Jun 2019'), - Genre: 'R&B', - Album: 'Once bitten' - }, - { - Number: 10, - Title: 'Truly Madly Amazing', - Released: new Date('12 Sep 2019'), - Genre: 'ethno-tunes', - Album: 'Once bitten' - } + Number: 1, + Title: 'Whole Lotta Super Cats', + Released: new Date('21 May 2019'), + Genre: '*', + Album: 'Once bitten' + }, + { + Number: 2, + Title: 'Enter Becky', + Released: new Date('16 Jan 2020'), + Genre: '*', + Album: 'Once bitten' + }, + { + Number: 3, + Title: 'Your Cheatin\' Flamingo', + Released: new Date('14 Jan 2020'), + Genre: '*', + Album: 'Once bitten' + }, + { + Number: 4, + Title: 'Mad to Kiss', + Released: new Date('6 Nov 2019'), + Genre: 'Synth-pop R&B', + Album: 'Once bitten' + }, + { + Number: 5, + Title: 'Hotel Prague', + Released: new Date('20 Oct 2019'), + Genre: 'ethno-tunes', + Album: 'Once bitten' + }, + { + Number: 6, + Title: 'Jail on My Mind', + Released: new Date('31 May 2019'), + Genre: 'Crunk reggaeton', + Album: 'Once bitten' + }, + { + Number: 7, + Title: 'Amazing Blues', + Released: new Date('29 May 2019'), + Genre: 'mystical parody-bap ', + Album: 'Once bitten' + }, + { + Number: 8, + Title: 'Goody Two Iron Filings', + Released: new Date('4 Jul 2019'), + Genre: 'Electro house Electropop', + Album: 'Once bitten' + }, + { + Number: 9, + Title: 'I Love in Your Arms', + Released: new Date('7 Jun 2019'), + Genre: 'R&B', + Album: 'Once bitten' + }, + { + Number: 10, + Title: 'Truly Madly Amazing', + Released: new Date('12 Sep 2019'), + Genre: 'ethno-tunes', + Album: 'Once bitten' + } ] }, { @@ -3282,7 +3291,8 @@ export class SampleTestData { Released: new Date('25 Jul 2019'), Genre: '*', Album: 'Your graciousness' - }] + } + ] }, { Album: 'Dark matters', @@ -3291,33 +3301,33 @@ export class SampleTestData { USBillboard200: 85, Artist: 'Izabella Tabakova', Songs: [{ - Number: 1, - Title: 'The Sun', - Released: new Date('31 Oct 2002'), - Genre: 'old emo-garage ', - Album: 'Dark matters' - }, - { - Number: 2, - Title: 'I will survive', - Released: new Date('03 Nov 2002'), - Genre: 'old emo-garage ', - Album: 'Dark matters' - }, - { - Number: 3, - Title: 'Try', - Released: new Date('04 Nov 2002'), - Genre: 'old emo-garage ', - Album: 'Dark matters' - }, - { - Number: 4, - Title: 'Miracle', - Released: new Date('05 Nov 2002'), - Genre: 'old emo-garage ', - Album: 'Dark matters' - }] + Number: 1, + Title: 'The Sun', + Released: new Date('31 Oct 2002'), + Genre: 'old emo-garage ', + Album: 'Dark matters' + }, + { + Number: 2, + Title: 'I will survive', + Released: new Date('03 Nov 2002'), + Genre: 'old emo-garage ', + Album: 'Dark matters' + }, + { + Number: 3, + Title: 'Try', + Released: new Date('04 Nov 2002'), + Genre: 'old emo-garage ', + Album: 'Dark matters' + }, + { + Number: 4, + Title: 'Miracle', + Released: new Date('05 Nov 2002'), + Genre: 'old emo-garage ', + Album: 'Dark matters' + }] } ] }, @@ -3336,47 +3346,47 @@ export class SampleTestData { USBillboard200: 5, Artist: 'Nguyễn Diệp Chi', Songs: [{ - Number: 1, - Title: 'Book of love', - Released: new Date('31 Dec 2003'), - Genre: 'Hip-hop', - Album: 'Library of liberty' - }, - { - Number: 2, - Title: 'Commitment', - Released: new Date('01 Jan 2004'), - Genre: 'Hip-hop', - Album: 'Library of liberty' - }, - { - Number: 3, - Title: 'Satisfaction', - Released: new Date('01 Jan 2004'), - Genre: 'Hip-hop', - Album: 'Library of liberty' - }, - { - Number: 4, - Title: 'Obsession', - Released: new Date('01 Jan 2004'), - Genre: 'Hip-hop', - Album: 'Library of liberty' - }, - { - Number: 5, - Title: 'Oblivion', - Released: new Date('02 Jan 2004'), - Genre: 'Hip-hop', - Album: 'Library of liberty' - }, - { - Number: 6, - Title: 'Energy', - Released: new Date('03 Jan 2004'), - Genre: 'Hip-hop', - Album: 'Library of liberty' - }] + Number: 1, + Title: 'Book of love', + Released: new Date('31 Dec 2003'), + Genre: 'Hip-hop', + Album: 'Library of liberty' + }, + { + Number: 2, + Title: 'Commitment', + Released: new Date('01 Jan 2004'), + Genre: 'Hip-hop', + Album: 'Library of liberty' + }, + { + Number: 3, + Title: 'Satisfaction', + Released: new Date('01 Jan 2004'), + Genre: 'Hip-hop', + Album: 'Library of liberty' + }, + { + Number: 4, + Title: 'Obsession', + Released: new Date('01 Jan 2004'), + Genre: 'Hip-hop', + Album: 'Library of liberty' + }, + { + Number: 5, + Title: 'Oblivion', + Released: new Date('02 Jan 2004'), + Genre: 'Hip-hop', + Album: 'Library of liberty' + }, + { + Number: 6, + Title: 'Energy', + Released: new Date('03 Jan 2004'), + Genre: 'Hip-hop', + Album: 'Library of liberty' + }] } ] }, @@ -3395,40 +3405,40 @@ export class SampleTestData { USBillboard200: 29, Artist: 'Eva Lee', Songs: [{ - Number: 1, - Title: 'We shall see', - Released: new Date('03 May 2001'), - Genre: 'rap-hop', - Album: 'Just a tease' - }, - { - Number: 2, - Title: 'Hopeless', - Released: new Date('04 May 2001'), - Genre: 'rap-hop', - Album: 'Just a tease' - }, - { - Number: 3, - Title: 'Ignorant', - Released: new Date('04 May 2001'), - Genre: 'rap-hop', - Album: 'Just a tease' - }, - { - Number: 4, - Title: 'Dance', - Released: new Date('05 May 2019'), - Genre: 'Metal', - Album: 'Just a tease' - }, - { - Number: 5, - Title: 'Fire', - Released: new Date('06 May 2019'), - Genre: 'Metal', - Album: 'Just a tease' - }] + Number: 1, + Title: 'We shall see', + Released: new Date('03 May 2001'), + Genre: 'rap-hop', + Album: 'Just a tease' + }, + { + Number: 2, + Title: 'Hopeless', + Released: new Date('04 May 2001'), + Genre: 'rap-hop', + Album: 'Just a tease' + }, + { + Number: 3, + Title: 'Ignorant', + Released: new Date('04 May 2001'), + Genre: 'rap-hop', + Album: 'Just a tease' + }, + { + Number: 4, + Title: 'Dance', + Released: new Date('05 May 2019'), + Genre: 'Metal', + Album: 'Just a tease' + }, + { + Number: 5, + Title: 'Fire', + Released: new Date('06 May 2019'), + Genre: 'Metal', + Album: 'Just a tease' + }] } ] }, @@ -3652,26 +3662,26 @@ export class SampleTestData { USBillboard200: 98, Artist: 'Pablo Cambeiro', Songs: [{ - Number: 1, - Title: 'Silence', - Released: new Date('25 Aug 2017'), - Genre: 'rap-hop', - Album: 'Fluke' - }, - { - Number: 2, - Title: 'Nothing matters anymore', - Released: new Date('25 Aug 2017'), - Genre: '*', - Album: 'Fluke' - }, - { - Number: 3, - Title: 'Everything wrong with me', - Released: new Date('25 Aug 2017'), - Genre: '*', - Album: 'Fluke' - }] + Number: 1, + Title: 'Silence', + Released: new Date('25 Aug 2017'), + Genre: 'rap-hop', + Album: 'Fluke' + }, + { + Number: 2, + Title: 'Nothing matters anymore', + Released: new Date('25 Aug 2017'), + Genre: '*', + Album: 'Fluke' + }, + { + Number: 3, + Title: 'Everything wrong with me', + Released: new Date('25 Aug 2017'), + Genre: '*', + Album: 'Fluke' + }] }, { Album: 'Crowd control', @@ -3680,69 +3690,70 @@ export class SampleTestData { USBillboard200: 84, Artist: 'Pablo Cambeiro', Songs: [{ - Number: 1, - Title: 'My Bed on My Mind', - Released: new Date('25 Mar 2019'), - Genre: 'ethno-tunes', - Album: 'Crowd control' - }, - { - Number: 2, - Title: 'Bright Blues', - Released: new Date('28 Sep 2019'), - Genre: 'neuro-tunes', - Album: 'Crowd control' - }, - { - Number: 3, - Title: 'Sail, Sail, Sail!', - Released: new Date('5 Mar 2019'), - Genre: '*', - Album: 'Crowd control' - }, - { - Number: 4, - Title: 'Hotel My Bed', - Released: new Date('22 Mar 2019'), - Genre: '*', - Album: 'Crowd control' - }, - { - Number: 5, - Title: 'Gonna Make You Mash', - Released: new Date('18 May 2019'), - Genre: '*', - Album: 'Crowd control' - }, - { - Number: 6, - Title: 'Straight Outta America', - Released: new Date('16 Jan 2020'), - Genre: 'hardcore opera', - Album: 'Crowd control' - }, - { - Number: 7, - Title: 'I Drive', - Released: new Date('23 Feb 2019'), - Genre: 'emotional C-jam ', - Album: 'Crowd control' - }, - { - Number: 8, - Title: 'Like a Teddy', - Released: new Date('31 Aug 2019'), - Genre: '*', - Album: 'Crowd control' - }, - { - Number: 9, - Title: 'Teddy Boogie', - Released: new Date('30 Nov 2019'), - Genre: '*', - Album: 'Crowd control' - }] - }] + Number: 1, + Title: 'My Bed on My Mind', + Released: new Date('25 Mar 2019'), + Genre: 'ethno-tunes', + Album: 'Crowd control' + }, + { + Number: 2, + Title: 'Bright Blues', + Released: new Date('28 Sep 2019'), + Genre: 'neuro-tunes', + Album: 'Crowd control' + }, + { + Number: 3, + Title: 'Sail, Sail, Sail!', + Released: new Date('5 Mar 2019'), + Genre: '*', + Album: 'Crowd control' + }, + { + Number: 4, + Title: 'Hotel My Bed', + Released: new Date('22 Mar 2019'), + Genre: '*', + Album: 'Crowd control' + }, + { + Number: 5, + Title: 'Gonna Make You Mash', + Released: new Date('18 May 2019'), + Genre: '*', + Album: 'Crowd control' + }, + { + Number: 6, + Title: 'Straight Outta America', + Released: new Date('16 Jan 2020'), + Genre: 'hardcore opera', + Album: 'Crowd control' + }, + { + Number: 7, + Title: 'I Drive', + Released: new Date('23 Feb 2019'), + Genre: 'emotional C-jam ', + Album: 'Crowd control' + }, + { + Number: 8, + Title: 'Like a Teddy', + Released: new Date('31 Aug 2019'), + Genre: '*', + Album: 'Crowd control' + }, + { + Number: 9, + Title: 'Teddy Boogie', + Released: new Date('30 Nov 2019'), + Genre: '*', + Album: 'Crowd control' + }] + } + ] }, { ID: 10, @@ -3759,33 +3770,33 @@ export class SampleTestData { USBillboard200: 77, Artist: 'Athar Malakooti', Songs: [{ - Number: 1, - Title: 'Actions', - Released: new Date('25 Feb 2016'), - Genre: 'ethno-tunes', - Album: 'Pushing up daisies' - }, - { - Number: 2, - Title: 'Blinding lights', - Released: new Date('28 Feb 2016'), - Genre: 'neuro-tunes', - Album: 'Pushing up daisies' - }, - { - Number: 3, - Title: 'I want more', - Released: new Date('5 Mar 2016'), - Genre: '*', - Album: 'Pushing up daisies' - }, - { - Number: 4, - Title: 'House by the lake', - Released: new Date('22 Mar 2016'), - Genre: '*', - Album: 'Pushing up daisies' - }] + Number: 1, + Title: 'Actions', + Released: new Date('25 Feb 2016'), + Genre: 'ethno-tunes', + Album: 'Pushing up daisies' + }, + { + Number: 2, + Title: 'Blinding lights', + Released: new Date('28 Feb 2016'), + Genre: 'neuro-tunes', + Album: 'Pushing up daisies' + }, + { + Number: 3, + Title: 'I want more', + Released: new Date('5 Mar 2016'), + Genre: '*', + Album: 'Pushing up daisies' + }, + { + Number: 4, + Title: 'House by the lake', + Released: new Date('22 Mar 2016'), + Genre: '*', + Album: 'Pushing up daisies' + }] } ] }, @@ -3810,7 +3821,8 @@ export class SampleTestData { Location: 'United States, Europe', Headliner: 'NO', TouredBy: 'Marti Valencia' - }], + } + ], Albums: [ { Album: 'Nemesis', @@ -3819,33 +3831,33 @@ export class SampleTestData { USBillboard200: 9, Artist: 'Marti Valencia', Songs: [{ - Number: 1, - Title: 'Love in motion', - Released: new Date('25 Jun 2004'), - Genre: 'ethno-tunes', - Album: 'Nemesis' - }, - { - Number: 2, - Title: 'The picture', - Released: new Date('28 Jun 2004'), - Genre: 'neuro-tunes', - Album: 'Nemesis' - }, - { - Number: 3, - Title: 'Flowers', - Released: new Date('5 Jul 2004'), - Genre: '*', - Album: 'Nemesis' - }, - { - Number: 4, - Title: 'Regret', - Released: new Date('22 Avg 2004'), - Genre: 'Heavy metal', - Album: 'Nemesis' - }] + Number: 1, + Title: 'Love in motion', + Released: new Date('25 Jun 2004'), + Genre: 'ethno-tunes', + Album: 'Nemesis' + }, + { + Number: 2, + Title: 'The picture', + Released: new Date('28 Jun 2004'), + Genre: 'neuro-tunes', + Album: 'Nemesis' + }, + { + Number: 3, + Title: 'Flowers', + Released: new Date('5 Jul 2004'), + Genre: '*', + Album: 'Nemesis' + }, + { + Number: 4, + Title: 'Regret', + Released: new Date('22 Avg 2004'), + Genre: 'Heavy metal', + Album: 'Nemesis' + }] }, { Album: 'First chance', @@ -3854,89 +3866,89 @@ export class SampleTestData { USBillboard200: 19, Artist: 'Marti Valencia', Songs: [{ - Number: 1, - Title: 'My Name is Jason', - Released: new Date('12 Jul 2019'), - Genre: '*', - Album: 'First chance' - }, - { - Number: 2, - Title: 'Amazing Andy', - Released: new Date('5 Mar 2019'), - Genre: '*', - Album: 'First chance' - }, - { - Number: 3, - Title: 'The Number of your Knight', - Released: new Date('4 Dec 2019'), - Genre: '*', - Album: 'First chance' - }, - { - Number: 4, - Title: 'I Sail', - Released: new Date('3 Mar 2019'), - Genre: '*', - Album: 'First chance' - }, - { - Number: 5, - Title: 'Goody Two Hands', - Released: new Date('11 Oct 2019'), - Genre: 'Electro house Electropop', - Album: 'First chance' - }, - { - Number: 6, - Title: 'Careful With That Knife', - Released: new Date('18 Dec 2019'), - Genre: 'R&B', - Album: 'First chance' - }, - { - Number: 7, - Title: 'Four Single Ants', - Released: new Date('18 Jan 2020'), - Genre: '*', - Album: 'First chance' - }, - { - Number: 8, - Title: 'Kiss Forever', - Released: new Date('10 Aug 2019'), - Genre: '*', - Album: 'First chance' - }, - { - Number: 9, - Title: 'Rich\'s Waiting', - Released: new Date('15 Mar 2019'), - Genre: 'Synth-pop R&B', - Album: 'First chance' - }, - { - Number: 10, - Title: 'Japan is Your Land', - Released: new Date('7 Mar 2019'), - Genre: 'ethno-tunes', - Album: 'First chance' - }, - { - Number: 11, - Title: 'Pencils in My Banana', - Released: new Date('21 Jun 2019'), - Genre: 'Crunk reggaeton', - Album: 'First chance' - }, - { - Number: 12, - Title: 'I Sail in Your Arms', - Released: new Date('30 Apr 2019'), - Genre: 'Synth-pop R&B', - Album: 'First chance' - }] + Number: 1, + Title: 'My Name is Jason', + Released: new Date('12 Jul 2019'), + Genre: '*', + Album: 'First chance' + }, + { + Number: 2, + Title: 'Amazing Andy', + Released: new Date('5 Mar 2019'), + Genre: '*', + Album: 'First chance' + }, + { + Number: 3, + Title: 'The Number of your Knight', + Released: new Date('4 Dec 2019'), + Genre: '*', + Album: 'First chance' + }, + { + Number: 4, + Title: 'I Sail', + Released: new Date('3 Mar 2019'), + Genre: '*', + Album: 'First chance' + }, + { + Number: 5, + Title: 'Goody Two Hands', + Released: new Date('11 Oct 2019'), + Genre: 'Electro house Electropop', + Album: 'First chance' + }, + { + Number: 6, + Title: 'Careful With That Knife', + Released: new Date('18 Dec 2019'), + Genre: 'R&B', + Album: 'First chance' + }, + { + Number: 7, + Title: 'Four Single Ants', + Released: new Date('18 Jan 2020'), + Genre: '*', + Album: 'First chance' + }, + { + Number: 8, + Title: 'Kiss Forever', + Released: new Date('10 Aug 2019'), + Genre: '*', + Album: 'First chance' + }, + { + Number: 9, + Title: 'Rich\'s Waiting', + Released: new Date('15 Mar 2019'), + Genre: 'Synth-pop R&B', + Album: 'First chance' + }, + { + Number: 10, + Title: 'Japan is Your Land', + Released: new Date('7 Mar 2019'), + Genre: 'ethno-tunes', + Album: 'First chance' + }, + { + Number: 11, + Title: 'Pencils in My Banana', + Released: new Date('21 Jun 2019'), + Genre: 'Crunk reggaeton', + Album: 'First chance' + }, + { + Number: 12, + Title: 'I Sail in Your Arms', + Released: new Date('30 Apr 2019'), + Genre: 'Synth-pop R&B', + Album: 'First chance' + }] }, { Album: 'God\'s advocate', @@ -3945,47 +3957,47 @@ export class SampleTestData { USBillboard200: 37, Artist: 'Marti Valencia', Songs: [{ - Number: 1, - Title: 'Destiny', - Released: new Date('07 May 2007'), - Genre: '*', - Album: 'God\'s advocate' - }, - { - Number: 2, - Title: 'I am the chosen one', - Released: new Date('08 May 2007'), - Genre: 'Heavy metal', - Album: 'God\'s advocate' - }, - { - Number: 3, - Title: 'New me', - Released: new Date('09 May 2007'), - Genre: 'Dance-pop R&B', - Album: 'God\'s advocate' - }, - { - Number: 4, - Title: 'Miss you', - Released: new Date('10 May 2007'), - Genre: 'Heavy metal', - Album: 'God\'s advocate' - }, - { - Number: 5, - Title: 'Turn back the time', - Released: new Date('21 May 2007'), - Genre: 'Dance-pop EDM', - Album: 'God\'s advocate' - }, - { - Number: 6, - Title: 'Let us have fun', - Released: new Date('01 Jun 2007'), - Genre: 'Dance-pop EDM', - Album: 'God\'s advocate' - }] + Number: 1, + Title: 'Destiny', + Released: new Date('07 May 2007'), + Genre: '*', + Album: 'God\'s advocate' + }, + { + Number: 2, + Title: 'I am the chosen one', + Released: new Date('08 May 2007'), + Genre: 'Heavy metal', + Album: 'God\'s advocate' + }, + { + Number: 3, + Title: 'New me', + Released: new Date('09 May 2007'), + Genre: 'Dance-pop R&B', + Album: 'God\'s advocate' + }, + { + Number: 4, + Title: 'Miss you', + Released: new Date('10 May 2007'), + Genre: 'Heavy metal', + Album: 'God\'s advocate' + }, + { + Number: 5, + Title: 'Turn back the time', + Released: new Date('21 May 2007'), + Genre: 'Dance-pop EDM', + Album: 'God\'s advocate' + }, + { + Number: 6, + Title: 'Let us have fun', + Released: new Date('01 Jun 2007'), + Genre: 'Dance-pop EDM', + Album: 'God\'s advocate' + }] } ] }, @@ -4004,33 +4016,33 @@ export class SampleTestData { USBillboard200: 7, Artist: 'Alicia Stanger', Songs: [{ - Number: 1, - Title: 'Brothers', - Released: new Date('25 Oct 2005'), - Genre: 'Hip-hop', - Album: 'Forever alone' - }, - { - Number: 2, - Title: 'Alone', - Released: new Date('28 Oct 2005'), - Genre: 'Heavy metal', - Album: 'Forever alone' - }, - { - Number: 3, - Title: 'I will go on', - Released: new Date('5 Nov 2005'), - Genre: 'Heavy metal', - Album: 'Forever alone' - }, - { - Number: 4, - Title: 'Horses', - Released: new Date('22 Dec 2005'), - Genre: '*', - Album: 'Forever alone' - }] + Number: 1, + Title: 'Brothers', + Released: new Date('25 Oct 2005'), + Genre: 'Hip-hop', + Album: 'Forever alone' + }, + { + Number: 2, + Title: 'Alone', + Released: new Date('28 Oct 2005'), + Genre: 'Heavy metal', + Album: 'Forever alone' + }, + { + Number: 3, + Title: 'I will go on', + Released: new Date('5 Nov 2005'), + Genre: 'Heavy metal', + Album: 'Forever alone' + }, + { + Number: 4, + Title: 'Horses', + Released: new Date('22 Dec 2005'), + Genre: '*', + Album: 'Forever alone' + }] } ] }, @@ -4093,33 +4105,33 @@ export class SampleTestData { USBillboard200: 35, Artist: 'Peter Taylor', Songs: [{ - Number: 1, - Title: 'Now that I am alone', - Released: new Date('25 Apr 2008'), - Genre: '*', - Album: 'Decisions decisions' - }, - { - Number: 2, - Title: 'Hopefully', - Released: new Date('26 Apr 2008'), - Genre: '*', - Album: 'Decisions decisions' - }, - { - Number: 3, - Title: 'Wonderful life', - Released: new Date('5 May 2008'), - Genre: '*', - Album: 'Decisions decisions' - }, - { - Number: 4, - Title: 'Amazing world', - Released: new Date('22 Dec 2008'), - Genre: '*', - Album: 'Decisions decisions' - }] + Number: 1, + Title: 'Now that I am alone', + Released: new Date('25 Apr 2008'), + Genre: '*', + Album: 'Decisions decisions' + }, + { + Number: 2, + Title: 'Hopefully', + Released: new Date('26 Apr 2008'), + Genre: '*', + Album: 'Decisions decisions' + }, + { + Number: 3, + Title: 'Wonderful life', + Released: new Date('5 May 2008'), + Genre: '*', + Album: 'Decisions decisions' + }, + { + Number: 4, + Title: 'Amazing world', + Released: new Date('22 Dec 2008'), + Genre: '*', + Album: 'Decisions decisions' + }] }, { Album: 'Climate changed', @@ -4128,536 +4140,536 @@ export class SampleTestData { USBillboard200: 89, Artist: 'Peter Taylor', Songs: [{ - Number: 1, - Title: 'This is how I am now', - Released: new Date('22 Jun 2015'), - Genre: 'Hip-hop', - Album: 'Climate changed' - }, - { - Number: 2, - Title: 'I feel', - Released: new Date('26 Jun 2015'), - Genre: 'rap-hop', - Album: 'Climate changed' - }, - { - Number: 3, - Title: 'Do I want to know', - Released: new Date('5 Jul 2015'), - Genre: 'rap-hop', - Album: 'Climate changed' - }, - { - Number: 4, - Title: 'Natural love', - Released: new Date('22 Jul 2015'), - Genre: '*', - Album: 'Climate changed' - }, - { - Number: 5, - Title: 'I will help', - Released: new Date('22 Jul 2015'), - Genre: '*', - Album: 'Climate changed' - }, - { - Number: 6, - Title: 'No matter what', - Released: new Date('22 Jul 2015'), - Genre: 'hip-hop', - Album: 'Climate changed' - }] + Number: 1, + Title: 'This is how I am now', + Released: new Date('22 Jun 2015'), + Genre: 'Hip-hop', + Album: 'Climate changed' + }, + { + Number: 2, + Title: 'I feel', + Released: new Date('26 Jun 2015'), + Genre: 'rap-hop', + Album: 'Climate changed' + }, + { + Number: 3, + Title: 'Do I want to know', + Released: new Date('5 Jul 2015'), + Genre: 'rap-hop', + Album: 'Climate changed' + }, + { + Number: 4, + Title: 'Natural love', + Released: new Date('22 Jul 2015'), + Genre: '*', + Album: 'Climate changed' + }, + { + Number: 5, + Title: 'I will help', + Released: new Date('22 Jul 2015'), + Genre: '*', + Album: 'Climate changed' + }, + { + Number: 6, + Title: 'No matter what', + Released: new Date('22 Jul 2015'), + Genre: 'hip-hop', + Album: 'Climate changed' + }] } ] } ]); public static gridProductData = () => [{ - ProductID: 1, - ProductName: "Chai", - SupplierID: 1, - CategoryID: 1, - QuantityPerUnit: "10 boxes x 20 bags", - UnitPrice: 18.0000, - UnitsInStock: 39, - UnitsOnOrder: 30, - ReorderLevel: 10, - Discontinued: false, - OrderDate: new Date("2012-02-12") - }, { - ProductID: 2, - ProductName: "Chang", - SupplierID: 1, - CategoryID: 1, - QuantityPerUnit: "24 - 12 oz bottles", - UnitPrice: 19.0000, - UnitsInStock: 17, - UnitsOnOrder: 40, - ReorderLevel: 25, - Discontinued: true, - OrderDate: new Date("2003-03-17") - }, { - ProductID: 3, - ProductName: "Aniseed Syrup", - SupplierID: 1, - CategoryID: 2, - QuantityPerUnit: "12 - 550 ml bottles", - UnitPrice: 10.0000, - UnitsInStock: 13, - UnitsOnOrder: 70, - ReorderLevel: 25, - Discontinued: false, - OrderDate: new Date("2006-03-17") - }, { - ProductID: 4, - ProductName: "Chef Antons Cajun Seasoning", - SupplierID: 2, - CategoryID: 2, - QuantityPerUnit: "48 - 6 oz jars", - UnitPrice: 22.0000, - UnitsInStock: 53, - UnitsOnOrder: 30, - ReorderLevel: 0, - Discontinued: false, - OrderDate: new Date("2016-03-17") - }, { - ProductID: 5, - ProductName: "Chef Antons Gumbo Mix", - SupplierID: 2, - CategoryID: 2, - QuantityPerUnit: "36 boxes", - UnitPrice: 21.3500, - UnitsInStock: 0, - UnitsOnOrder: 30, - ReorderLevel: 0, - Discontinued: true, - OrderDate: new Date("2011-11-11") - }, { - ProductID: 6, - ProductName: "Grandmas Boysenberry Spread", - SupplierID: 3, - CategoryID: 2, - QuantityPerUnit: "12 - 8 oz jars", - UnitPrice: 25.0000, - UnitsInStock: 0, - UnitsOnOrder: 30, - ReorderLevel: 25, - Discontinued: false, - OrderDate: new Date("2017-12-17") - }, { - ProductID: 7, - ProductName: "Uncle Bobs Organic Dried Pears", - SupplierID: 3, - CategoryID: 7, - QuantityPerUnit: "12 - 1 lb pkgs.", - UnitPrice: 30.0000, - UnitsInStock: 150, - UnitsOnOrder: 30, - ReorderLevel: 10, - Discontinued: false, - OrderDate: new Date("2016-07-17") - }, { - ProductID: 8, - ProductName: "Northwoods Cranberry Sauce", - SupplierID: 3, - CategoryID: 2, - QuantityPerUnit: "12 - 12 oz jars", - UnitPrice: 40.0000, - UnitsInStock: 6, - UnitsOnOrder: 30, - ReorderLevel: 0, - Discontinued: false, - OrderDate: new Date("2018-01-17") - }, { - ProductID: 9, - ProductName: "Mishi Kobe Niku", - SupplierID: 4, - CategoryID: 6, - QuantityPerUnit: "18 - 500 g pkgs.", - UnitPrice: 97.0000, - UnitsInStock: 29, - UnitsOnOrder: 30, - ReorderLevel: 0, - Discontinued: true, - OrderDate: new Date("2010-02-17") - }, { - ProductID: 10, - ProductName: "Ikura", - SupplierID: 4, - CategoryID: 8, - QuantityPerUnit: "12 - 200 ml jars", - UnitPrice: 31.0000, - UnitsInStock: 31, - UnitsOnOrder: 30, - ReorderLevel: 0, - Discontinued: false, - OrderDate: new Date("2008-05-17") - }, { - ProductID: 11, - ProductName: "Queso Cabrales", - SupplierID: 5, - CategoryID: 4, - QuantityPerUnit: "1 kg pkg.", - UnitPrice: 21.0000, - UnitsInStock: 22, - UnitsOnOrder: 30, - ReorderLevel: 30, - Discontinued: false, - OrderDate: new Date("2009-01-17") - }, { - ProductID: 12, - ProductName: "Queso Manchego La Pastora", - SupplierID: 5, - CategoryID: 4, - QuantityPerUnit: "10 - 500 g pkgs.", - UnitPrice: 38.0000, - UnitsInStock: 86, - UnitsOnOrder: 30, - ReorderLevel: 0, - Discontinued: false, - OrderDate: new Date("2015-11-17") - }, { - ProductID: 13, - ProductName: "Konbu", - SupplierID: 6, - CategoryID: 8, - QuantityPerUnit: "2 kg box", - UnitPrice: 6.0000, - UnitsInStock: 24, - UnitsOnOrder: 30, - ReorderLevel: 5, - Discontinued: false, - OrderDate: new Date("2015-03-17") - }, { - ProductID: 14, - ProductName: "Tofu", - SupplierID: 6, - CategoryID: 7, - QuantityPerUnit: "40 - 100 g pkgs.", - UnitPrice: 23.2500, - UnitsInStock: 35, - UnitsOnOrder: 30, - ReorderLevel: 0, - Discontinued: false, - OrderDate: new Date("2017-06-17") - }, { - ProductID: 15, - ProductName: "Genen Shouyu", - SupplierID: 6, - CategoryID: 2, - QuantityPerUnit: "24 - 250 ml bottles", - UnitPrice: 15.5000, - UnitsInStock: 39, - UnitsOnOrder: 30, - ReorderLevel: 5, - Discontinued: false, - OrderDate: new Date("2014-03-17") - }, { - ProductID: 16, - ProductName: "Pavlova", - SupplierID: 7, - CategoryID: 3, - QuantityPerUnit: "32 - 500 g boxes", - UnitPrice: 17.4500, - UnitsInStock: 29, - UnitsOnOrder: 30, - ReorderLevel: 10, - Discontinued: false, - OrderDate: new Date("2018-03-28") - }, { - ProductID: 17, - ProductName: "Alice Mutton", - SupplierID: 7, - CategoryID: 6, - QuantityPerUnit: "20 - 1 kg tins", - UnitPrice: 39.0000, - UnitsInStock: 0, - UnitsOnOrder: 30, - ReorderLevel: 0, - Discontinued: true, - OrderDate: new Date("2015-08-17") - }, { - ProductID: 18, - ProductName: "Carnarvon Tigers", - SupplierID: 7, - CategoryID: 8, - QuantityPerUnit: "16 kg pkg.", - UnitPrice: 62.5000, - UnitsInStock: 42, - UnitsOnOrder: 30, - ReorderLevel: 0, - Discontinued: false, - OrderDate: new Date("2005-09-27") - }, { - ProductID: 19, - ProductName: "Teatime Chocolate Biscuits", - SupplierID: 8, - CategoryID: 3, - QuantityPerUnit: "", - UnitPrice: 9.2000, - UnitsInStock: 25, - UnitsOnOrder: 30, - ReorderLevel: 5, - Discontinued: false, - OrderDate: new Date("2001-03-17") - }, { - ProductID: 20, - ProductName: "Sir Rodneys Marmalade", - SupplierID: 8, - CategoryID: 3, - QuantityPerUnit: undefined, - UnitPrice: 4.5, - UnitsInStock: 40, - UnitsOnOrder: 30, - ReorderLevel: 0, - Discontinued: false, - OrderDate: new Date("2005-03-17") - } + ProductID: 1, + ProductName: "Chai", + SupplierID: 1, + CategoryID: 1, + QuantityPerUnit: "10 boxes x 20 bags", + UnitPrice: 18.0000, + UnitsInStock: 39, + UnitsOnOrder: 30, + ReorderLevel: 10, + Discontinued: false, + OrderDate: new Date("2012-02-12") + }, { + ProductID: 2, + ProductName: "Chang", + SupplierID: 1, + CategoryID: 1, + QuantityPerUnit: "24 - 12 oz bottles", + UnitPrice: 19.0000, + UnitsInStock: 17, + UnitsOnOrder: 40, + ReorderLevel: 25, + Discontinued: true, + OrderDate: new Date("2003-03-17") + }, { + ProductID: 3, + ProductName: "Aniseed Syrup", + SupplierID: 1, + CategoryID: 2, + QuantityPerUnit: "12 - 550 ml bottles", + UnitPrice: 10.0000, + UnitsInStock: 13, + UnitsOnOrder: 70, + ReorderLevel: 25, + Discontinued: false, + OrderDate: new Date("2006-03-17") + }, { + ProductID: 4, + ProductName: "Chef Antons Cajun Seasoning", + SupplierID: 2, + CategoryID: 2, + QuantityPerUnit: "48 - 6 oz jars", + UnitPrice: 22.0000, + UnitsInStock: 53, + UnitsOnOrder: 30, + ReorderLevel: 0, + Discontinued: false, + OrderDate: new Date("2016-03-17") + }, { + ProductID: 5, + ProductName: "Chef Antons Gumbo Mix", + SupplierID: 2, + CategoryID: 2, + QuantityPerUnit: "36 boxes", + UnitPrice: 21.3500, + UnitsInStock: 0, + UnitsOnOrder: 30, + ReorderLevel: 0, + Discontinued: true, + OrderDate: new Date("2011-11-11") + }, { + ProductID: 6, + ProductName: "Grandmas Boysenberry Spread", + SupplierID: 3, + CategoryID: 2, + QuantityPerUnit: "12 - 8 oz jars", + UnitPrice: 25.0000, + UnitsInStock: 0, + UnitsOnOrder: 30, + ReorderLevel: 25, + Discontinued: false, + OrderDate: new Date("2017-12-17") + }, { + ProductID: 7, + ProductName: "Uncle Bobs Organic Dried Pears", + SupplierID: 3, + CategoryID: 7, + QuantityPerUnit: "12 - 1 lb pkgs.", + UnitPrice: 30.0000, + UnitsInStock: 150, + UnitsOnOrder: 30, + ReorderLevel: 10, + Discontinued: false, + OrderDate: new Date("2016-07-17") + }, { + ProductID: 8, + ProductName: "Northwoods Cranberry Sauce", + SupplierID: 3, + CategoryID: 2, + QuantityPerUnit: "12 - 12 oz jars", + UnitPrice: 40.0000, + UnitsInStock: 6, + UnitsOnOrder: 30, + ReorderLevel: 0, + Discontinued: false, + OrderDate: new Date("2018-01-17") + }, { + ProductID: 9, + ProductName: "Mishi Kobe Niku", + SupplierID: 4, + CategoryID: 6, + QuantityPerUnit: "18 - 500 g pkgs.", + UnitPrice: 97.0000, + UnitsInStock: 29, + UnitsOnOrder: 30, + ReorderLevel: 0, + Discontinued: true, + OrderDate: new Date("2010-02-17") + }, { + ProductID: 10, + ProductName: "Ikura", + SupplierID: 4, + CategoryID: 8, + QuantityPerUnit: "12 - 200 ml jars", + UnitPrice: 31.0000, + UnitsInStock: 31, + UnitsOnOrder: 30, + ReorderLevel: 0, + Discontinued: false, + OrderDate: new Date("2008-05-17") + }, { + ProductID: 11, + ProductName: "Queso Cabrales", + SupplierID: 5, + CategoryID: 4, + QuantityPerUnit: "1 kg pkg.", + UnitPrice: 21.0000, + UnitsInStock: 22, + UnitsOnOrder: 30, + ReorderLevel: 30, + Discontinued: false, + OrderDate: new Date("2009-01-17") + }, { + ProductID: 12, + ProductName: "Queso Manchego La Pastora", + SupplierID: 5, + CategoryID: 4, + QuantityPerUnit: "10 - 500 g pkgs.", + UnitPrice: 38.0000, + UnitsInStock: 86, + UnitsOnOrder: 30, + ReorderLevel: 0, + Discontinued: false, + OrderDate: new Date("2015-11-17") + }, { + ProductID: 13, + ProductName: "Konbu", + SupplierID: 6, + CategoryID: 8, + QuantityPerUnit: "2 kg box", + UnitPrice: 6.0000, + UnitsInStock: 24, + UnitsOnOrder: 30, + ReorderLevel: 5, + Discontinued: false, + OrderDate: new Date("2015-03-17") + }, { + ProductID: 14, + ProductName: "Tofu", + SupplierID: 6, + CategoryID: 7, + QuantityPerUnit: "40 - 100 g pkgs.", + UnitPrice: 23.2500, + UnitsInStock: 35, + UnitsOnOrder: 30, + ReorderLevel: 0, + Discontinued: false, + OrderDate: new Date("2017-06-17") + }, { + ProductID: 15, + ProductName: "Genen Shouyu", + SupplierID: 6, + CategoryID: 2, + QuantityPerUnit: "24 - 250 ml bottles", + UnitPrice: 15.5000, + UnitsInStock: 39, + UnitsOnOrder: 30, + ReorderLevel: 5, + Discontinued: false, + OrderDate: new Date("2014-03-17") + }, { + ProductID: 16, + ProductName: "Pavlova", + SupplierID: 7, + CategoryID: 3, + QuantityPerUnit: "32 - 500 g boxes", + UnitPrice: 17.4500, + UnitsInStock: 29, + UnitsOnOrder: 30, + ReorderLevel: 10, + Discontinued: false, + OrderDate: new Date("2018-03-28") + }, { + ProductID: 17, + ProductName: "Alice Mutton", + SupplierID: 7, + CategoryID: 6, + QuantityPerUnit: "20 - 1 kg tins", + UnitPrice: 39.0000, + UnitsInStock: 0, + UnitsOnOrder: 30, + ReorderLevel: 0, + Discontinued: true, + OrderDate: new Date("2015-08-17") + }, { + ProductID: 18, + ProductName: "Carnarvon Tigers", + SupplierID: 7, + CategoryID: 8, + QuantityPerUnit: "16 kg pkg.", + UnitPrice: 62.5000, + UnitsInStock: 42, + UnitsOnOrder: 30, + ReorderLevel: 0, + Discontinued: false, + OrderDate: new Date("2005-09-27") + }, { + ProductID: 19, + ProductName: "Teatime Chocolate Biscuits", + SupplierID: 8, + CategoryID: 3, + QuantityPerUnit: "", + UnitPrice: 9.2000, + UnitsInStock: 25, + UnitsOnOrder: 30, + ReorderLevel: 5, + Discontinued: false, + OrderDate: new Date("2001-03-17") + }, { + ProductID: 20, + ProductName: "Sir Rodneys Marmalade", + SupplierID: 8, + CategoryID: 3, + QuantityPerUnit: undefined, + UnitPrice: 4.5, + UnitsInStock: 40, + UnitsOnOrder: 30, + ReorderLevel: 0, + Discontinued: false, + OrderDate: new Date("2005-03-17") + } ]; public static gridCustomSummaryData = () => [{ - ProductID: 1, - ProductName: "Chai", - SupplierID: 1, - CategoryID: 1, - QuantityPerUnit: "10 boxes x 20 bags", - UnitPrice: 18.0000, - UnitsInStock: 39, - UnitsOnOrder: 30, - ReorderLevel: 10, - Discontinued: false, - OrderDate: new Date("2012-02-12") - }, { - ProductID: 2, - ProductName: "Chang", - SupplierID: 1, - CategoryID: 1, - QuantityPerUnit: "24 - 12 oz bottles", - UnitPrice: 19.0000, - UnitsInStock: 17, - UnitsOnOrder: 40, - ReorderLevel: 25, - Discontinued: true, - OrderDate: new Date("2003-03-17") - }, { - ProductID: 3, - ProductName: "Aniseed Syrup", - SupplierID: 1, - CategoryID: 2, - QuantityPerUnit: "12 - 550 ml bottles", - UnitPrice: 10.0000, - UnitsInStock: 13, - UnitsOnOrder: 70, - ReorderLevel: 25, - Discontinued: false, - OrderDate: new Date("2006-03-17") - }, { - ProductID: 4, - ProductName: "Chef Antons Cajun Seasoning", - SupplierID: 2, - CategoryID: 2, - QuantityPerUnit: "48 - 6 oz jars", - UnitPrice: 22.0000, - UnitsInStock: 53, - UnitsOnOrder: 30, - ReorderLevel: 0, - Discontinued: false, - OrderDate: new Date("2016-03-17") - }, { - ProductID: 5, - ProductName: "Chef Antons Gumbo Mix", - SupplierID: 2, - CategoryID: 2, - QuantityPerUnit: "36 boxes", - UnitPrice: 21.3500, - UnitsInStock: 0, - UnitsOnOrder: 30, - ReorderLevel: 0, - Discontinued: true, - OrderDate: new Date("2011-11-11") - }, { - ProductID: 6, - ProductName: "Grandmas Boysenberry Spread", - SupplierID: 3, - CategoryID: 2, - QuantityPerUnit: "12 - 8 oz jars", - UnitPrice: 25.0000, - UnitsInStock: 0, - UnitsOnOrder: 30, - ReorderLevel: 25, - Discontinued: false, - OrderDate: new Date("2017-12-17") - }, { - ProductID: 7, - ProductName: "Uncle Bobs Organic Dried Pears", - SupplierID: 3, - CategoryID: 7, - QuantityPerUnit: "12 - 1 lb pkgs.", - UnitPrice: 30.0000, - UnitsInStock: 150, - UnitsOnOrder: 30, - ReorderLevel: 10, - Discontinued: false, - OrderDate: new Date("2016-07-17") - }, { - ProductID: 8, - ProductName: "Northwoods Cranberry Sauce", - SupplierID: 3, - CategoryID: 2, - QuantityPerUnit: "12 - 12 oz jars", - UnitPrice: 40.0000, - UnitsInStock: 6, - UnitsOnOrder: 30, - ReorderLevel: 0, - Discontinued: false, - OrderDate: new Date("2018-01-17") - }, { - ProductID: 9, - ProductName: "Mishi Kobe Niku", - SupplierID: 4, - CategoryID: 6, - QuantityPerUnit: "18 - 500 g pkgs.", - UnitPrice: 97.0000, - UnitsInStock: 29, - UnitsOnOrder: 30, - ReorderLevel: 0, - Discontinued: true, - OrderDate: new Date("2010-02-17") - }, { - ProductID: 10, - ProductName: "Ikura", - SupplierID: 4, - CategoryID: 8, - QuantityPerUnit: "12 - 200 ml jars", - UnitPrice: 31.0000, - UnitsInStock: 31, - UnitsOnOrder: 30, - ReorderLevel: 0, - Discontinued: false, - OrderDate: new Date("2008-05-17") - }, { - ProductID: 11, - ProductName: "Queso Cabrales", - SupplierID: 5, - CategoryID: 4, - QuantityPerUnit: "1 kg pkg.", - UnitPrice: 21.0000, - UnitsInStock: 22, - UnitsOnOrder: 30, - ReorderLevel: 30, - Discontinued: false, - OrderDate: new Date("2009-01-17") - }, { - ProductID: 12, - ProductName: "Queso Manchego La Pastora", - SupplierID: 5, - CategoryID: 4, - QuantityPerUnit: "10 - 500 g pkgs.", - UnitPrice: 38.0000, - UnitsInStock: 86, - UnitsOnOrder: 30, - ReorderLevel: 0, - Discontinued: false, - OrderDate: new Date("2015-11-17") - }, { - ProductID: 13, - ProductName: "Konbu", - SupplierID: 6, - CategoryID: 8, - QuantityPerUnit: "2 kg box", - UnitPrice: 6.0000, - UnitsInStock: 24, - UnitsOnOrder: 30, - ReorderLevel: 5, - Discontinued: false, - OrderDate: new Date("2015-03-17") - }, { - ProductID: 14, - ProductName: "Tofu", - SupplierID: 6, - CategoryID: 7, - QuantityPerUnit: "40 - 100 g pkgs.", - UnitPrice: 23.2500, - UnitsInStock: 35, - UnitsOnOrder: 30, - ReorderLevel: 0, - Discontinued: false, - OrderDate: new Date("2017-06-17") - }, { - ProductID: 15, - ProductName: "Genen Shouyu", - SupplierID: 6, - CategoryID: 2, - QuantityPerUnit: "24 - 250 ml bottles", - UnitPrice: 15.5000, - UnitsInStock: 39, - UnitsOnOrder: 30, - ReorderLevel: 5, - Discontinued: false, - OrderDate: new Date("2014-03-17") - }, { - ProductID: 16, - ProductName: "Pavlova", - SupplierID: 7, - CategoryID: 3, - QuantityPerUnit: "32 - 500 g boxes", - UnitPrice: 17.4500, - UnitsInStock: 29, - UnitsOnOrder: 30, - ReorderLevel: 10, - Discontinued: false, - OrderDate: new Date("2018-03-28") - }, { - ProductID: 17, - ProductName: "Alice Mutton", - SupplierID: 7, - CategoryID: 6, - QuantityPerUnit: "20 - 1 kg tins", - UnitPrice: 39.0000, - UnitsInStock: 0, - UnitsOnOrder: 30, - ReorderLevel: 0, - Discontinued: true, - OrderDate: new Date("2015-08-17") - }, { - ProductID: 18, - ProductName: "Carnarvon Tigers", - SupplierID: 7, - CategoryID: 8, - QuantityPerUnit: "16 kg pkg.", - UnitPrice: 62.5000, - UnitsInStock: 42, - UnitsOnOrder: 30, - ReorderLevel: 0, - Discontinued: false, - OrderDate: new Date("2005-09-27") - }, { - ProductID: 19, - ProductName: "Teatime Chocolate Biscuits", - SupplierID: 8, - CategoryID: 3, - QuantityPerUnit: "", - UnitPrice: 9.2000, - UnitsInStock: 25, - UnitsOnOrder: 30, - ReorderLevel: 5, - Discontinued: false, - OrderDate: new Date("2001-03-17") - }, { - ProductID: 20, - ProductName: "Sir Rodneys Marmalade", - SupplierID: 8, - CategoryID: 3, - QuantityPerUnit: undefined, - UnitPrice: 4.5, - UnitsInStock: 40, - UnitsOnOrder: 30, - ReorderLevel: 0, - Discontinued: false, - OrderDate: new Date("2005-03-17") - } + ProductID: 1, + ProductName: "Chai", + SupplierID: 1, + CategoryID: 1, + QuantityPerUnit: "10 boxes x 20 bags", + UnitPrice: 18.0000, + UnitsInStock: 39, + UnitsOnOrder: 30, + ReorderLevel: 10, + Discontinued: false, + OrderDate: new Date("2012-02-12") + }, { + ProductID: 2, + ProductName: "Chang", + SupplierID: 1, + CategoryID: 1, + QuantityPerUnit: "24 - 12 oz bottles", + UnitPrice: 19.0000, + UnitsInStock: 17, + UnitsOnOrder: 40, + ReorderLevel: 25, + Discontinued: true, + OrderDate: new Date("2003-03-17") + }, { + ProductID: 3, + ProductName: "Aniseed Syrup", + SupplierID: 1, + CategoryID: 2, + QuantityPerUnit: "12 - 550 ml bottles", + UnitPrice: 10.0000, + UnitsInStock: 13, + UnitsOnOrder: 70, + ReorderLevel: 25, + Discontinued: false, + OrderDate: new Date("2006-03-17") + }, { + ProductID: 4, + ProductName: "Chef Antons Cajun Seasoning", + SupplierID: 2, + CategoryID: 2, + QuantityPerUnit: "48 - 6 oz jars", + UnitPrice: 22.0000, + UnitsInStock: 53, + UnitsOnOrder: 30, + ReorderLevel: 0, + Discontinued: false, + OrderDate: new Date("2016-03-17") + }, { + ProductID: 5, + ProductName: "Chef Antons Gumbo Mix", + SupplierID: 2, + CategoryID: 2, + QuantityPerUnit: "36 boxes", + UnitPrice: 21.3500, + UnitsInStock: 0, + UnitsOnOrder: 30, + ReorderLevel: 0, + Discontinued: true, + OrderDate: new Date("2011-11-11") + }, { + ProductID: 6, + ProductName: "Grandmas Boysenberry Spread", + SupplierID: 3, + CategoryID: 2, + QuantityPerUnit: "12 - 8 oz jars", + UnitPrice: 25.0000, + UnitsInStock: 0, + UnitsOnOrder: 30, + ReorderLevel: 25, + Discontinued: false, + OrderDate: new Date("2017-12-17") + }, { + ProductID: 7, + ProductName: "Uncle Bobs Organic Dried Pears", + SupplierID: 3, + CategoryID: 7, + QuantityPerUnit: "12 - 1 lb pkgs.", + UnitPrice: 30.0000, + UnitsInStock: 150, + UnitsOnOrder: 30, + ReorderLevel: 10, + Discontinued: false, + OrderDate: new Date("2016-07-17") + }, { + ProductID: 8, + ProductName: "Northwoods Cranberry Sauce", + SupplierID: 3, + CategoryID: 2, + QuantityPerUnit: "12 - 12 oz jars", + UnitPrice: 40.0000, + UnitsInStock: 6, + UnitsOnOrder: 30, + ReorderLevel: 0, + Discontinued: false, + OrderDate: new Date("2018-01-17") + }, { + ProductID: 9, + ProductName: "Mishi Kobe Niku", + SupplierID: 4, + CategoryID: 6, + QuantityPerUnit: "18 - 500 g pkgs.", + UnitPrice: 97.0000, + UnitsInStock: 29, + UnitsOnOrder: 30, + ReorderLevel: 0, + Discontinued: true, + OrderDate: new Date("2010-02-17") + }, { + ProductID: 10, + ProductName: "Ikura", + SupplierID: 4, + CategoryID: 8, + QuantityPerUnit: "12 - 200 ml jars", + UnitPrice: 31.0000, + UnitsInStock: 31, + UnitsOnOrder: 30, + ReorderLevel: 0, + Discontinued: false, + OrderDate: new Date("2008-05-17") + }, { + ProductID: 11, + ProductName: "Queso Cabrales", + SupplierID: 5, + CategoryID: 4, + QuantityPerUnit: "1 kg pkg.", + UnitPrice: 21.0000, + UnitsInStock: 22, + UnitsOnOrder: 30, + ReorderLevel: 30, + Discontinued: false, + OrderDate: new Date("2009-01-17") + }, { + ProductID: 12, + ProductName: "Queso Manchego La Pastora", + SupplierID: 5, + CategoryID: 4, + QuantityPerUnit: "10 - 500 g pkgs.", + UnitPrice: 38.0000, + UnitsInStock: 86, + UnitsOnOrder: 30, + ReorderLevel: 0, + Discontinued: false, + OrderDate: new Date("2015-11-17") + }, { + ProductID: 13, + ProductName: "Konbu", + SupplierID: 6, + CategoryID: 8, + QuantityPerUnit: "2 kg box", + UnitPrice: 6.0000, + UnitsInStock: 24, + UnitsOnOrder: 30, + ReorderLevel: 5, + Discontinued: false, + OrderDate: new Date("2015-03-17") + }, { + ProductID: 14, + ProductName: "Tofu", + SupplierID: 6, + CategoryID: 7, + QuantityPerUnit: "40 - 100 g pkgs.", + UnitPrice: 23.2500, + UnitsInStock: 35, + UnitsOnOrder: 30, + ReorderLevel: 0, + Discontinued: false, + OrderDate: new Date("2017-06-17") + }, { + ProductID: 15, + ProductName: "Genen Shouyu", + SupplierID: 6, + CategoryID: 2, + QuantityPerUnit: "24 - 250 ml bottles", + UnitPrice: 15.5000, + UnitsInStock: 39, + UnitsOnOrder: 30, + ReorderLevel: 5, + Discontinued: false, + OrderDate: new Date("2014-03-17") + }, { + ProductID: 16, + ProductName: "Pavlova", + SupplierID: 7, + CategoryID: 3, + QuantityPerUnit: "32 - 500 g boxes", + UnitPrice: 17.4500, + UnitsInStock: 29, + UnitsOnOrder: 30, + ReorderLevel: 10, + Discontinued: false, + OrderDate: new Date("2018-03-28") + }, { + ProductID: 17, + ProductName: "Alice Mutton", + SupplierID: 7, + CategoryID: 6, + QuantityPerUnit: "20 - 1 kg tins", + UnitPrice: 39.0000, + UnitsInStock: 0, + UnitsOnOrder: 30, + ReorderLevel: 0, + Discontinued: true, + OrderDate: new Date("2015-08-17") + }, { + ProductID: 18, + ProductName: "Carnarvon Tigers", + SupplierID: 7, + CategoryID: 8, + QuantityPerUnit: "16 kg pkg.", + UnitPrice: 62.5000, + UnitsInStock: 42, + UnitsOnOrder: 30, + ReorderLevel: 0, + Discontinued: false, + OrderDate: new Date("2005-09-27") + }, { + ProductID: 19, + ProductName: "Teatime Chocolate Biscuits", + SupplierID: 8, + CategoryID: 3, + QuantityPerUnit: "", + UnitPrice: 9.2000, + UnitsInStock: 25, + UnitsOnOrder: 30, + ReorderLevel: 5, + Discontinued: false, + OrderDate: new Date("2001-03-17") + }, { + ProductID: 20, + ProductName: "Sir Rodneys Marmalade", + SupplierID: 8, + CategoryID: 3, + QuantityPerUnit: undefined, + UnitPrice: 4.5, + UnitsInStock: 40, + UnitsOnOrder: 30, + ReorderLevel: 0, + Discontinued: false, + OrderDate: new Date("2005-03-17") + } ]; /** @@ -4687,12 +4699,13 @@ export class SampleTestData { let children; for (let i = 0; i < count; i++) { const rowID = parendID ? parendID + i : i.toString(); - if (level > 0 ) { - children = this.generateHGridData(count / 2 , currLevel - 1, rowID); - } - prods.push({ - ID: rowID, ChildLevels: currLevel, ProductName: 'Product: A' + i, Col1: i, - Col2: i, Col3: i, childData: children, childData2: children }); + if (level > 0) { + children = this.generateHGridData(count / 2, currLevel - 1, rowID); + } + prods.push({ + ID: rowID, ChildLevels: currLevel, ProductName: 'Product: A' + i, Col1: i, + Col2: i, Col3: i, childData: children, childData2: children + }); } return prods; } diff --git a/projects/igniteui-angular/test-utils/tabs-components.spec.ts b/projects/igniteui-angular/test-utils/tabs-components.spec.ts index 376b65c2313..1e3bd114a01 100644 --- a/projects/igniteui-angular/test-utils/tabs-components.spec.ts +++ b/projects/igniteui-angular/test-utils/tabs-components.spec.ts @@ -42,8 +42,10 @@ import { IgxPrefixDirective, IgxSuffixDirective } from 'igniteui-angular/input-g imports: [IgxTabsComponent, IgxTabItemComponent, IgxTabHeaderComponent, IgxTabContentComponent] }) export class BasicTabsComponent { - @ViewChild(IgxTabsComponent, { static: true }) public tabs: IgxTabsComponent; - @ViewChildren(IgxTabItemComponent) public tabItems: QueryList; + @ViewChild(IgxTabsComponent, { static: true }) + public tabs: IgxTabsComponent; + @ViewChildren(IgxTabItemComponent) + public tabItems: QueryList; } @Component({ @@ -89,8 +91,10 @@ export class BasicTabsComponent { imports: [IgxTabsComponent, IgxTabItemComponent, IgxTabHeaderComponent, IgxTabContentComponent, IgxIconComponent, IgxTabHeaderIconDirective, IgxTabHeaderLabelDirective] }) export class TabsTestComponent { - @ViewChild(IgxTabsComponent, { static: true }) public tabs: IgxTabsComponent; - @ViewChild('wrapperDiv', { static: true }) public wrapperDiv: any; + @ViewChild(IgxTabsComponent, { static: true }) + public tabs: IgxTabsComponent; + @ViewChild('wrapperDiv', { static: true }) + public wrapperDiv: any; } @Component({ @@ -109,8 +113,10 @@ export class TabsTestComponent { imports: [IgxTabsComponent, IgxTabItemComponent, IgxTabHeaderComponent, IgxTabContentComponent, IgxTabHeaderLabelDirective] }) export class TabsTest2Component { - @ViewChild(IgxTabsComponent, { static: true }) public tabs: IgxTabsComponent; - @ViewChild('wrapperDiv', { static: true }) public wrapperDiv: any; + @ViewChild(IgxTabsComponent, { static: true }) + public tabs: IgxTabsComponent; + @ViewChild('wrapperDiv', { static: true }) + public wrapperDiv: any; protected collection: any[]; constructor() { @@ -192,8 +198,10 @@ export class TabsTest2Component { imports: [IgxTabsComponent, IgxTabItemComponent, IgxTabHeaderComponent, IgxTabContentComponent, IgxTabHeaderLabelDirective] }) export class TemplatedTabsTestComponent { - @ViewChild(IgxTabsComponent, { static: true }) public tabs: IgxTabsComponent; - @ViewChild('wrapperDiv', { static: true }) public wrapperDiv: any; + @ViewChild(IgxTabsComponent, { static: true }) + public tabs: IgxTabsComponent; + @ViewChild('wrapperDiv', { static: true }) + public wrapperDiv: any; } @Component({ @@ -211,7 +219,8 @@ export class TemplatedTabsTestComponent { imports: [IgxTabsComponent, IgxTabItemComponent, IgxTabHeaderComponent, IgxTabHeaderLabelDirective] }) export class TabsTestSelectedTabComponent { - @ViewChild(IgxTabsComponent, { static: true }) public tabs: IgxTabsComponent; + @ViewChild(IgxTabsComponent, { static: true }) + public tabs: IgxTabsComponent; protected collection: any[]; constructor() { @@ -266,7 +275,8 @@ export class TabsTestCustomStylesComponent { imports: [IgxTabsComponent, IgxTabItemComponent, IgxTabHeaderComponent, IgxTabContentComponent, IgxTabHeaderLabelDirective, IgxDropDownComponent, IgxToggleActionDirective, IgxButtonDirective] }) export class TabsTestBug4420Component { - @ViewChild(IgxTabsComponent, { static: true }) public tabs: IgxTabsComponent; + @ViewChild(IgxTabsComponent, { static: true }) + public tabs: IgxTabsComponent; } @Component({ @@ -406,7 +416,8 @@ export class TabsTabsOnlyModeTest1Component { imports: [IgxTabsComponent, IgxTabItemComponent, IgxTabHeaderComponent, IgxTabContentComponent, IgxTabHeaderLabelDirective] }) export class TabsDisabledTestComponent { - @ViewChild(IgxTabsComponent, { static: true }) public tabs: IgxTabsComponent; + @ViewChild(IgxTabsComponent, { static: true }) + public tabs: IgxTabsComponent; } @Component({ @@ -447,7 +458,8 @@ export class TabsDisabledTestComponent { imports: [IgxTabsComponent, IgxTabItemComponent, IgxTabHeaderComponent, IgxTabContentComponent, IgxTabHeaderLabelDirective] }) export class TabsTestHtmlAttributesComponent { - @ViewChild(IgxTabsComponent, { static: true }) public tabs: IgxTabsComponent; + @ViewChild(IgxTabsComponent, { static: true }) + public tabs: IgxTabsComponent; } @Component({ @@ -538,7 +550,8 @@ export class TabsContactsComponent extends TabsTestComponent { imports: [IgxTabsComponent, IgxTabItemComponent, IgxTabHeaderComponent, IgxTabContentComponent, IgxTabHeaderLabelDirective] }) export class AddingSelectedTabComponent { - @ViewChild(IgxTabsComponent, { static: true }) public tabs: IgxTabsComponent; + @ViewChild(IgxTabsComponent, { static: true }) + public tabs: IgxTabsComponent; protected collection: any[]; constructor() { this.collection = [ @@ -569,8 +582,10 @@ export class AddingSelectedTabComponent { imports: [IgxTabsComponent, IgxTabItemComponent, IgxTabHeaderComponent, IgxTabContentComponent, IgxTabHeaderLabelDirective] }) export class TabsRtlComponent { - @ViewChild(IgxTabsComponent, { static: true }) public tabs: IgxTabsComponent; - @ViewChild('wrapperDiv', { static: true }) public wrapperDiv: any; + @ViewChild(IgxTabsComponent, { static: true }) + public tabs: IgxTabsComponent; + @ViewChild('wrapperDiv', { static: true }) + public wrapperDiv: any; protected collection = [ { name: 'tab1', selected: true }, { name: 'tab2', selected: false }, diff --git a/projects/igniteui-angular/test-utils/template-strings.spec.ts b/projects/igniteui-angular/test-utils/template-strings.spec.ts index 587f1f2b9bd..91801e23d5e 100644 --- a/projects/igniteui-angular/test-utils/template-strings.spec.ts +++ b/projects/igniteui-angular/test-utils/template-strings.spec.ts @@ -18,8 +18,7 @@ export class GridTemplateStrings { [height]="height" [width]="width"> `; - public static declareGrid(attributes = ``, events = ``, columnDefinitions: ColumnDefinitions = ``, - toolbarDefinition = '', paginatorDefinition = '', templateDefinitions: TemplateDefinitions = '') { + public static declareGrid(attributes = ``, events = ``, columnDefinitions: ColumnDefinitions = ``, toolbarDefinition = '', paginatorDefinition = '', templateDefinitions: TemplateDefinitions = '') { return ` + [resizable]="true"> + [editable]="true"> diff --git a/projects/igniteui-angular/test-utils/tooltip-components.spec.ts b/projects/igniteui-angular/test-utils/tooltip-components.spec.ts index 01f45faf660..30126798d49 100644 --- a/projects/igniteui-angular/test-utils/tooltip-components.spec.ts +++ b/projects/igniteui-angular/test-utils/tooltip-components.spec.ts @@ -20,8 +20,10 @@ import { IgxToggleActionDirective, IgxToggleDirective, IgxTooltipDirective, IgxT imports: [IgxTooltipDirective, IgxTooltipTargetDirective] }) export class IgxTooltipSingleTargetComponent { - @ViewChild(IgxTooltipDirective, { static: true }) public tooltip: IgxTooltipDirective; - @ViewChild(IgxTooltipTargetDirective, { static: false }) public tooltipTarget: IgxTooltipTargetDirective; + @ViewChild(IgxTooltipDirective, { static: true }) + public tooltip: IgxTooltipDirective; + @ViewChild(IgxTooltipTargetDirective, { static: false }) + public tooltipTarget: IgxTooltipTargetDirective; public cancelShowing = false; public cancelHiding = false; public showButton = true; @@ -66,11 +68,16 @@ export class IgxTooltipSingleTargetComponent { imports: [IgxTooltipDirective, IgxTooltipTargetDirective] }) export class IgxTooltipMultipleTargetsComponent { - @ViewChild('targetOne', { read: IgxTooltipTargetDirective, static: true }) public targetOne: IgxTooltipTargetDirective; - @ViewChild('targetTwo', { read: IgxTooltipTargetDirective, static: true }) public targetTwo: IgxTooltipTargetDirective; - @ViewChild(IgxTooltipDirective, { static: true }) public tooltip: IgxTooltipDirective; - @ViewChild('customClose', { static: true }) public customCloseTemplate: TemplateRef; - @ViewChild('secondCustomClose', { static: true }) public secondCustomCloseTemplate: TemplateRef; + @ViewChild('targetOne', { read: IgxTooltipTargetDirective, static: true }) + public targetOne: IgxTooltipTargetDirective; + @ViewChild('targetTwo', { read: IgxTooltipTargetDirective, static: true }) + public targetTwo: IgxTooltipTargetDirective; + @ViewChild(IgxTooltipDirective, { static: true }) + public tooltip: IgxTooltipDirective; + @ViewChild('customClose', { static: true }) + public customCloseTemplate: TemplateRef; + @ViewChild('secondCustomClose', { static: true }) + public secondCustomCloseTemplate: TemplateRef; } @Component({ @@ -95,10 +102,14 @@ export class IgxTooltipMultipleTargetsComponent { imports: [IgxTooltipDirective, IgxTooltipTargetDirective] }) export class IgxTooltipMultipleTooltipsComponent { - @ViewChild('targetOne', { read: IgxTooltipTargetDirective, static: true }) public targetOne: IgxTooltipTargetDirective; - @ViewChild('targetTwo', { read: IgxTooltipTargetDirective, static: true }) public targetTwo: IgxTooltipTargetDirective; - @ViewChild('tooltipRef1', { read: IgxTooltipDirective, static: true }) public tooltipOne: IgxTooltipDirective; - @ViewChild('tooltipRef2', { read: IgxTooltipDirective, static: true }) public tooltipTwo: IgxTooltipDirective; + @ViewChild('targetOne', { read: IgxTooltipTargetDirective, static: true }) + public targetOne: IgxTooltipTargetDirective; + @ViewChild('targetTwo', { read: IgxTooltipTargetDirective, static: true }) + public targetTwo: IgxTooltipTargetDirective; + @ViewChild('tooltipRef1', { read: IgxTooltipDirective, static: true }) + public tooltipOne: IgxTooltipDirective; + @ViewChild('tooltipRef2', { read: IgxTooltipDirective, static: true }) + public tooltipTwo: IgxTooltipDirective; } @@ -111,7 +122,8 @@ export class IgxTooltipMultipleTooltipsComponent { imports: [IgxTooltipTargetDirective] }) export class IgxTooltipPlainStringComponent { - @ViewChild(IgxTooltipTargetDirective, { static: true }) public tooltipTarget: IgxTooltipTargetDirective; + @ViewChild(IgxTooltipTargetDirective, { static: true }) + public tooltipTarget: IgxTooltipTargetDirective; } @Component({ @@ -125,9 +137,12 @@ export class IgxTooltipPlainStringComponent { imports: [IgxTooltipDirective, IgxTooltipTargetDirective, IgxToggleActionDirective, IgxToggleDirective] }) export class IgxTooltipWithToggleActionComponent { - @ViewChild(IgxTooltipDirective, { static: true }) public tooltip: IgxTooltipDirective; - @ViewChild(IgxTooltipTargetDirective, { static: true }) public tooltipTarget: IgxTooltipTargetDirective; - @ViewChild(IgxToggleDirective, { static: true }) public toggleDir: IgxToggleDirective; + @ViewChild(IgxTooltipDirective, { static: true }) + public tooltip: IgxTooltipDirective; + @ViewChild(IgxTooltipTargetDirective, { static: true }) + public tooltipTarget: IgxTooltipTargetDirective; + @ViewChild(IgxToggleDirective, { static: true }) + public toggleDir: IgxToggleDirective; } @Component({ @@ -145,8 +160,10 @@ export class IgxTooltipWithToggleActionComponent { imports: [IgxTooltipDirective, IgxTooltipTargetDirective] }) export class IgxTooltipWithCloseButtonComponent { - @ViewChild(IgxTooltipDirective, { static: true }) public tooltip: IgxTooltipDirective; - @ViewChild(IgxTooltipTargetDirective, { static: true }) public tooltipTarget: IgxTooltipTargetDirective; + @ViewChild(IgxTooltipDirective, { static: true }) + public tooltip: IgxTooltipDirective; + @ViewChild(IgxTooltipTargetDirective, { static: true }) + public tooltipTarget: IgxTooltipTargetDirective; } @Component({ @@ -165,8 +182,10 @@ export class IgxTooltipWithCloseButtonComponent { standalone: true }) export class IgxTooltipWithNestedContentComponent { - @ViewChild(IgxTooltipDirective, { static: true }) public tooltip!: IgxTooltipDirective; - @ViewChild(IgxTooltipTargetDirective, { static: true }) public tooltipTarget!: IgxTooltipTargetDirective; + @ViewChild(IgxTooltipDirective, { static: true }) + public tooltip!: IgxTooltipDirective; + @ViewChild(IgxTooltipTargetDirective, { static: true }) + public tooltipTarget!: IgxTooltipTargetDirective; } @Component({ @@ -199,11 +218,17 @@ export class IgxTooltipWithNestedContentComponent { standalone: true }) export class IgxTooltipNestedTooltipsComponent { - @ViewChild('targetLevel1', { read: IgxTooltipTargetDirective, static: true }) public targetLevel1: IgxTooltipTargetDirective; - @ViewChild('targetLevel2', { read: IgxTooltipTargetDirective, static: true }) public targetLevel2: IgxTooltipTargetDirective; - @ViewChild('targetLevel3', { read: IgxTooltipTargetDirective, static: true }) public targetLevel3: IgxTooltipTargetDirective; - - @ViewChild('tooltipLevel1', { read: IgxTooltipDirective, static: true }) public tooltipLevel1: IgxTooltipDirective; - @ViewChild('tooltipLevel2', { read: IgxTooltipDirective, static: true }) public tooltipLevel2: IgxTooltipDirective; - @ViewChild('tooltipLevel3', { read: IgxTooltipDirective, static: true }) public tooltipLevel3: IgxTooltipDirective; + @ViewChild('targetLevel1', { read: IgxTooltipTargetDirective, static: true }) + public targetLevel1: IgxTooltipTargetDirective; + @ViewChild('targetLevel2', { read: IgxTooltipTargetDirective, static: true }) + public targetLevel2: IgxTooltipTargetDirective; + @ViewChild('targetLevel3', { read: IgxTooltipTargetDirective, static: true }) + public targetLevel3: IgxTooltipTargetDirective; + + @ViewChild('tooltipLevel1', { read: IgxTooltipDirective, static: true }) + public tooltipLevel1: IgxTooltipDirective; + @ViewChild('tooltipLevel2', { read: IgxTooltipDirective, static: true }) + public tooltipLevel2: IgxTooltipDirective; + @ViewChild('tooltipLevel3', { read: IgxTooltipDirective, static: true }) + public tooltipLevel3: IgxTooltipDirective; } diff --git a/projects/igniteui-angular/test-utils/tree-grid-components.spec.ts b/projects/igniteui-angular/test-utils/tree-grid-components.spec.ts index 704f9ef36c8..de4dd4f02c2 100644 --- a/projects/igniteui-angular/test-utils/tree-grid-components.spec.ts +++ b/projects/igniteui-angular/test-utils/tree-grid-components.spec.ts @@ -20,7 +20,8 @@ import { IgxColumnComponent, IgxColumnGroupComponent, IgxExcelStyleColumnOperati imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridSortingComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeSmallTreeData(); } @@ -36,7 +37,8 @@ export class IgxTreeGridSortingComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridFilteringComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeTreeData(); } @@ -75,7 +77,8 @@ export class IgxTreeGridFilteringComponent { ] }) export class IgxTreeGridFilteringESFTemplatesComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeTreeData(); } @@ -95,7 +98,8 @@ export class IgxTreeGridFilteringESFTemplatesComponent { imports: [IgxTreeGridComponent, IgxColumnComponent, IgxPaginatorComponent] }) export class IgxTreeGridSimpleComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeSmallTreeData(); public selectedRows = []; public paging = false; @@ -115,7 +119,8 @@ export class IgxTreeGridSimpleComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridWithScrollsComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeAllTypesTreeData(); } @@ -132,7 +137,8 @@ export class IgxTreeGridWithScrollsComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridWithNoScrollsComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeAllTypesTreeData(); } @@ -152,15 +158,16 @@ export class IgxTreeGridWithNoScrollsComponent { imports: [IgxTreeGridComponent, IgxColumnComponent, IgxPaginatorComponent] }) export class IgxTreeGridPrimaryForeignKeyComponent implements OnInit { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = []; public paging = false; public sortByName = false; public ngOnInit(): void { this.data = !this.sortByName - ? SampleTestData.employeePrimaryForeignKeyTreeData() - : SampleTestData.employeePrimaryForeignKeyTreeData().sort((a, b) => a.Name.localeCompare(b.Name)); + ? SampleTestData.employeePrimaryForeignKeyTreeData() + : SampleTestData.employeePrimaryForeignKeyTreeData().sort((a, b) => a.Name.localeCompare(b.Name)); } } @@ -177,7 +184,8 @@ export class IgxTreeGridPrimaryForeignKeyComponent implements OnInit { imports: [IgxTreeGridComponent, IgxColumnComponent, IgxPaginatorComponent] }) export class IgxTreeGridExpandingComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeTreeData(); } @@ -200,7 +208,8 @@ export class IgxTreeGridExpandingComponent { imports: [IgxTreeGridComponent, IgxColumnComponent, IgxPaginatorComponent] }) export class IgxTreeGridCellSelectionComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeTreeData(); @ViewChild('customCell', { static: true }) public customCell!: TemplateRef; @@ -220,7 +229,8 @@ export class IgxTreeGridCellSelectionComponent { imports: [IgxTreeGridComponent, IgxColumnComponent, IgxPaginatorComponent] }) export class IgxTreeGridNoDataComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; } // Test Component with 'string' dataType tree-column @@ -236,7 +246,8 @@ export class IgxTreeGridNoDataComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridStringTreeColumnComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeSmallTreeData(); } @@ -253,7 +264,8 @@ export class IgxTreeGridStringTreeColumnComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridDateTreeColumnComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeSmallTreeData(); } @@ -271,7 +283,8 @@ export class IgxTreeGridDateTreeColumnComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridBooleanTreeColumnComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeAllTypesTreeData(); } @@ -288,7 +301,8 @@ export class IgxTreeGridBooleanTreeColumnComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridRowEditingComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeSmallTreeData(); } @@ -305,7 +319,8 @@ export class IgxTreeGridRowEditingComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridFilteringRowEditingComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeTreeData(); } @@ -321,7 +336,8 @@ export class IgxTreeGridFilteringRowEditingComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridSelectionRowEditingComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeTreeData(); } @@ -341,7 +357,8 @@ export class IgxTreeGridSelectionRowEditingComponent { imports: [IgxTreeGridComponent, IgxColumnComponent, IgxColumnGroupComponent] }) export class IgxTreeGridMultiColHeadersComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeSmallTreeData(); } @@ -359,7 +376,8 @@ export class IgxTreeGridMultiColHeadersComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridSummariesComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeTreeData(); public ageSummary = AgeSummary; public ageSummaryTest = AgeSummaryTest; @@ -380,7 +398,8 @@ export class IgxTreeGridSummariesComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridSummariesKeyScroliingComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeTreeDataPrimaryForeignKey(); } @@ -398,7 +417,8 @@ export class IgxTreeGridSummariesKeyScroliingComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridWithNoForeignKeyComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeTreeDataPrimaryForeignKey(); } @@ -419,7 +439,8 @@ export class IgxTreeGridWithNoForeignKeyComponent { imports: [IgxTreeGridComponent, IgxColumnComponent, IgxPaginatorComponent] }) export class IgxTreeGridSummariesKeyComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeTreeDataPrimaryForeignKey(); public calculationMode: GridSummaryCalculationMode = 'rootAndChildLevels'; public ageSummary = AgeSummary; @@ -442,7 +463,8 @@ export class IgxTreeGridSummariesKeyComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridSummariesTransactionsComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeTreeDataPrimaryForeignKey(); public calculationMode: GridSummaryCalculationMode = 'rootAndChildLevels'; public ageSummary = AgeSummaryMinMax; @@ -454,7 +476,7 @@ class AgeSummary extends IgxNumberSummaryOperand { super(); } - public override operate(summaries?: any[]): IgxSummaryResult [] { + public override operate(summaries?: any[]): IgxSummaryResult[] { const result = super.operate(summaries).filter((obj) => { if (obj.key === 'average' || obj.key === 'sum' || obj.key === 'count') { const summaryResult = obj.summaryResult; @@ -537,7 +559,8 @@ class PTOSummary extends IgxSummaryOperand { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridRowEditingTransactionComponent { - @ViewChild('treeGrid', { read: IgxTreeGridComponent, static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild('treeGrid', { read: IgxTreeGridComponent, static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeePrimaryForeignKeyTreeData(); public paging = false; } @@ -555,7 +578,8 @@ export class IgxTreeGridRowEditingTransactionComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridCustomSummariesComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeTreeData(); public ageSummary = AgeSummary; public ageSummaryTest = AgeSummaryTest; @@ -575,7 +599,8 @@ export class IgxTreeGridCustomSummariesComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridRowEditingHierarchicalDSTransactionComponent { - @ViewChild('treeGrid', { read: IgxTreeGridComponent, static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild('treeGrid', { read: IgxTreeGridComponent, static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeAllTypesTreeData(); public paging = false; } @@ -596,7 +621,8 @@ export class IgxTreeGridRowEditingHierarchicalDSTransactionComponent { imports: [IgxTreeGridComponent, IgxColumnComponent, IgxPaginatorComponent] }) export class IgxTreeGridRowPinningComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeAllTypesTreeData(); public paging = false; } @@ -616,7 +642,8 @@ export class IgxTreeGridRowPinningComponent { }) export class IgxTreeGridWrappedInContComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeTreeData(); public height = null; @@ -651,7 +678,7 @@ export class IgxTreeGridWrappedInContComponent { return false; } - public clearData(){ + public clearData() { this.data = []; } } @@ -671,7 +698,8 @@ export class IgxTreeGridWrappedInContComponent { imports: [IgxTreeGridComponent, IgxColumnComponent, IgxPaginatorComponent] }) export class IgxTreeGridSummariesScrollingComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeScrollingData(); public paging = false; } @@ -689,7 +717,8 @@ export class IgxTreeGridSummariesScrollingComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridSearchComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeSearchTreeData(); } @@ -708,7 +737,8 @@ export class IgxTreeGridSearchComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridLoadOnDemandComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public allData = SampleTestData.employeePrimaryForeignKeyTreeData(); public data = []; @@ -733,7 +763,8 @@ export class IgxTreeGridLoadOnDemandComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridSelectionKeyComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeTreeDataPrimaryForeignKey(); } @@ -752,7 +783,8 @@ export class IgxTreeGridSelectionKeyComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridLoadOnDemandChildDataComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public allData = SampleTestData.employeePrimaryForeignKeyTreeData(); public data = []; @@ -778,7 +810,8 @@ export class IgxTreeGridLoadOnDemandChildDataComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridSelectionComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeTreeData(); } @@ -797,7 +830,8 @@ export class IgxTreeGridSelectionComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridLoadOnDemandHasChildrenComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public allData = SampleTestData.employeePrimaryForeignKeyTreeData(); public data = []; @@ -836,7 +870,8 @@ export class IgxTreeGridLoadOnDemandHasChildrenComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridSelectionWithTransactionComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeTreeData(); } @@ -854,7 +889,8 @@ export class IgxTreeGridSelectionWithTransactionComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridFKeySelectionWithTransactionComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeTreeDataPrimaryForeignKey(); } @@ -871,7 +907,8 @@ export class IgxTreeGridFKeySelectionWithTransactionComponent { imports: [IgxTreeGridComponent, IgxColumnComponent] }) export class IgxTreeGridDefaultLoadingComponent implements OnInit { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = []; public ngOnInit(): void { @@ -959,7 +996,8 @@ export class IgxTreeGridCustomRowSelectorsComponent implements OnInit { imports: [IgxTreeGridComponent, IgxColumnComponent, IgxRowExpandedIndicatorDirective, IgxRowCollapsedIndicatorDirective] }) export class IgxTreeGridCustomExpandersTemplateComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeTreeData(); } @@ -979,7 +1017,8 @@ export class IgxTreeGridCustomExpandersTemplateComponent { imports: [IgxTreeGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridEditingActionsComponent] }) export class IgxTreeGridEditActionsComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; @ViewChild('actionStrip', { read: IgxActionStripComponent, static: true }) public actionStrip: IgxActionStripComponent; public data = SampleTestData.employeePrimaryForeignKeyTreeData(); @@ -1001,7 +1040,8 @@ export class IgxTreeGridEditActionsComponent { imports: [IgxTreeGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridEditingActionsComponent] }) export class IgxTreeGridCascadingSelectionComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; @ViewChild('actionStrip', { read: IgxActionStripComponent, static: true }) public actionStrip: IgxActionStripComponent; public data = SampleTestData.employeeSmallTreeData(); @@ -1023,7 +1063,8 @@ export class IgxTreeGridCascadingSelectionComponent { imports: [IgxTreeGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridEditingActionsComponent] }) export class IgxTreeGridCascadingSelectionTransactionComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; @ViewChild('actionStrip', { read: IgxActionStripComponent, static: true }) public actionStrip: IgxActionStripComponent; public data = SampleTestData.employeeSmallTreeData(); @@ -1050,17 +1091,18 @@ export class IgxTreeGridCascadingSelectionTransactionComponent { imports: [IgxTreeGridComponent, IgxColumnComponent, IgxTreeGridGroupByAreaComponent, IgxTreeGridGroupingPipe] }) export class IgxTreeGridGroupingComponent { - @ViewChild(IgxTreeGridGroupByAreaComponent, { static: true }) public groupByArea: IgxTreeGridGroupByAreaComponent; - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridGroupByAreaComponent, { static: true }) + public groupByArea: IgxTreeGridGroupByAreaComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; public data = SampleTestData.employeeTreeDataPrimaryForeignKeyExt(); public groupKey = 'GK_Employees'; public groupedInitially = true; - public childDataKey='Employees'; - public groupingExpressions: IGroupingExpression[] = - [ - { fieldName: 'OnPTO', dir: 1, ignoreCase: true, strategy: DefaultSortingStrategy.instance() }, - { fieldName: 'HireDate', dir: 2, ignoreCase: true, strategy: DefaultSortingStrategy.instance() } - ]; + public childDataKey = 'Employees'; + public groupingExpressions: IGroupingExpression[] = [ + { fieldName: 'OnPTO', dir: 1, ignoreCase: true, strategy: DefaultSortingStrategy.instance() }, + { fieldName: 'HireDate', dir: 2, ignoreCase: true, strategy: DefaultSortingStrategy.instance() } + ]; public aggregations = []; } @@ -1076,8 +1118,10 @@ export class IgxTreeGridGroupingComponent { imports: [IgxTreeGridComponent, IgxTreeGridGroupByAreaComponent] }) export class IgxTreeGridGroupByAreaTestComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; - @ViewChild(IgxTreeGridGroupByAreaComponent, { static: true }) public groupByArea: IgxTreeGridGroupByAreaComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridGroupByAreaComponent, { static: true }) + public groupByArea: IgxTreeGridGroupByAreaComponent; } @Component({ @@ -1096,7 +1140,8 @@ export class IgxTreeGridGroupByAreaTestComponent { imports: [IgxTreeGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridEditingActionsComponent] }) export class IgxTreeGridPrimaryForeignKeyCascadeSelectionComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; @ViewChild('actionStrip', { read: IgxActionStripComponent, static: true }) public actionStrip: IgxActionStripComponent; public data = SampleTestData.employeeSmallPrimaryForeignKeyTreeData(); @@ -1119,7 +1164,8 @@ export class IgxTreeGridPrimaryForeignKeyCascadeSelectionComponent { imports: [IgxTreeGridComponent, IgxColumnComponent, IgxActionStripComponent, IgxGridPinningActionsComponent, IgxGridEditingActionsComponent] }) export class IgxTreeGridEditActionsPinningComponent { - @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild(IgxTreeGridComponent, { static: true }) + public treeGrid: IgxTreeGridComponent; @ViewChild('actionStrip', { read: IgxActionStripComponent, static: true }) public actionStrip: IgxActionStripComponent; public data = SampleTestData.employeePrimaryForeignKeyTreeData(); diff --git a/projects/igniteui-angular/test-utils/tree-grid-functions.spec.ts b/projects/igniteui-angular/test-utils/tree-grid-functions.spec.ts index 2705c21c41d..6d98ccd435b 100644 --- a/projects/igniteui-angular/test-utils/tree-grid-functions.spec.ts +++ b/projects/igniteui-angular/test-utils/tree-grid-functions.spec.ts @@ -5,6 +5,7 @@ import { DebugElement } from '@angular/core'; import { IgxCheckboxComponent } from 'igniteui-angular/checkbox'; import { IgxTreeGridComponent } from 'igniteui-angular/grids/tree-grid'; import { CellType, IgxGridCellComponent, IgxRowDirective } from 'igniteui-angular/grids/core'; +import { expect } from 'vitest'; // CSS class should end with a number that specified the row's level const TREE_CELL_DIV_INDENTATION_CSS_CLASS = '.igx-grid__tree-cell--padding-level-'; @@ -27,7 +28,7 @@ export class TreeGridFunctions { return fix.debugElement.query(By.css(TREE_HEADER_ROW_CSS_CLASS)); } - public static getAllRows(fix): DebugElement [] { + public static getAllRows(fix): DebugElement[] { return fix.debugElement.queryAll(By.css('igx-tree-grid-row')); } @@ -132,13 +133,13 @@ export class TreeGridFunctions { // Verify each row's cell count const treeCell = TreeGridFunctions.getTreeCell(row); const normalCells = TreeGridFunctions.getNormalCells(row); - expect(1 + normalCells.length).toBe(expectedColumnsCount, 'incorrect cell count for a row'); + expect(1 + normalCells.length, 'incorrect cell count for a row').toBe(expectedColumnsCount); const treeCellRectRight = treeCell.nativeElement.getBoundingClientRect().right; normalCells.forEach((normalCell) => { // Verify that the treeCell is the first cell (on the left of all the other cells) const normalCellRectLeft = normalCell.nativeElement.getBoundingClientRect().left; - expect(treeCellRectRight <= normalCellRectLeft).toBe(true, 'TreeCell is not on the left of a normal cell.'); + expect(treeCellRectRight <= normalCellRectLeft, 'TreeCell is not on the left of a normal cell.').toBe(true); }); }); } @@ -154,10 +155,10 @@ export class TreeGridFunctions { // and thus it has no indentation div. const indentationDiv = treeCell.query(By.css(TREE_CELL_DIV_INDENTATION_CSS_CLASS + expectedIndentationLevel)); if (expectedIndentationLevel === 0) { - expect(divChildren.length).toBe(2, 'root treeCell has incorrect divs count'); + expect(divChildren.length, 'root treeCell has incorrect divs count').toBe(2); expect(indentationDiv).toBeNull(); } else { - expect(divChildren.length).toBe(3, 'child treeCell has incorrect divs count'); + expect(divChildren.length, 'child treeCell has incorrect divs count').toBe(3); expect(indentationDiv).toBeDefined(); expect(indentationDiv).not.toBeNull(); } @@ -196,9 +197,9 @@ export class TreeGridFunctions { const headerCellRect = headerCell.nativeElement.getBoundingClientRect(); treeCells.forEach(treeCell => { const treeCellRect = treeCell.nativeElement.getBoundingClientRect(); - expect(headerCellRect.bottom <= treeCellRect.top).toBe(true, 'headerCell is not on top of a treeCell'); - expect(headerCellRect.left).toBe(treeCellRect.left, 'headerCell and treeCell are not left-aligned'); - expect(headerCellRect.right).toBe(treeCellRect.right, 'headerCell and treeCell are not right-aligned'); + expect(headerCellRect.bottom <= treeCellRect.top, 'headerCell is not on top of a treeCell').toBe(true); + expect(headerCellRect.left, 'headerCell and treeCell are not left-aligned').toBe(treeCellRect.left); + expect(headerCellRect.right, 'headerCell and treeCell are not right-aligned').toBe(treeCellRect.right); }); } @@ -207,8 +208,7 @@ export class TreeGridFunctions { */ public static verifyTreeColumnInMultiColHeaders(fix, _expectedTreeColumnKey, expectedColumnsCount) { const headersDOM = TreeGridFunctions.sortElementsHorizontally(fix.debugElement.queryAll(By.css('igx-grid-header'))); - const leftMostHeaders = headersDOM.filter(x => - x.nativeElement.getBoundingClientRect().left === headersDOM[0].nativeElement.getBoundingClientRect().left); + const leftMostHeaders = headersDOM.filter(x => x.nativeElement.getBoundingClientRect().left === headersDOM[0].nativeElement.getBoundingClientRect().left); const headerCell = TreeGridFunctions.getElementWithMinHeight(leftMostHeaders); const treeCells = TreeGridFunctions.getTreeCells(fix); @@ -220,25 +220,22 @@ export class TreeGridFunctions { const headerCellRect = headerCell.nativeElement.getBoundingClientRect(); treeCells.forEach(treeCell => { const treeCellRect = treeCell.nativeElement.getBoundingClientRect(); - expect(headerCellRect.bottom <= treeCellRect.top).toBe(true, 'headerCell is not above a treeCell'); - expect(headerCellRect.left).toBe(treeCellRect.left, 'headerCell and treeCell are not left-aligned'); - expect(headerCellRect.right).toBe(treeCellRect.right, 'headerCell and treeCell are not right-aligned'); + expect(headerCellRect.bottom <= treeCellRect.top, 'headerCell is not above a treeCell').toBe(true); + expect(headerCellRect.left, 'headerCell and treeCell are not left-aligned').toBe(treeCellRect.left); + expect(headerCellRect.right, 'headerCell and treeCell are not right-aligned').toBe(treeCellRect.right); }); } public static getElementWithMinHeight(arr) { - return arr.reduce((a, b) => - (a.nativeElement.getBoundingClientRect().height < b.nativeElement.getBoundingClientRect().height) ? a : b); + return arr.reduce((a, b) => (a.nativeElement.getBoundingClientRect().height < b.nativeElement.getBoundingClientRect().height) ? a : b); } public static sortElementsVertically(arr) { - return arr.sort((a, b) => - a.nativeElement.getBoundingClientRect().top - b.nativeElement.getBoundingClientRect().top); + return arr.sort((a, b) => a.nativeElement.getBoundingClientRect().top - b.nativeElement.getBoundingClientRect().top); } public static sortElementsHorizontally(arr) { - return arr.sort((a, b) => - a.nativeElement.getBoundingClientRect().left - b.nativeElement.getBoundingClientRect().left); + return arr.sort((a, b) => a.nativeElement.getBoundingClientRect().left - b.nativeElement.getBoundingClientRect().left); } public static verifyTreeRowHasCollapsedIcon(treeRowDOM) { @@ -272,8 +269,7 @@ export class TreeGridFunctions { const iconDiv = TreeGridFunctions.getExpansionIndicatorDiv(treeRowDOM); const iconDivRect = iconDiv.nativeElement.getBoundingClientRect(); - expect((iconDivRect.left - (treeCellRect.left + treeCellPaddingLeft + indentation)) < 2) - .toBe(true, 'TreeRow icon has incorrect position'); + expect((iconDivRect.left - (treeCellRect.left + treeCellPaddingLeft + indentation)) < 2, 'TreeRow icon has incorrect position').toBe(true); } /** @@ -297,11 +293,11 @@ export class TreeGridFunctions { // Verfiy selection of checkbox const checkboxDiv = rowDOM.query(By.css(TREE_ROW_DIV_SELECTION_CHECKBOX_CSS_CLASS)); const checkboxComponent = checkboxDiv.query(By.css('igx-checkbox')).componentInstance as IgxCheckboxComponent; - expect(checkboxComponent.checked).toBe(expectedSelection, 'Incorrect checkbox selection state'); - expect(checkboxComponent.nativeInput.nativeElement.checked).toBe(expectedSelection, 'Incorrect native checkbox selection state'); + expect(checkboxComponent.checked, 'Incorrect checkbox selection state').toBe(expectedSelection); + expect(checkboxComponent.nativeInput.nativeElement.checked, 'Incorrect native checkbox selection state').toBe(expectedSelection); // Verify selection of row - expect(rowComponent.selected).toBe(expectedSelection, 'Incorrect row selection state'); + expect(rowComponent.selected, 'Incorrect row selection state').toBe(expectedSelection); expect(rowDOM.nativeElement.classList.contains(TREE_ROW_SELECTION_CSS_CLASS)).toBe(expectedSelection); // Verify selection of row through treeGrid @@ -328,7 +324,7 @@ export class TreeGridFunctions { public static verifyDataRowsSelection(fix, expectedSelectedRowIndices: any[], expectedSelection: boolean) { if (expectedSelection) { const treeGrid = fix.debugElement.query(By.css('igx-tree-grid')).componentInstance as IgxTreeGridComponent; - expect(treeGrid.selectedRows.length).toBe(expectedSelectedRowIndices.length, 'Incorrect number of rows that are selected.'); + expect(treeGrid.selectedRows.length, 'Incorrect number of rows that are selected.').toBe(expectedSelectedRowIndices.length); } expectedSelectedRowIndices.forEach(rowIndex => { @@ -339,8 +335,7 @@ export class TreeGridFunctions { /** * Verifies the selection and checkbox state of the treeGrid row. */ - public static verifyRowByIndexSelectionAndCheckboxState(fix, rowIndex: any, expectedSelection: boolean, - expectedCheckboxState: boolean | null) { + public static verifyRowByIndexSelectionAndCheckboxState(fix, rowIndex: any, expectedSelection: boolean, expectedCheckboxState: boolean | null) { const treeGrid = fix.debugElement.query(By.css('igx-tree-grid')).componentInstance as IgxTreeGridComponent; const rowComponent = treeGrid.getRowByIndex(rowIndex); const rowDOM = TreeGridFunctions.sortElementsVertically(TreeGridFunctions.getAllRows(fix))[rowIndex]; @@ -350,23 +345,22 @@ export class TreeGridFunctions { if (expectedCheckboxState === null) { expect(checkboxComponent.indeterminate).toBe(true); - expect(checkboxComponent.checked).toBe(false, 'Incorrect checkbox selection state'); - expect(checkboxComponent.nativeInput.nativeElement.checked).toBe(false, 'Incorrect native checkbox selection state'); + expect(checkboxComponent.checked, 'Incorrect checkbox selection state').toBe(false); + expect(checkboxComponent.nativeInput.nativeElement.checked, 'Incorrect native checkbox selection state').toBe(false); // Verify selection of row - expect(rowComponent.selected).toBe(false, 'Incorrect row selection state'); + expect(rowComponent.selected, 'Incorrect row selection state').toBe(false); expect((rowDOM.nativeElement as HTMLElement).classList.contains(TREE_ROW_SELECTION_CSS_CLASS)).toBe(false); // Verify selection of row through treeGrid const selectedRows = (treeGrid as IgxTreeGridComponent).selectedRows; expect(selectedRows.includes(rowComponent.key)).toBe(false); } else { - expect(checkboxComponent.checked).toBe(expectedCheckboxState, 'Incorrect checkbox selection state'); - expect(checkboxComponent.nativeInput.nativeElement.checked).toBe( - expectedCheckboxState, 'Incorrect native checkbox selection state'); + expect(checkboxComponent.checked, 'Incorrect checkbox selection state').toBe(expectedCheckboxState); + expect(checkboxComponent.nativeInput.nativeElement.checked, 'Incorrect native checkbox selection state').toBe(expectedCheckboxState); // Verify selection of row - expect(rowComponent.selected).toBe(expectedSelection, 'Incorrect row selection state'); + expect(rowComponent.selected, 'Incorrect row selection state').toBe(expectedSelection); expect((rowDOM.nativeElement as HTMLElement).classList.contains(TREE_ROW_SELECTION_CSS_CLASS)).toBe(expectedSelection); // Verify selection of row through treeGrid @@ -386,13 +380,12 @@ export class TreeGridFunctions { if (expectedSelection === null) { expect(checkboxComponent.indeterminate).toBe(true); - expect(checkboxComponent.checked).toBe(false, 'Incorrect checkbox selection state'); - expect(checkboxComponent.nativeInput.nativeElement.checked).toBe(false, 'Incorrect native checkbox selection state'); + expect(checkboxComponent.checked, 'Incorrect checkbox selection state').toBe(false); + expect(checkboxComponent.nativeInput.nativeElement.checked, 'Incorrect native checkbox selection state').toBe(false); } else { expect(checkboxComponent.indeterminate).toBe(false); - expect(checkboxComponent.checked).toBe(expectedSelection, 'Incorrect checkbox selection state'); - expect(checkboxComponent.nativeInput.nativeElement.checked).toBe(expectedSelection, - 'Incorrect native checkbox selection state'); + expect(checkboxComponent.checked, 'Incorrect checkbox selection state').toBe(expectedSelection); + expect(checkboxComponent.nativeInput.nativeElement.checked, 'Incorrect native checkbox selection state').toBe(expectedSelection); } } @@ -400,8 +393,7 @@ export class TreeGridFunctions { return cellDOM.nativeElement.classList.contains(TREE_CELL_SELECTION_CSS_CLASS); } - public static verifyTreeGridCellSelected(treeGrid: IgxTreeGridComponent, - cell: IgxGridCellComponent | CellType, selected = true) { + public static verifyTreeGridCellSelected(treeGrid: IgxTreeGridComponent, cell: IgxGridCellComponent | CellType, selected = true) { expect(cell).toBeDefined(); if (cell) { expect(TreeGridFunctions.verifyGridCellHasSelectedClass(cell)).toBe(selected); @@ -458,8 +450,7 @@ export class TreeGridFunctions { TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, newCell); } - public static moveCellLeftRight(fix, treeGrid: IgxTreeGridComponent, rowIndex: number, - firstColumnName: string, nextColumnName: string, moveRight = true) { + public static moveCellLeftRight(fix, treeGrid: IgxTreeGridComponent, rowIndex: number, firstColumnName: string, nextColumnName: string, moveRight = true) { const cell = treeGrid.gridAPI.get_cell_by_index(rowIndex, firstColumnName); const keyboardEventKey = moveRight ? 'ArrowRight' : 'ArrowLeft'; const gridContent = GridFunctions.getGridContent(fix); @@ -473,10 +464,9 @@ export class TreeGridFunctions { } - public static moveGridCellWithTab = - async (fix, cell: IgxGridCellComponent | CellType) => { - UIInteractions.triggerKeyDownEvtUponElem('Tab', cell.nativeElement, true); - await wait(DEBOUNCETIME); - fix.detectChanges(); - }; + public static moveGridCellWithTab = async (fix, cell: IgxGridCellComponent | CellType) => { + UIInteractions.triggerKeyDownEvtUponElem('Tab', cell.nativeElement, true); + await wait(DEBOUNCETIME); + fix.detectChanges(); + }; } diff --git a/projects/igniteui-angular/test-utils/ui-interactions.spec.ts b/projects/igniteui-angular/test-utils/ui-interactions.spec.ts index 3bd6c261053..85895340907 100644 --- a/projects/igniteui-angular/test-utils/ui-interactions.spec.ts +++ b/projects/igniteui-angular/test-utils/ui-interactions.spec.ts @@ -21,7 +21,7 @@ export const waitForSelectionChange = grid => new Promise(resolve => grid. declare let Touch: { prototype: Touch; - new(prop): Touch; + new (prop): Touch; }; export class UIInteractions { /** @@ -205,8 +205,8 @@ export class UIInteractions { const endPos = target.nativeElement.selectionEnd; target.nativeElement.value = target.nativeElement.value.substring(0, startPos) + - inputValue + - target.nativeElement.value.substring(endPos); + inputValue + + target.nativeElement.value.substring(endPos); // move the caret if (startPos !== endPos) { // replaced selection, cursor goes to end @@ -423,10 +423,7 @@ export class UIInteractions { * @param hAlign The horizontal position of the point within the element (defaults to center) * @param vAlign The vertical position of the point within the element (defaults to middle) */ - public static getPointFromElement( - element: Element, - hAlign: HorizontalAlignment = HorizontalAlignment.Center, - vAlign: VerticalAlignment = VerticalAlignment.Middle): Point { + public static getPointFromElement(element: Element, hAlign: HorizontalAlignment = HorizontalAlignment.Center, vAlign: VerticalAlignment = VerticalAlignment.Middle): Point { const elementRect = element.getBoundingClientRect(); return { x: elementRect.right + hAlign * elementRect.width, diff --git a/projects/igniteui-angular/time-picker/src/time-picker/time-picker.component.spec.ts b/projects/igniteui-angular/time-picker/src/time-picker/time-picker.component.spec.ts index b3fc9f630e5..a48db34487e 100644 --- a/projects/igniteui-angular/time-picker/src/time-picker/time-picker.component.spec.ts +++ b/projects/igniteui-angular/time-picker/src/time-picker/time-picker.component.spec.ts @@ -1,3 +1,5 @@ +import type { Mock } from "vitest"; +import { describe, it, expect, beforeEach, vi } from 'vitest'; import { Component, ViewChild, DebugElement, EventEmitter, QueryList, ElementRef, Injector, ChangeDetectorRef } from '@angular/core'; import { TestBed, fakeAsync, tick, ComponentFixture, waitForAsync } from '@angular/core/testing'; import { UntypedFormControl, UntypedFormGroup, FormsModule, NgForm, ReactiveFormsModule, Validators } from '@angular/forms'; @@ -5,9 +7,7 @@ import { By } from '@angular/platform-browser'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxTimePickerComponent, IgxTimePickerValidationFailedEventArgs } from './time-picker.component'; import { UIInteractions } from '../../../test-utils/ui-interactions.spec'; -import { - IgxHintDirective, IgxInputGroupComponent, IgxInputState, IgxLabelDirective, IgxPrefixDirective, IgxSuffixDirective -} from '../../../input-group/src/public_api'; +import { IgxHintDirective, IgxInputGroupComponent, IgxInputState, IgxLabelDirective, IgxPrefixDirective, IgxSuffixDirective } from '../../../input-group/src/public_api'; import { PickerInteractionMode } from '../../../core/src/date-common/types'; import { PlatformUtil, BaseFormatter, I18N_FORMATTER } from 'igniteui-angular/core'; import { DatePart } from '../../../core/src/date-common/public_api'; @@ -72,8 +72,8 @@ describe('IgxTimePicker', () => { valueChange: new EventEmitter(), validationFailed: new EventEmitter() }; - spyOn(mockDateTimeEditorDirective, 'increment'); - spyOn(mockDateTimeEditorDirective, 'decrement'); + vi.spyOn(mockDateTimeEditorDirective, 'increment'); + vi.spyOn(mockDateTimeEditorDirective, 'decrement'); mockInputGroup = { _isFocused: false, @@ -91,13 +91,22 @@ describe('IgxTimePicker', () => { this._isRequired = val; }, element: { - nativeElement: jasmine.createSpyObj('mockElement', - ['focus', 'blur', 'click', 'addEventListener', 'removeEventListener']) + nativeElement: { + focus: vi.fn().mockName("mockElement.focus"), + blur: vi.fn().mockName("mockElement.blur"), + click: vi.fn().mockName("mockElement.click"), + addEventListener: vi.fn().mockName("mockElement.addEventListener"), + removeEventListener: vi.fn().mockName("mockElement.removeEventListener") + } } } as any; elementRef = { - nativeElement: jasmine.createSpyObj('mockElement', ['blur', 'click', 'focus']) + nativeElement: { + blur: vi.fn().mockName("mockElement.blur"), + click: vi.fn().mockName("mockElement.click"), + focus: vi.fn().mockName("mockElement.focus") + } }; mockControlInstance = { _touched: false, @@ -188,18 +197,20 @@ describe('IgxTimePicker', () => { }, focus: () => { } }; - mockInjector = jasmine.createSpyObj('Injector', { - get: mockNgControl - }); + mockInjector = { + get: vi.fn().mockName("Injector.get").mockReturnValue(mockNgControl) + }; - mockCdr = jasmine.createSpyObj('ChangeDetectorRef', ['detectChanges']); + mockCdr = { + detectChanges: vi.fn().mockName("ChangeDetectorRef.detectChanges") + }; //const platformUtil = TestBed.inject(PlatformUtil); TestBed.configureTestingModule({ providers: [ - {provide: ElementRef, useValue: elementRef}, - {provide: Injector, useValue: mockInjector}, - {provide: ChangeDetectorRef, useValue: mockCdr}, + { provide: ElementRef, useValue: elementRef }, + { provide: Injector, useValue: mockInjector }, + { provide: ChangeDetectorRef, useValue: mockCdr }, { provide: IGX_TIME_PICKER_COMPONENT, useExisting: IgxTimePickerComponent }, IgxTimePickerComponent, PlatformUtil, @@ -216,8 +227,10 @@ describe('IgxTimePicker', () => { }); it('should properly initialize w/ ngControl', () => { - const mockSub = jasmine.createSpyObj('mockSub', ['unsubscribe']); - spyOn(mockNgControl.statusChanges, 'subscribe').and.returnValue(mockSub); + const mockSub = { + unsubscribe: vi.fn().mockName("mockSub.unsubscribe") + }; + vi.spyOn(mockNgControl.statusChanges, 'subscribe').mockReturnValue(mockSub); timePicker.ngOnInit(); timePicker.ngAfterViewInit(); expect(mockNgControl.statusChanges.subscribe).toHaveBeenCalledTimes(1); @@ -228,52 +241,52 @@ describe('IgxTimePicker', () => { it('should properly subscribe to ngControl status changes', () => { timePicker.ngOnInit(); timePicker.ngAfterViewInit(); - const touchedSpy = spyOnProperty(mockControlInstance, 'touched', 'get'); - const dirtySpy = spyOnProperty(mockControlInstance, 'dirty', 'get'); - const validatorSpy = spyOnProperty(mockControlInstance, 'validator'); - const asyncValidatorSpy = spyOnProperty(mockControlInstance, 'asyncValidator'); - const inputGroupFocusedSpy = spyOnProperty(mockInputGroup, 'isFocused', 'get'); - const inputGroupRequiredGet = spyOnProperty(mockInputGroup, 'isRequired', 'get'); - const inputGroupRequiredSet = spyOnProperty(mockInputGroup, 'isRequired', 'set'); - inputGroupRequiredGet.and.returnValue(false); - inputGroupFocusedSpy.and.returnValue(false); + const touchedSpy = vi.spyOn(mockControlInstance, 'touched', 'get'); + const dirtySpy = vi.spyOn(mockControlInstance, 'dirty', 'get'); + const validatorSpy = vi.spyOn(mockControlInstance, 'validator'); + const asyncValidatorSpy = vi.spyOn(mockControlInstance, 'asyncValidator'); + const inputGroupFocusedSpy = vi.spyOn(mockInputGroup, 'isFocused', 'get'); + const inputGroupRequiredGet = vi.spyOn(mockInputGroup, 'isRequired', 'get'); + const inputGroupRequiredSet = vi.spyOn(mockInputGroup, 'isRequired', 'set'); + inputGroupRequiredGet.mockReturnValue(false); + inputGroupFocusedSpy.mockReturnValue(false); expect(touchedSpy).not.toHaveBeenCalled(); expect(dirtySpy).not.toHaveBeenCalled(); expect(validatorSpy).not.toHaveBeenCalled(); expect(asyncValidatorSpy).not.toHaveBeenCalled(); - touchedSpy.and.returnValue(false); - dirtySpy.and.returnValue(false); + touchedSpy.mockReturnValue(false); + dirtySpy.mockReturnValue(false); mockNgControl.statusChanges.emit(); expect(touchedSpy).toHaveBeenCalledTimes(1); expect(dirtySpy).toHaveBeenCalledTimes(1); // required getter expect(validatorSpy).toHaveBeenCalledTimes(1); - touchedSpy.and.returnValue(true); - dirtySpy.and.returnValue(true); - validatorSpy.and.returnValue(false); - asyncValidatorSpy.and.returnValue(false); + touchedSpy.mockReturnValue(true); + dirtySpy.mockReturnValue(true); + validatorSpy.mockReturnValue(false); + asyncValidatorSpy.mockReturnValue(false); mockNgControl.statusChanges.emit(); expect(validatorSpy).toHaveBeenCalledTimes(3); expect(asyncValidatorSpy).toHaveBeenCalledTimes(1); expect(inputGroupFocusedSpy).not.toHaveBeenCalled(); - validatorSpy.and.returnValue(() => { }); - asyncValidatorSpy.and.returnValue(() => { }); + validatorSpy.mockReturnValue(() => { }); + asyncValidatorSpy.mockReturnValue(() => { }); mockNgControl.statusChanges.emit(); expect(inputGroupFocusedSpy).toHaveBeenCalledTimes(1); expect(inputGroupRequiredSet).not.toHaveBeenCalled(); - inputGroupRequiredGet.and.returnValue(false); - validatorSpy.and.returnValue(() => ({ required: true })); + inputGroupRequiredGet.mockReturnValue(false); + validatorSpy.mockReturnValue(() => ({ required: true })); mockNgControl.statusChanges.emit(); expect(inputGroupFocusedSpy).toHaveBeenCalledTimes(2); expect(inputGroupRequiredSet).toHaveBeenCalledTimes(1); expect(inputGroupRequiredSet).toHaveBeenCalledWith(true); - inputGroupRequiredGet.and.returnValue(true); + inputGroupRequiredGet.mockReturnValue(true); mockNgControl.statusChanges.emit(); expect(inputGroupFocusedSpy).toHaveBeenCalledTimes(3); @@ -284,7 +297,7 @@ describe('IgxTimePicker', () => { mockNgControl.statusChanges.emit(); expect(mockInputDirective.valid).toBe(IgxInputState.INVALID); - inputGroupFocusedSpy.and.returnValue(true); + inputGroupFocusedSpy.mockReturnValue(true); mockNgControl.statusChanges.emit(); expect(mockInputDirective.valid).toBe(IgxInputState.INVALID); @@ -295,35 +308,45 @@ describe('IgxTimePicker', () => { }); it('should open/close the dropdown with open()/close() method', () => { - const mockToggleDirective = jasmine.createSpyObj('IgxToggleDirective', ['open', 'close'], { collapsed: true }); + const mockToggleDirective = { + open: vi.fn().mockName("IgxToggleDirective.open"), + close: vi.fn().mockName("IgxToggleDirective.close"), + collapsed: true + }; (timePicker as any).toggleRef = mockToggleDirective; timePicker.ngOnInit(); timePicker.open(); expect(mockToggleDirective.open).toHaveBeenCalledTimes(1); - (Object.getOwnPropertyDescriptor(mockToggleDirective, 'collapsed')?.get as jasmine.Spy<() => boolean>).and.returnValue(false); + (Object.getOwnPropertyDescriptor(mockToggleDirective, 'collapsed')?.get as Mock).mockReturnValue(false); timePicker.close(); expect(mockToggleDirective.close).toHaveBeenCalledTimes(1); }); it('should open/close the dropdown with toggle() method', () => { (timePicker as any).dateTimeEditor = mockDateTimeEditorDirective; - const mockToggleDirective = jasmine.createSpyObj('IgxToggleDirective', ['open', 'close'], { collapsed: true }); + const mockToggleDirective = { + open: vi.fn().mockName("IgxToggleDirective.open"), + close: vi.fn().mockName("IgxToggleDirective.close"), + collapsed: true + }; (timePicker as any).toggleRef = mockToggleDirective; timePicker.ngOnInit(); timePicker.toggle(); expect(mockToggleDirective.open).toHaveBeenCalledTimes(1); - (Object.getOwnPropertyDescriptor(mockToggleDirective, 'collapsed')?.get as jasmine.Spy<() => boolean>).and.returnValue(false); + (Object.getOwnPropertyDescriptor(mockToggleDirective, 'collapsed')?.get as Mock).mockReturnValue(false); timePicker.toggle(); expect(mockToggleDirective.close).toHaveBeenCalledTimes(1); }); it('should reset value and emit valueChange with clear() method', () => { (timePicker as any).dateTimeEditor = mockDateTimeEditorDirective; - const mockToggleDirective = jasmine.createSpyObj('IgxToggleDirective', { collapsed: true }); + const mockToggleDirective = { + collapsed: vi.fn().mockName("IgxToggleDirective.collapsed").mockReturnValue(true) + }; (timePicker as any).toggleRef = mockToggleDirective; timePicker.minDropdownValue = timePicker.minDateValue; timePicker.maxDropdownValue = timePicker.maxDateValue; @@ -331,7 +354,7 @@ describe('IgxTimePicker', () => { const date = new Date(2020, 12, 12, 10, 30, 30); timePicker.value = new Date(date); date.setHours(0, 0, 0); - spyOn(timePicker.valueChange, 'emit').and.callThrough(); + vi.spyOn(timePicker.valueChange, 'emit'); timePicker.clear(); expect(timePicker.value).toEqual(date); @@ -349,12 +372,14 @@ describe('IgxTimePicker', () => { it('should not emit valueChange when value is \'00:00:00\' and is cleared', () => { (timePicker as any).dateTimeEditor = mockDateTimeEditorDirective; - const mockToggleDirective = jasmine.createSpyObj('IgxToggleDirective', { collapsed: true }); + const mockToggleDirective = { + collapsed: vi.fn().mockName("IgxToggleDirective.collapsed").mockReturnValue(true) + }; (timePicker as any).toggleRef = mockToggleDirective; const date = new Date(2020, 12, 12, 0, 0, 0); timePicker.value = date; - spyOn(timePicker.valueChange, 'emit').and.callThrough(); + vi.spyOn(timePicker.valueChange, 'emit'); timePicker.ngOnInit(); @@ -364,11 +389,13 @@ describe('IgxTimePicker', () => { it('should not emit valueChange when value is null and is cleared', () => { (timePicker as any).dateTimeEditor = mockDateTimeEditorDirective; - const mockToggleDirective = jasmine.createSpyObj('IgxToggleDirective', { collapsed: true }); + const mockToggleDirective = { + collapsed: vi.fn().mockName("IgxToggleDirective.collapsed").mockReturnValue(true) + }; (timePicker as any).toggleRef = mockToggleDirective; timePicker.value = null; timePicker.ngOnInit(); - spyOn(timePicker.valueChange, 'emit').and.callThrough(); + vi.spyOn(timePicker.valueChange, 'emit'); timePicker.clear(); expect(timePicker.valueChange.emit).not.toHaveBeenCalled(); @@ -383,7 +410,7 @@ describe('IgxTimePicker', () => { timePicker.maxDropdownValue = timePicker.maxDateValue; const selectedDate = new Date(2020, 12, 12, 6, 45, 0); - spyOn(timePicker.valueChange, 'emit').and.callThrough(); + vi.spyOn(timePicker.valueChange, 'emit'); timePicker.select(selectedDate); expect(timePicker.value).toEqual(selectedDate); @@ -395,15 +422,18 @@ describe('IgxTimePicker', () => { const date = new Date(2020, 12, 12, 10, 30, 30); const updatedDate = new Date(2020, 12, 12, 11, 30, 30); - const mockToggleDirective = jasmine.createSpyObj('IgxToggleDirective', ['close'], { collapsed: true }); + const mockToggleDirective = { + close: vi.fn().mockName("IgxToggleDirective.close"), + collapsed: true + }; timePicker['dateTimeEditor'] = mockDateTimeEditorDirective; timePicker['inputDirective'] = mockInputDirective; timePicker['toggleRef'] = mockToggleDirective; timePicker.minDropdownValue = timePicker.minDateValue; timePicker.maxDropdownValue = timePicker.maxDateValue; timePicker.ngOnInit(); - spyOn(mockNgControl, 'registerOnChangeCb'); - spyOn(mockNgControl, 'registerOnTouchedCb'); + vi.spyOn(mockNgControl, 'registerOnChangeCb'); + vi.spyOn(mockNgControl, 'registerOnTouchedCb'); timePicker.registerOnChange(mockNgControl.registerOnChangeCb); timePicker.registerOnTouched(mockNgControl.registerOnTouchedCb); @@ -430,8 +460,8 @@ describe('IgxTimePicker', () => { timePicker['inputDirective'] = mockInputDirective; timePicker.ngOnInit(); - spyOn(mockNgControl, 'registerOnChangeCb'); - spyOn(mockNgControl, 'registerOnValidatorChangeCb'); + vi.spyOn(mockNgControl, 'registerOnChangeCb'); + vi.spyOn(mockNgControl, 'registerOnValidatorChangeCb'); timePicker.registerOnChange(mockNgControl.registerOnChangeCb); timePicker.registerOnValidatorChange(mockNgControl.registerOnValidatorChangeCb); @@ -456,18 +486,14 @@ describe('IgxTimePicker', () => { it('should handle panmove event correctly', () => { const touchManager = TestBed.inject(HammerGesturesManager); const itemListDirective = TestBed.inject(IgxItemListDirective); - spyOn(touchManager, 'addEventListener'); + vi.spyOn(touchManager, 'addEventListener'); itemListDirective.ngOnInit(); expect(touchManager.addEventListener).toHaveBeenCalledTimes(1); const hammerOptions: HammerOptions = { recognizers: [[HammerGesturesManager.Hammer.Pan, { direction: HammerGesturesManager.Hammer.DIRECTION_VERTICAL, threshold: 10 }]] }; - expect(touchManager.addEventListener).toHaveBeenCalledWith( - elementRef.nativeElement, - 'pan', - (itemListDirective as any).onPanMove, - hammerOptions); + expect(touchManager.addEventListener).toHaveBeenCalledWith(elementRef.nativeElement, 'pan', (itemListDirective as any).onPanMove, hammerOptions); - spyOn(itemListDirective, 'onPanMove').and.callThrough(); + vi.spyOn(itemListDirective, 'onPanMove'); const event = { type: 'pan' }; (itemListDirective as any).onPanMove(event); expect(itemListDirective['onPanMove']).toHaveBeenCalled(); @@ -508,7 +534,7 @@ describe('IgxTimePicker', () => { secondsColumn = fixture.debugElement.query(By.css(CSS_CLASS_SECONDSLIST)); ampmColumn = fixture.debugElement.query(By.css(`.${CSS_CLASS_AMPMLIST}`)); dateTimeEditor = fixture.debugElement.query(By.directive(IgxDateTimeEditorDirective)). - injector.get(IgxDateTimeEditorDirective); + injector.get(IgxDateTimeEditorDirective); })); it('should open/close the dropdown and keep the current selection on toggle icon click', fakeAsync(() => { const toggleIcon = fixture.debugElement.query(By.css('igx-prefix')); @@ -643,7 +669,8 @@ describe('IgxTimePicker', () => { hourColumn.triggerEventHandler('wheel', event); fixture.detectChanges(); hourColumn.triggerEventHandler('wheel', event); - fixture.detectChanges(); hourColumn.triggerEventHandler('wheel', event); + fixture.detectChanges(); + hourColumn.triggerEventHandler('wheel', event); fixture.detectChanges(); let selectedHour = fixture.componentInstance.date.getHours() + 2; const selectedAmpm = selectedHour < 12 ? 'AM' : 'PM'; @@ -697,10 +724,10 @@ describe('IgxTimePicker', () => { })); it('should fire opening/closing event on open/close', fakeAsync(() => { - spyOn(timePicker.opening, 'emit').and.callThrough(); - spyOn(timePicker.opened, 'emit').and.callThrough(); - spyOn(timePicker.closing, 'emit').and.callThrough(); - spyOn(timePicker.closed, 'emit').and.callThrough(); + vi.spyOn(timePicker.opening, 'emit'); + vi.spyOn(timePicker.opened, 'emit'); + vi.spyOn(timePicker.closing, 'emit'); + vi.spyOn(timePicker.closed, 'emit'); timePicker.open(); tick(); @@ -718,10 +745,10 @@ describe('IgxTimePicker', () => { })); it('should be able to cancel opening/closing events', fakeAsync(() => { - spyOn(timePicker.opening, 'emit').and.callThrough(); - spyOn(timePicker.opened, 'emit').and.callThrough(); - spyOn(timePicker.closing, 'emit').and.callThrough(); - spyOn(timePicker.closed, 'emit').and.callThrough(); + vi.spyOn(timePicker.opening, 'emit'); + vi.spyOn(timePicker.opened, 'emit'); + vi.spyOn(timePicker.closing, 'emit'); + vi.spyOn(timePicker.closed, 'emit'); const openingSub = timePicker.opening.subscribe((event) => event.cancel = true); @@ -758,7 +785,7 @@ describe('IgxTimePicker', () => { timePicker.maxValue = new Date(2020, 12, 12, 16, 0, 0, 0); timePicker.itemsDelta = { hours: 2, minutes: 20, seconds: 15 }; fixture.detectChanges(); - spyOn(timePicker.valueChange, 'emit').and.callThrough(); + vi.spyOn(timePicker.valueChange, 'emit'); timePicker.increment(DatePart.Hours); date.setHours(date.getHours() + timePicker.itemsDelta.hours); @@ -794,7 +821,7 @@ describe('IgxTimePicker', () => { timePicker.maxValue = new Date(2020, 12, 12, 16, 0, 0); timePicker.itemsDelta = { hours: 2, minutes: 20, seconds: 15 }; fixture.detectChanges(); - spyOn(timePicker.validationFailed, 'emit').and.callThrough(); + vi.spyOn(timePicker.validationFailed, 'emit'); timePicker.increment(DatePart.Hours); fixture.detectChanges(); @@ -851,7 +878,7 @@ describe('IgxTimePicker', () => { toggleIcon.triggerEventHandler('click', UIInteractions.getMouseEvent('click')); tick(); fixture.detectChanges(); - expect(timePicker.collapsed).toBeTrue(); + expect(timePicker.collapsed).toBe(true); expect((timePicker.value as Date).getHours()).toEqual(expectedValuedHour); expect((timePicker.value as Date).getMinutes()).toEqual(expectedMinute); @@ -902,7 +929,7 @@ describe('IgxTimePicker', () => { toggleIcon.triggerEventHandler('click', UIInteractions.getMouseEvent('click')); tick(); fixture.detectChanges(); - expect(timePicker.collapsed).toBeTrue(); + expect(timePicker.collapsed).toBe(true); expect((timePicker.value as Date).getHours()).toEqual(expectedValuedHour); expect((timePicker.value as Date).getMinutes()).toEqual(expectedMinute); @@ -1132,7 +1159,7 @@ describe('IgxTimePicker', () => { // ensure there is content in each element of the spinners // '08', '09', '10', '11', '12', '01', '02' - expect(hourColumn.queryAll(By.css('span')).every(e => !!e.nativeElement.innerText)).toBeTrue(); + expect(hourColumn.queryAll(By.css('span')).every(e => !!e.nativeElement.innerText)).toBe(true); // '00', '15', '30', '45', '', '', '' - three empty elements to align the minutes spinner length with the hours spinner length expect(minutesColumn.queryAll(By.css('span')).filter(e => !!e.nativeElement.innerText).length).toEqual(4); @@ -1157,7 +1184,7 @@ describe('IgxTimePicker', () => { minutesColumn = fixture.debugElement.query(By.css(`.${CSS_CLASS_MINUTELIST}`)); ampmColumn = fixture.debugElement.query(By.css(`.${CSS_CLASS_AMPMLIST}`)); dateTimeEditor = fixture.debugElement.query(By.directive(IgxDateTimeEditorDirective)). - injector.get(IgxDateTimeEditorDirective); + injector.get(IgxDateTimeEditorDirective); })); it('Should render default toggle and clear icons', () => { @@ -1165,10 +1192,10 @@ describe('IgxTimePicker', () => { fixture.detectChanges(); inputGroup = fixture.debugElement.query(By.directive(IgxInputGroupComponent)); const prefix = inputGroup.queryAll(By.directive(IgxPrefixDirective)); - expect(prefix).toHaveSize(1); + expect(prefix).toHaveLength(1); expect(prefix[0].nativeElement.innerText).toEqual(TIME_PICKER_TOGGLE_ICON); const suffix = inputGroup.queryAll(By.directive(IgxSuffixDirective)); - expect(suffix).toHaveSize(1); + expect(suffix).toHaveLength(1); expect(suffix[0].nativeElement.innerText).toEqual(TIME_PICKER_CLEAR_ICON); }); @@ -1334,7 +1361,7 @@ describe('IgxTimePicker', () => { expect(dateTimeEditor.inputFormat).toEqual('HH:mm'); })); - it('should display selected time in dialog header', fakeAsync(() => { + it('should display selected time in dialog header', fakeAsync(() => { fixture.componentInstance.timePicker.mode = PickerInteractionMode.Dialog; fixture.detectChanges(); @@ -1514,7 +1541,8 @@ describe('IgxTimePicker', () => { const expectedSecond = '01'; const expectedAmPm = 'PM'; - let item; let selectedItems; + let item; + let selectedItems; item = ampmColumn.queryAll(By.directive(IgxTimeItemDirective))[4]; item.triggerEventHandler('click', UIInteractions.getMouseEvent('click')); tick(); @@ -1566,7 +1594,7 @@ describe('IgxTimePicker', () => { // no placeholder - set to inputFormat, if it is set // test with the different a,aa,.. ampm formats - for(let i = 1; i <= 5; i++) { + for (let i = 1; i <= 5; i++) { const format = `hh:mm ${'a'.repeat(i)}`; timePicker.inputFormat = format; fixture.detectChanges(); @@ -1641,12 +1669,12 @@ describe('IgxTimePicker', () => { })); it('should toggle the dropdown with ALT + DOWN/UP ARROW key', fakeAsync(() => { - spyOn(timePicker.opening, 'emit').and.callThrough(); - spyOn(timePicker.opened, 'emit').and.callThrough(); - spyOn(timePicker.closing, 'emit').and.callThrough(); - spyOn(timePicker.closed, 'emit').and.callThrough(); + vi.spyOn(timePicker.opening, 'emit'); + vi.spyOn(timePicker.opened, 'emit'); + vi.spyOn(timePicker.closing, 'emit'); + vi.spyOn(timePicker.closed, 'emit'); expect(timePicker.collapsed).toBeTruthy(); - expect(timePicker.isFocused).toBeFalse(); + expect(timePicker.isFocused).toBe(false); UIInteractions.triggerEventHandlerKeyDown('ArrowDown', timePickerDebElement, true); @@ -1656,10 +1684,8 @@ describe('IgxTimePicker', () => { expect(timePicker.collapsed).toBeFalsy(); expect(timePicker.opening.emit).toHaveBeenCalledTimes(1); expect(timePicker.opened.emit).toHaveBeenCalledTimes(1); - expect(hourColumn.nativeElement.contains(document.activeElement)) - .withContext('focus should move to hour column for KB nav') - .toBeTrue(); - expect(timePicker.isFocused).toBeTrue(); + expect(hourColumn.nativeElement.contains(document.activeElement), 'focus should move to hour column for KB nav').toBe(true); + expect(timePicker.isFocused).toBe(true); UIInteractions.triggerKeyDownEvtUponElem('ArrowUp', timePickerElement, true, true); tick(); @@ -1667,15 +1693,13 @@ describe('IgxTimePicker', () => { expect(timePicker.collapsed).toBeTruthy(); expect(timePicker.closing.emit).toHaveBeenCalledTimes(1); expect(timePicker.closed.emit).toHaveBeenCalledTimes(1); - expect(inputGroup.nativeElement.contains(document.activeElement)) - .withContext('focus should return to the picker input') - .toBeTrue(); - expect(timePicker.isFocused).toBeTrue(); + expect(inputGroup.nativeElement.contains(document.activeElement), 'focus should return to the picker input').toBe(true); + expect(timePicker.isFocused).toBe(true); })); it('should open the dropdown with SPACE key', fakeAsync(() => { - spyOn(timePicker.opening, 'emit').and.callThrough(); - spyOn(timePicker.opened, 'emit').and.callThrough(); + vi.spyOn(timePicker.opening, 'emit'); + vi.spyOn(timePicker.opened, 'emit'); expect(timePicker.collapsed).toBeTruthy(); UIInteractions.triggerEventHandlerKeyDown(' ', timePickerDebElement); @@ -1688,8 +1712,8 @@ describe('IgxTimePicker', () => { })); it('should close the dropdown with ESC', fakeAsync(() => { - spyOn(timePicker.closing, 'emit').and.callThrough(); - spyOn(timePicker.closed, 'emit').and.callThrough(); + vi.spyOn(timePicker.closing, 'emit'); + vi.spyOn(timePicker.closed, 'emit'); expect(timePicker.collapsed).toBeTruthy(); timePicker.open(); @@ -1724,18 +1748,18 @@ describe('IgxTimePicker', () => { inputGroup = fixture.debugElement.query(By.directive(IgxInputGroupComponent)); const label = inputGroup.queryAll(By.directive(IgxLabelDirective)); - expect(label).toHaveSize(1); + expect(label).toHaveLength(1); expect(label[0].nativeElement.innerText).toEqual('Label'); const hint = inputGroup.queryAll(By.directive(IgxHintDirective)); - expect(hint).toHaveSize(1); + expect(hint).toHaveLength(1); expect(hint[0].nativeElement.innerText).toEqual('Hint'); const prefix = inputGroup.queryAll(By.directive(IgxPrefixDirective)); - expect(prefix).toHaveSize(2); + expect(prefix).toHaveLength(2); expect(prefix[0].nativeElement.innerText).toEqual(TIME_PICKER_TOGGLE_ICON); expect(prefix[1].nativeElement.innerText).toEqual('Prefix'); const suffix = inputGroup.queryAll(By.directive(IgxSuffixDirective)); - expect(suffix).toHaveSize(2); + expect(suffix).toHaveLength(2); expect(suffix[0].nativeElement.innerText).toEqual(TIME_PICKER_CLEAR_ICON); expect(suffix[1].nativeElement.innerText).toEqual('Suffix'); }); @@ -1748,11 +1772,11 @@ describe('IgxTimePicker', () => { inputGroup = fixture.debugElement.query(By.directive(IgxInputGroupComponent)); const prefix = inputGroup.queryAll(By.directive(IgxPrefixDirective)); - expect(prefix).toHaveSize(2); + expect(prefix).toHaveLength(2); expect(prefix[0].nativeElement.innerText).toEqual('CustomToggle'); expect(prefix[1].nativeElement.innerText).toEqual('Prefix'); const suffix = inputGroup.queryAll(By.directive(IgxSuffixDirective)); - expect(suffix).toHaveSize(2); + expect(suffix).toHaveLength(2); expect(suffix[0].nativeElement.innerText).toEqual('CustomClear'); expect(suffix[1].nativeElement.innerText).toEqual('Suffix'); }); @@ -1763,8 +1787,8 @@ describe('IgxTimePicker', () => { fixture.componentInstance.showCustomClear = true; fixture.componentInstance.showCustomToggle = true; fixture.detectChanges(); - spyOn(timePicker, 'open'); - spyOn(timePicker, 'clear'); + vi.spyOn(timePicker, 'open'); + vi.spyOn(timePicker, 'clear'); inputGroup = fixture.debugElement.query(By.directive(IgxInputGroupComponent)); const toggleElem = inputGroup.query(By.directive(IgxPickerToggleComponent)); @@ -1772,9 +1796,11 @@ describe('IgxTimePicker', () => { let toggle = fixture.componentInstance.customToggle; let clear = fixture.componentInstance.customClear; - expect(toggle.clicked.observers).toHaveSize(1); - expect(clear.clicked.observers).toHaveSize(1); - const event = jasmine.createSpyObj('event', ['stopPropagation']); + expect(toggle.clicked.observers).toHaveLength(1); + expect(clear.clicked.observers).toHaveLength(1); + const event = { + stopPropagation: vi.fn().mockName("event.stopPropagation") + }; toggleElem.triggerEventHandler('click', event); expect(timePicker.open).toHaveBeenCalledTimes(1); clearElem.triggerEventHandler('click', event); @@ -1783,12 +1809,12 @@ describe('IgxTimePicker', () => { // hide fixture.componentInstance.showCustomToggle = false; fixture.detectChanges(); - expect(toggle.clicked.observers).toHaveSize(0); - expect(clear.clicked.observers).toHaveSize(1); + expect(toggle.clicked.observers).toHaveLength(0); + expect(clear.clicked.observers).toHaveLength(1); fixture.componentInstance.showCustomClear = false; fixture.detectChanges(); - expect(toggle.clicked.observers).toHaveSize(0); - expect(clear.clicked.observers).toHaveSize(0); + expect(toggle.clicked.observers).toHaveLength(0); + expect(clear.clicked.observers).toHaveLength(0); // show again fixture.componentInstance.showCustomClear = true; @@ -1796,12 +1822,12 @@ describe('IgxTimePicker', () => { fixture.detectChanges(); toggle = fixture.componentInstance.customToggle; clear = fixture.componentInstance.customClear; - expect(toggle.clicked.observers).toHaveSize(1); - expect(clear.clicked.observers).toHaveSize(1); + expect(toggle.clicked.observers).toHaveLength(1); + expect(clear.clicked.observers).toHaveLength(1); timePicker.ngOnDestroy(); - expect(toggle.clicked.observers).toHaveSize(0); - expect(clear.clicked.observers).toHaveSize(0); + expect(toggle.clicked.observers).toHaveLength(0); + expect(clear.clicked.observers).toHaveLength(0); }); }); @@ -1926,7 +1952,7 @@ describe('IgxTimePicker', () => { // no validator, but there is a set error expect((timePicker as any).inputDirective.valid).toBe(IgxInputState.INVALID); - expect((timePicker as any).inputGroup.element.nativeElement).toHaveClass(CSS_CLASS_INPUT_GROUP_INVALID); + expect((timePicker as any).inputGroup.element.nativeElement.classList.contains(CSS_CLASS_INPUT_GROUP_INVALID)).toBe(true); expect((timePicker as any).inputGroup.element.nativeElement.classList.contains(CSS_CLASS_INPUT_GROUP_REQUIRED)).toBe(false); }); }); @@ -1967,9 +1993,12 @@ export class IgxTimePickerTestComponent { imports: [IgxTimePickerComponent, IgxPickerToggleComponent, IgxPickerClearComponent, IgxLabelDirective, IgxPrefixDirective, IgxSuffixDirective, IgxHintDirective] }) export class IgxTimePickerWithProjectionsComponent { - @ViewChild(IgxTimePickerComponent) public timePicker: IgxTimePickerComponent; - @ViewChild(IgxPickerToggleComponent) public customToggle: IgxPickerToggleComponent; - @ViewChild(IgxPickerClearComponent) public customClear: IgxPickerClearComponent; + @ViewChild(IgxTimePickerComponent) + public timePicker: IgxTimePickerComponent; + @ViewChild(IgxPickerToggleComponent) + public customToggle: IgxPickerToggleComponent; + @ViewChild(IgxPickerClearComponent) + public customClear: IgxPickerClearComponent; public mode: PickerInteractionMode = PickerInteractionMode.DropDown; public showCustomToggle = false; public showCustomClear = false; diff --git a/projects/igniteui-angular/toast/src/toast/toast.component.spec.ts b/projects/igniteui-angular/toast/src/toast/toast.component.spec.ts index 72640693dcc..f8ef9f2ad28 100644 --- a/projects/igniteui-angular/toast/src/toast/toast.component.spec.ts +++ b/projects/igniteui-angular/toast/src/toast/toast.component.spec.ts @@ -1,15 +1,9 @@ -import { - waitForAsync, - TestBed, - ComponentFixture, - flushMicrotasks, - fakeAsync, -} from '@angular/core/testing'; +import { waitForAsync, TestBed, ComponentFixture, flushMicrotasks, fakeAsync, } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { - IgxToastComponent -} from './toast.component'; -import { HorizontalAlignment, PositionSettings, VerticalAlignment } from 'igniteui-angular/core';; +import { IgxToastComponent } from './toast.component'; +import { HorizontalAlignment, PositionSettings, VerticalAlignment } from 'igniteui-angular/core'; +import { describe, it, expect, beforeEach, vi } from 'vitest'; +; describe('IgxToast', () => { let fixture: ComponentFixture; @@ -53,14 +47,15 @@ describe('IgxToast', () => { }); it('should properly toggle and emit isVisibleChange', fakeAsync(() => { - spyOn(toast.isVisibleChange, 'emit').and.callThrough(); + vi.spyOn(toast.isVisibleChange, 'emit'); expect(toast.isVisible).toBe(false); expect(toast.isVisibleChange.emit).toHaveBeenCalledTimes(0); toast.toggle(); expect(toast.isVisible).toBe(true); flushMicrotasks(); - expect(toast.isVisibleChange.emit).toHaveBeenCalledOnceWith({ owner: toast, id: '0' }); + expect(toast.isVisibleChange.emit).toHaveBeenCalledTimes(1); + expect(toast.isVisibleChange.emit).toHaveBeenCalledWith({ owner: toast, id: '0' }); toast.toggle(); flushMicrotasks(); diff --git a/projects/igniteui-angular/tree/src/tree/tree-functions.spec.ts b/projects/igniteui-angular/tree/src/tree/tree-functions.spec.ts index 51341ef59cb..7a5a2b1d53a 100644 --- a/projects/igniteui-angular/tree/src/tree/tree-functions.spec.ts +++ b/projects/igniteui-angular/tree/src/tree/tree-functions.spec.ts @@ -1,3 +1,5 @@ +import type { MockedObject } from "vitest"; +import { expect, vi } from 'vitest'; import { EventEmitter, QueryList } from '@angular/core'; import { ComponentFixture } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; @@ -65,24 +67,29 @@ export class TreeTestFunctions { } } - public static createNodeSpy( - properties: { [key: string]: any } = null, - methodNames: (keyof IgxTreeNode)[] = ['selected']): jasmine.SpyObj> { - if (!properties) { - return jasmine.createSpyObj>(methodNames); + public static createNodeSpy(properties: { + [key: string]: any; + } = null, methodNames: (keyof IgxTreeNode)[] = ['selected']): MockedObject> { + const spy: any = {}; + + // Create mock functions for each method name + methodNames.forEach(methodName => { + spy[methodName] = vi.fn().mockName(String(methodName)); + }); + + // Add properties if provided + if (properties) { + Object.assign(spy, properties); } - return jasmine.createSpyObj>(methodNames, properties); + + return spy as MockedObject>; } - public static createNodeSpies( - level: number, - count: number, - parentNode?: IgxTreeNodeComponent, - children?: any[], - allChildren?: any[] - ): IgxTreeNodeComponent[] { + public static createNodeSpies(level: number, count: number, parentNode?: IgxTreeNodeComponent, children?: any[], allChildren?: any[]): IgxTreeNodeComponent[] { const nodesArr = []; - const mockEmitter: EventEmitter = jasmine.createSpyObj('emitter', ['emit']); + const mockEmitter: any = { + emit: vi.fn().mockName("emitter.emit") + }; for (let i = 0; i < count; i++) { nodesArr.push(this.createNodeSpy({ level, @@ -99,14 +106,18 @@ export class TreeTestFunctions { return nodesArr; } - public static createQueryListSpy(nodes: IgxTreeNodeComponent[]): jasmine.SpyObj>> { - const mockQuery = jasmine.createSpyObj(['toArray', 'filter', 'forEach']); + public static createQueryListSpy(nodes: IgxTreeNodeComponent[]): MockedObject>> { + const mockQuery = { + toArray: vi.fn(), + filter: vi.fn(), + forEach: vi.fn() + }; Object.defineProperty(mockQuery, 'first', { value: nodes[0], enumerable: true }); Object.defineProperty(mockQuery, 'last', { value: nodes[nodes.length - 1], enumerable: true }); Object.defineProperty(mockQuery, 'length', { value: nodes.length, enumerable: true }); - mockQuery.toArray.and.returnValue(nodes); - mockQuery.filter.and.callFake((cb) => nodes.filter(cb)); - mockQuery.forEach.and.callFake((cb) => nodes.forEach(cb)); + mockQuery.toArray.mockReturnValue(nodes); + mockQuery.filter.mockImplementation((cb) => nodes.filter(cb)); + mockQuery.forEach.mockImplementation((cb) => nodes.forEach(cb)); return mockQuery; } } diff --git a/projects/igniteui-angular/tree/src/tree/tree-navigation.spec.ts b/projects/igniteui-angular/tree/src/tree/tree-navigation.spec.ts index 88edbd5b540..d6ac9a7a685 100644 --- a/projects/igniteui-angular/tree/src/tree/tree-navigation.spec.ts +++ b/projects/igniteui-angular/tree/src/tree/tree-navigation.spec.ts @@ -1,3 +1,5 @@ +import type { Mock } from "vitest"; +import { describe, it, expect, beforeEach, vi } from 'vitest'; import { waitForAsync, TestBed, fakeAsync, tick } from '@angular/core/testing'; import { IgxTreeNavigationComponent, IgxTreeScrollComponent, IgxTreeSimpleComponent } from './tree-samples.spec'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; @@ -61,7 +63,7 @@ describe('IgxTree - Navigation #treeView', () => { }); it('Should focus/activate correct node on ArrowDown/ArrowUp (+ Ctrl) key pressed', () => { - spyOn(tree.activeNodeChanged, 'emit').and.callThrough(); + vi.spyOn(tree.activeNodeChanged, 'emit'); tree.nodes.first.header.nativeElement.dispatchEvent(new Event('pointerdown')); fix.detectChanges(); @@ -101,7 +103,7 @@ describe('IgxTree - Navigation #treeView', () => { }); it('Should focus and activate the first/last visible node on Home/End key press', () => { - spyOn(tree.activeNodeChanged, 'emit').and.callThrough(); + vi.spyOn(tree.activeNodeChanged, 'emit'); tree.nodes.first.expand(); fix.detectChanges(); tree.nodes.toArray()[2].header.nativeElement.dispatchEvent(new Event('pointerdown')); @@ -123,7 +125,7 @@ describe('IgxTree - Navigation #treeView', () => { }); it('Should collapse/navigate to correct node on Arrow left key press', fakeAsync(() => { - spyOn(tree.activeNodeChanged, 'emit').and.callThrough(); + vi.spyOn(tree.activeNodeChanged, 'emit'); // If node is collapsed and has no parents the focus and activation should not be moved on Arrow left key press tree.nodes.first.header.nativeElement.dispatchEvent(new Event('pointerdown')); tick(); @@ -164,7 +166,7 @@ describe('IgxTree - Navigation #treeView', () => { })); it('Should expand/navigate to correct node on Arrow right key press', () => { - spyOn(tree.activeNodeChanged, 'emit').and.callThrough(); + vi.spyOn(tree.activeNodeChanged, 'emit'); // If node has no children the focus and activation should not be moved on Arrow right key press tree.nodes.last.header.nativeElement.dispatchEvent(new Event('pointerdown')); fix.detectChanges(); @@ -215,7 +217,7 @@ describe('IgxTree - Navigation #treeView', () => { }); it('Pressing Enter should activate the focused node and not prevent the keydown event`s deafault behavior', () => { - spyOn(tree.activeNodeChanged, 'emit').and.callThrough(); + vi.spyOn(tree.activeNodeChanged, 'emit'); tree.nodes.first.header.nativeElement.dispatchEvent(new Event('pointerdown')); fix.detectChanges(); @@ -223,7 +225,7 @@ describe('IgxTree - Navigation #treeView', () => { fix.detectChanges(); const mockEvent = new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }); - spyOn(mockEvent, 'preventDefault'); + vi.spyOn(mockEvent, 'preventDefault'); tree.nodes.toArray()[17].nativeElement.dispatchEvent(mockEvent); expect(mockEvent.preventDefault).not.toHaveBeenCalled(); @@ -233,7 +235,7 @@ describe('IgxTree - Navigation #treeView', () => { }); it('Should correctly set node`s selection state on Space key press', () => { - spyOn(tree.activeNodeChanged, 'emit').and.callThrough(); + vi.spyOn(tree.activeNodeChanged, 'emit'); // Space on None Selection Mode tree.selection = 'None'; tree.nodes.first.header.nativeElement.dispatchEvent(new Event('pointerdown')); @@ -242,9 +244,9 @@ describe('IgxTree - Navigation #treeView', () => { UIInteractions.triggerKeyDownEvtUponElem('arrowdown', tree.nodes.first.nativeElement, true, false, false, true); fix.detectChanges(); - spyOn((tree as any).selectionService, 'selectNode').and.callThrough(); - spyOn((tree as any).selectionService, 'deselectNode').and.callThrough(); - spyOn((tree as any).selectionService, 'selectMultipleNodes').and.callThrough(); + vi.spyOn((tree as any).selectionService, 'selectNode'); + vi.spyOn((tree as any).selectionService, 'deselectNode'); + vi.spyOn((tree as any).selectionService, 'selectMultipleNodes'); UIInteractions.triggerKeyDownEvtUponElem('space', tree.nodes.toArray()[17].nativeElement); fix.detectChanges(); @@ -602,8 +604,7 @@ describe('IgxTree - Navigation #treeView', () => { navService?.ngOnDestroy(); //navService = new IgxTreeNavigationService(); mockNodesLevel1 = TreeTestFunctions.createNodeSpies(0, 3, null, [mockQuery2, mockQuery3, []], [mockQuery6, mockQuery3, []]); - mockNodesLevel2_1 = TreeTestFunctions.createNodeSpies(1, 2, - mockNodesLevel1[0], [mockQuery4, mockQuery5], [mockQuery4, mockQuery5]); + mockNodesLevel2_1 = TreeTestFunctions.createNodeSpies(1, 2, mockNodesLevel1[0], [mockQuery4, mockQuery5], [mockQuery4, mockQuery5]); mockNodesLevel2_2 = TreeTestFunctions.createNodeSpies(1, 1, mockNodesLevel1[1], [[]]); mockNodesLevel3_1 = TreeTestFunctions.createNodeSpies(2, 2, mockNodesLevel2_1[0], [[], []]); mockNodesLevel3_2 = TreeTestFunctions.createNodeSpies(2, 2, mockNodesLevel2_1[1], [[], []]); @@ -635,9 +636,14 @@ describe('IgxTree - Navigation #treeView', () => { describe('IgxNavigationService', () => { beforeEach(() => { - mockEmitter = jasmine.createSpyObj('emitter', ['emit']); - mockTree = jasmine.createSpyObj('tree', [''], - { selection: IgxTreeSelectionType.BiState, activeNodeChanged: mockEmitter, nodes: mockQuery1 }); + mockEmitter = { + emit: vi.fn() + } as unknown as EventEmitter>; + mockTree = { + selection: IgxTreeSelectionType.BiState, + activeNodeChanged: mockEmitter, + nodes: mockQuery1 + } as unknown as IgxTree; TestBed.configureTestingModule({ providers: [ @@ -663,18 +669,15 @@ describe('IgxTree - Navigation #treeView', () => { navService.init_invisible_cache(); expect(navService.visibleChildren.length).toEqual(3); - (Object.getOwnPropertyDescriptor(allNodes[0], 'expanded').get as jasmine.Spy) - .and.returnValue(true); + (Object.getOwnPropertyDescriptor(allNodes[0], 'expanded').get as Mock).mockReturnValue(true); navService.init_invisible_cache(); expect(navService.visibleChildren.length).toEqual(5); - (Object.getOwnPropertyDescriptor(allNodes[0], 'disabled').get as jasmine.Spy) - .and.returnValue(true); + (Object.getOwnPropertyDescriptor(allNodes[0], 'disabled').get as Mock).mockReturnValue(true); navService.update_disabled_cache(allNodes[0]); expect(navService.visibleChildren.length).toEqual(4); allNodes.forEach(e => { - (Object.getOwnPropertyDescriptor(e, 'disabled').get as jasmine.Spy) - .and.returnValue(true); + (Object.getOwnPropertyDescriptor(e, 'disabled').get as Mock).mockReturnValue(true); navService.update_disabled_cache(e); }); expect(navService.visibleChildren.length).toEqual(0); @@ -687,14 +690,18 @@ describe('IgxTree - Navigation #treeView', () => { const someNode = { tabIndex: null, header: { - nativeElement: jasmine.createSpyObj('nativeElement', ['focus']) + nativeElement: { + focus: vi.fn().mockName("nativeElement.focus") + } } } as any; const someNode2 = { tabIndex: null, header: { - nativeElement: jasmine.createSpyObj('nativeElement', ['focus']) + nativeElement: { + focus: vi.fn().mockName("nativeElement.focus") + } } } as any; @@ -726,8 +733,8 @@ describe('IgxTree - Navigation #treeView', () => { navService.register(mockTree); navService.init_invisible_cache(); const mockEvent1 = new KeyboardEvent('keydown', { key: 'arrowdown', bubbles: true }); - spyOn(mockEvent1, 'preventDefault'); - spyOn(navService, 'handleKeydown').and.callThrough(); + vi.spyOn(mockEvent1, 'preventDefault'); + vi.spyOn(navService, 'handleKeydown'); navService.focusedNode = mockNodesLevel1[0]; navService.handleKeydown(mockEvent1); @@ -737,7 +744,7 @@ describe('IgxTree - Navigation #treeView', () => { expect(navService.focusedNode).toEqual(mockNodesLevel1[1]); const mockEvent2 = new KeyboardEvent('keydown', { key: 'arrowup', bubbles: true }); - spyOn(mockEvent2, 'preventDefault'); + vi.spyOn(mockEvent2, 'preventDefault'); navService.handleKeydown(mockEvent2); expect(mockEvent2.preventDefault).toHaveBeenCalled(); @@ -745,7 +752,7 @@ describe('IgxTree - Navigation #treeView', () => { expect(navService.focusedNode).toEqual(mockNodesLevel1[0]); const mockEvent3 = new KeyboardEvent('keydown', { key: 'arrowdown', bubbles: true, repeat: true }); - spyOn(mockEvent3, 'preventDefault'); + vi.spyOn(mockEvent3, 'preventDefault'); // when event is repeated, prevent default and wait navService.handleKeydown(mockEvent3); expect(navService.handleKeydown).toHaveBeenCalledTimes(3); @@ -758,7 +765,7 @@ describe('IgxTree - Navigation #treeView', () => { // does nothing if there is no focused node navService.focusedNode = null; const mockEvent4 = new KeyboardEvent('keydown', { key: 'arrowdown', bubbles: true, repeat: false }); - spyOn(mockEvent4, 'preventDefault'); + vi.spyOn(mockEvent4, 'preventDefault'); navService.handleKeydown(mockEvent4); expect(mockEvent4.preventDefault).not.toHaveBeenCalled(); @@ -769,22 +776,35 @@ describe('IgxTree - Navigation #treeView', () => { }); it('Should update visible children on all relevant tree events', () => { - const mockTreeService = jasmine.createSpyObj('mockSelection', - ['register', 'collapse', 'expand', 'collapsing'], { - collapsingNodes: jasmine.createSpyObj>>('mockCollpasingSet', - ['add', 'delete', 'has'], { + const mockTreeService = { + register: vi.fn().mockName("mockSelection.register"), + collapse: vi.fn().mockName("mockSelection.collapse"), + expand: vi.fn().mockName("mockSelection.expand"), + collapsing: vi.fn().mockName("mockSelection.collapsing"), + collapsingNodes: { + add: vi.fn().mockName("mockCollpasingSet.add"), + delete: vi.fn().mockName("mockCollpasingSet.delete"), + has: vi.fn().mockName("mockCollpasingSet.has"), size: 0 - }), - expandedNodes: jasmine.createSpyObj>>('mockExpandedSet', - ['add', 'delete', 'has'], { + }, + expandedNodes: { + add: vi.fn().mockName("mockExpandedSet.add"), + delete: vi.fn().mockName("mockExpandedSet.delete"), + has: vi.fn().mockName("mockExpandedSet.has"), size: 0 - }), - }); - const mockElementRef = jasmine.createSpyObj('mockElement', ['nativeElement'], { + } + }; + const mockElementRef = { + nativeElement: vi.fn().mockName("mockElement.nativeElement"), nativeElement: document.createElement('div') - }); - const mockSelectionService = jasmine.createSpyObj('mockSelection', - ['selectNodesWithNoEvent', 'selectMultipleNodes', 'deselectNode', 'selectNode', 'register']); + }; + const mockSelectionService = { + selectNodesWithNoEvent: vi.fn().mockName("mockSelection.selectNodesWithNoEvent"), + selectMultipleNodes: vi.fn().mockName("mockSelection.selectMultipleNodes"), + deselectNode: vi.fn().mockName("mockSelection.deselectNode"), + selectNode: vi.fn().mockName("mockSelection.selectNode"), + register: vi.fn().mockName("mockSelection.register") + }; TestBed.resetTestingModule(); TestBed.configureTestingModule({ @@ -802,11 +822,14 @@ describe('IgxTree - Navigation #treeView', () => { const lvl1Nodes = TreeTestFunctions.createNodeSpies(0, 5); const mockQuery = TreeTestFunctions.createQueryListSpy(lvl1Nodes); Object.assign(mockQuery, { changes: new EventEmitter() }); - spyOn(nav, 'init_invisible_cache'); - spyOn(nav, 'update_disabled_cache'); - spyOn(nav, 'update_visible_cache'); - spyOn(nav, 'register'); - const mockPlatform = jasmine.createSpyObj('platform', ['isBrowser', 'isServer']); + vi.spyOn(nav, 'init_invisible_cache'); + vi.spyOn(nav, 'update_disabled_cache'); + vi.spyOn(nav, 'update_visible_cache'); + vi.spyOn(nav, 'register'); + const mockPlatform = { + isBrowser: vi.fn().mockName("platform.isBrowser"), + isServer: vi.fn().mockName("platform.isServer") + }; const tree = TestBed.inject(IgxTreeComponent, mockPlatform); tree.nodes = mockQuery; expect(nav.register).toHaveBeenCalledWith(tree); @@ -861,6 +884,3 @@ describe('IgxTree - Navigation #treeView', () => { }); }); }); - - - diff --git a/projects/igniteui-angular/tree/src/tree/tree-samples.spec.ts b/projects/igniteui-angular/tree/src/tree/tree-samples.spec.ts index 6d98bc70ed2..fa11156a274 100644 --- a/projects/igniteui-angular/tree/src/tree/tree-samples.spec.ts +++ b/projects/igniteui-angular/tree/src/tree/tree-samples.spec.ts @@ -27,7 +27,8 @@ import { IgxIconComponent } from 'igniteui-angular/icon'; imports: [IgxTreeComponent, IgxTreeNodeComponent] }) export class IgxTreeSimpleComponent { - @ViewChild(IgxTreeComponent, { static: true }) public tree: IgxTreeComponent; + @ViewChild(IgxTreeComponent, { static: true }) + public tree: IgxTreeComponent; public data = HIERARCHICAL_SAMPLE_DATA; } @@ -56,7 +57,8 @@ export class IgxTreeSimpleComponent { export class IgxTreeSelectionSampleComponent { public cdr = inject(ChangeDetectorRef); - @ViewChild(IgxTreeComponent, { static: true }) public tree: IgxTreeComponent; + @ViewChild(IgxTreeComponent, { static: true }) + public tree: IgxTreeComponent; public data; constructor() { this.data = HIERARCHICAL_SAMPLE_DATA; @@ -127,7 +129,8 @@ export class IgxTreeSelectionSampleComponent { imports: [IgxTreeComponent, IgxTreeNodeComponent, IgxTreeNodeLinkDirective, NgTemplateOutlet] }) export class IgxTreeNavigationComponent { - @ViewChild(IgxTreeComponent, { static: true }) public tree: IgxTreeComponent; + @ViewChild(IgxTreeComponent, { static: true }) + public tree: IgxTreeComponent; public data = HIERARCHICAL_SAMPLE_DATA; public showNodesWithDirective = false; public isDisabled = false; @@ -158,6 +161,7 @@ export class IgxTreeNavigationComponent { imports: [IgxTreeComponent, IgxTreeNodeComponent, IgxTreeExpandIndicatorDirective, IgxIconComponent] }) export class IgxTreeScrollComponent { - @ViewChild(IgxTreeComponent, { static: true }) public tree: IgxTreeComponent; + @ViewChild(IgxTreeComponent, { static: true }) + public tree: IgxTreeComponent; public data = HIERARCHICAL_SAMPLE_DATA; } diff --git a/projects/igniteui-angular/tree/src/tree/tree-selection.service.spec.ts b/projects/igniteui-angular/tree/src/tree/tree-selection.service.spec.ts index 82d8162c187..6f2533a2607 100644 --- a/projects/igniteui-angular/tree/src/tree/tree-selection.service.spec.ts +++ b/projects/igniteui-angular/tree/src/tree/tree-selection.service.spec.ts @@ -1,3 +1,5 @@ +import type { Mock } from "vitest"; +import { describe, it, expect, beforeEach, vi } from 'vitest'; import { EventEmitter } from '@angular/core'; import { IgxTree, IgxTreeNode, IgxTreeSelectionType, ITreeNodeSelectionEvent } from './common'; import { TreeTestFunctions } from './tree-functions.spec'; @@ -54,9 +56,12 @@ describe('IgxTreeSelectionService - Unit Tests #treeView', () => { describe('IgxTreeSelectionService - BiState & None', () => { beforeEach(() => { - mockEmitter = jasmine.createSpyObj('emitter', ['emit']); - mockTree = jasmine.createSpyObj('tree', [''], - { selection: IgxTreeSelectionType.BiState, nodeSelection: mockEmitter, nodes: mockQuery1 }); + mockEmitter = { + emit: vi.fn().mockName("emitter.emit") + }; + mockTree = { + selection: IgxTreeSelectionType.BiState, nodeSelection: mockEmitter, nodes: mockQuery1 + }; selectionService.register(mockTree); }); @@ -74,7 +79,7 @@ describe('IgxTreeSelectionService - Unit Tests #treeView', () => { expect(selectionSet.size).toBe(0); - spyOn(selectionSet, 'clear').and.callThrough(); + vi.spyOn(selectionSet, 'clear'); const mockNode1 = TreeTestFunctions.createNodeSpy(); const mockNode2 = TreeTestFunctions.createNodeSpy(); @@ -96,19 +101,20 @@ describe('IgxTreeSelectionService - Unit Tests #treeView', () => { }); it('Should handle selection based on tree.selection', () => { - const mockSelectedChangeEmitter: EventEmitter = jasmine.createSpyObj('emitter', ['emit']); + const mockSelectedChangeEmitter: EventEmitter = { + emit: vi.fn().mockName("emitter.emit") + }; const mockNode = TreeTestFunctions.createNodeSpy({ selectedChange: mockSelectedChangeEmitter }); // None - (Object.getOwnPropertyDescriptor(mockTree, 'selection').get as jasmine.Spy).and.returnValue(IgxTreeSelectionType.None); + (Object.getOwnPropertyDescriptor(mockTree, 'selection').get as Mock).mockReturnValue(IgxTreeSelectionType.None); selectionService.selectNode(mockNode); expect(selectionService.isNodeSelected(mockNode)).toBeFalsy(); expect(mockTree.nodeSelection.emit).not.toHaveBeenCalled(); expect(mockNode.selectedChange.emit).not.toHaveBeenCalled(); // BiState - (Object.getOwnPropertyDescriptor(mockTree, 'selection').get as jasmine.Spy) - .and.returnValue(IgxTreeSelectionType.BiState); + (Object.getOwnPropertyDescriptor(mockTree, 'selection').get as Mock).mockReturnValue(IgxTreeSelectionType.BiState); let expected: ITreeNodeSelectionEvent = { oldSelection: [], newSelection: [mockNode], added: [mockNode], removed: [], event: undefined, cancel: false, owner: mockTree @@ -125,8 +131,7 @@ describe('IgxTreeSelectionService - Unit Tests #treeView', () => { // Cascading selectionService.deselectNode(mockNode); - (Object.getOwnPropertyDescriptor(mockTree, 'selection').get as jasmine.Spy) - .and.returnValue(IgxTreeSelectionType.Cascading); + (Object.getOwnPropertyDescriptor(mockTree, 'selection').get as Mock).mockReturnValue(IgxTreeSelectionType.Cascading); selectionService.selectNode(allNodes[1]); expected = { @@ -147,7 +152,9 @@ describe('IgxTreeSelectionService - Unit Tests #treeView', () => { }); it('Should deselect nodes', () => { - const mockSelectedChangeEmitter: EventEmitter = jasmine.createSpyObj('emitter', ['emit']); + const mockSelectedChangeEmitter: EventEmitter = { + emit: vi.fn().mockName("emitter.emit") + }; const mockNode1 = TreeTestFunctions.createNodeSpy({ selectedChange: mockSelectedChangeEmitter }); const mockNode2 = TreeTestFunctions.createNodeSpy({ selectedChange: mockSelectedChangeEmitter }); @@ -366,9 +373,12 @@ describe('IgxTreeSelectionService - Unit Tests #treeView', () => { describe('IgxTreeSelectionService - Cascading', () => { beforeEach(() => { - mockEmitter = jasmine.createSpyObj('emitter', ['emit']); - mockTree = jasmine.createSpyObj('tree', [''], - { selection: IgxTreeSelectionType.Cascading, nodeSelection: mockEmitter, nodes: mockQuery1 }); + mockEmitter = { + emit: vi.fn().mockName("emitter.emit") + }; + mockTree = { + selection: IgxTreeSelectionType.Cascading, nodeSelection: mockEmitter, nodes: mockQuery1 + }; selectionService.register(mockTree); }); @@ -405,7 +415,7 @@ describe('IgxTreeSelectionService - Unit Tests #treeView', () => { expect(node.selectedChange.emit).toHaveBeenCalled(); expect(node.selectedChange.emit).toHaveBeenCalledWith(false); } - expect(selectionService.isNodeIndeterminate(allNodes[0])).toBeFalse(); + expect(selectionService.isNodeIndeterminate(allNodes[0])).toBe(false); expect(mockTree.nodeSelection.emit).toHaveBeenCalledTimes(2); expect(mockTree.nodeSelection.emit).toHaveBeenCalledWith(expected); }); @@ -583,13 +593,13 @@ describe('IgxTreeSelectionService - Unit Tests #treeView', () => { it('Should ensure correct state after a node entry is destroyed', () => { // instant frames go 'BRRRR' - spyOn(window, 'requestAnimationFrame').and.callFake((callback: any) => callback()); - const deselectSpy = spyOn(selectionService, 'deselectNodesWithNoEvent'); - const selectSpy = spyOn(selectionService, 'selectNodesWithNoEvent'); + vi.spyOn(window, 'requestAnimationFrame').mockImplementation((callback: any) => callback()); + const deselectSpy = vi.spyOn(selectionService, 'deselectNodesWithNoEvent'); + const selectSpy = vi.spyOn(selectionService, 'selectNodesWithNoEvent'); const tree = { selection: IgxTreeSelectionType.None } as any; - const selectedNodeSpy = spyOn(selectionService, 'isNodeSelected').and.returnValue(false); + const selectedNodeSpy = vi.spyOn(selectionService, 'isNodeSelected').mockReturnValue(false); const mockNode = { selected: false } as any; @@ -606,7 +616,7 @@ describe('IgxTreeSelectionService - Unit Tests #treeView', () => { expect(selectSpy).not.toHaveBeenCalled(); expect(selectedNodeSpy).not.toHaveBeenCalled(); tree.selection = IgxTreeSelectionType.Cascading; - selectedNodeSpy.and.returnValue(true); + selectedNodeSpy.mockReturnValue(true); selectionService.ensureStateOnNodeDelete(mockNode); expect(selectedNodeSpy).toHaveBeenCalledTimes(1); @@ -615,14 +625,16 @@ describe('IgxTreeSelectionService - Unit Tests #treeView', () => { expect(deselectSpy).toHaveBeenCalledWith([mockNode], false); expect(selectSpy).not.toHaveBeenCalled(); mockNode.parentNode = false; - selectedNodeSpy.and.returnValue(false); + selectedNodeSpy.mockReturnValue(false); selectionService.ensureStateOnNodeDelete(mockNode); expect(selectedNodeSpy).toHaveBeenCalledTimes(2); expect(deselectSpy).toHaveBeenCalledTimes(1); expect(selectSpy).not.toHaveBeenCalled(); - const childrenSpy = jasmine.createSpyObj('creep', ['find']); - childrenSpy.find.and.returnValue(null); + const childrenSpy = { + find: vi.fn().mockName("creep.find") + }; + childrenSpy.find.mockReturnValue(null); mockNode.parentNode = { allChildren: childrenSpy }; @@ -634,7 +646,7 @@ describe('IgxTreeSelectionService - Unit Tests #treeView', () => { const mockChild = { selected: true } as any; - childrenSpy.find.and.returnValue(mockChild); + childrenSpy.find.mockReturnValue(mockChild); selectionService.ensureStateOnNodeDelete(mockNode); expect(selectedNodeSpy).toHaveBeenCalledTimes(4); diff --git a/projects/igniteui-angular/tree/src/tree/tree-selection.spec.ts b/projects/igniteui-angular/tree/src/tree/tree-selection.spec.ts index a7438f0c994..95d42a40b31 100644 --- a/projects/igniteui-angular/tree/src/tree/tree-selection.spec.ts +++ b/projects/igniteui-angular/tree/src/tree/tree-selection.spec.ts @@ -1,3 +1,5 @@ +import type { MockedObject } from "vitest"; +import { describe, it, expect, beforeEach, afterAll, vi } from 'vitest'; import { TestBed, fakeAsync, waitForAsync } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { ChangeDetectorRef, ElementRef, EventEmitter, QueryList } from '@angular/core'; @@ -80,7 +82,7 @@ describe('IgxTree - Selection #treeView', () => { it('Click on checkbox should call node`s onSelectorClick method', () => { const firstNode = tree.nodes.toArray()[0]; - spyOn(firstNode, 'onSelectorClick').and.callThrough(); + vi.spyOn(firstNode, 'onSelectorClick'); const ev = TreeTestFunctions.clickNodeCheckbox(firstNode); fix.detectChanges(); @@ -548,11 +550,14 @@ describe('IgxTree - Selection #treeView', () => { describe('IgxTree - API Tests', () => { let mockNodes: IgxTreeNodeComponent[]; - let mockQuery: jasmine.SpyObj>; + let mockQuery: MockedObject>; const selectionService = new IgxTreeSelectionService(); const treeService = new IgxTreeService(); const elementRef = { nativeElement: null }; - const mockPlatform = jasmine.createSpyObj('platform', ['isBrowser', 'isServer']); + const mockPlatform = { + isBrowser: vi.fn().mockName("platform.isBrowser"), + isServer: vi.fn().mockName("platform.isServer") + }; mockPlatform.isBrowser = true; let navService: IgxTreeNavigationService; let tree: IgxTreeComponent; @@ -574,8 +579,8 @@ describe('IgxTree - Selection #treeView', () => { mockNodes = TreeTestFunctions.createNodeSpies(0, 5); mockQuery = TreeTestFunctions.createQueryListSpy(mockNodes); - mockQuery.toArray.and.returnValue(mockNodes); - mockQuery.forEach.and.callFake((cb) => mockNodes.forEach(cb)); + mockQuery.toArray.mockReturnValue(mockNodes); + mockQuery.forEach.mockImplementation((cb) => mockNodes.forEach(cb)); tree.selection = IgxTreeSelectionType.BiState; (tree.nodes as any) = mockQuery; @@ -587,7 +592,7 @@ describe('IgxTree - Selection #treeView', () => { }); it('Should be able to deselect all nodes', () => { - spyOn(selectionService, 'deselectNodesWithNoEvent').and.callThrough(); + vi.spyOn(selectionService, 'deselectNodesWithNoEvent'); tree.nodes.forEach(node => node.selected = true); @@ -597,7 +602,7 @@ describe('IgxTree - Selection #treeView', () => { }); it('Should be able to deselect multiple nodes', () => { - spyOn(selectionService, 'deselectNodesWithNoEvent').and.callThrough(); + vi.spyOn(selectionService, 'deselectNodesWithNoEvent'); tree.nodes.toArray()[0].selected = true; tree.nodes.toArray()[1].selected = true; @@ -615,14 +620,18 @@ describe('IgxTree - Selection #treeView', () => { const elementRef = { nativeElement: null }; const selectionService = new IgxTreeSelectionService(); const treeService = new IgxTreeService(); - const mockEmitter: EventEmitter = jasmine.createSpyObj('emitter', ['emit']); - const mockTree: IgxTree = jasmine.createSpyObj('tree', [''], - { - selection: IgxTreeSelectionType.BiState, nodeSelection: mockEmitter, nodes: { - find: () => true - } - }); - const mockCdr = jasmine.createSpyObj('ChangeDetectorRef', ['markForCheck', 'detectChanges']); + const mockEmitter: EventEmitter = { + emit: vi.fn().mockName("emitter.emit") + }; + const mockTree: IgxTree = { + selection: IgxTreeSelectionType.BiState, nodeSelection: mockEmitter, nodes: { + find: () => true + } + }; + const mockCdr = { + markForCheck: vi.fn().mockName("ChangeDetectorRef.markForCheck"), + detectChanges: vi.fn().mockName("ChangeDetectorRef.detectChanges") + }; selectionService.register(mockTree); @@ -648,7 +657,7 @@ describe('IgxTree - Selection #treeView', () => { }); it('Should call selectNodesWithNoEvent when setting node`s selected property to true', () => { - spyOn(selectionService, 'selectNodesWithNoEvent').and.callThrough(); + vi.spyOn(selectionService, 'selectNodesWithNoEvent'); node.selected = true; expect((node as any).selectionService.selectNodesWithNoEvent).toHaveBeenCalled(); @@ -656,7 +665,7 @@ describe('IgxTree - Selection #treeView', () => { }); it('Should call deselectNodesWithNoEvent when seting node`s selected property to false', () => { - spyOn(selectionService, 'deselectNodesWithNoEvent').and.callThrough(); + vi.spyOn(selectionService, 'deselectNodesWithNoEvent'); if (!node.selected) { node.selected = true; @@ -669,22 +678,21 @@ describe('IgxTree - Selection #treeView', () => { }); it('Should call isNodeSelected when node`s selected getter is invoked', () => { - spyOn(selectionService, 'isNodeSelected').and.callThrough(); + vi.spyOn(selectionService, 'isNodeSelected'); const isSelected = node.selected; - expect(isSelected).toBeFalse(); + expect(isSelected).toBe(false); expect((node as any).selectionService.isNodeSelected).toHaveBeenCalled(); expect((node as any).selectionService.isNodeSelected).toHaveBeenCalledWith(node); }); it('Should call isNodeIndeterminate when node`s indeterminate getter is invoked', () => { - spyOn(selectionService, 'isNodeIndeterminate').and.callThrough(); + vi.spyOn(selectionService, 'isNodeIndeterminate'); const isIndeterminate = node.indeterminate; - expect(isIndeterminate).toBeFalse(); + expect(isIndeterminate).toBe(false); expect((node as any).selectionService.isNodeIndeterminate).toHaveBeenCalled(); expect((node as any).selectionService.isNodeIndeterminate).toHaveBeenCalledWith(node); }); }); }); - diff --git a/projects/igniteui-angular/tree/src/tree/tree.spec.ts b/projects/igniteui-angular/tree/src/tree/tree.spec.ts index 290c2e85944..fb8419dd0f8 100644 --- a/projects/igniteui-angular/tree/src/tree/tree.spec.ts +++ b/projects/igniteui-angular/tree/src/tree/tree.spec.ts @@ -12,6 +12,8 @@ import { IgxTreeSelectionService } from './tree-selection.service'; import { IgxTreeComponent } from './tree.component'; import { IgxTreeService } from './tree.service'; import { IGX_TREE_COMPONENT } from './common'; +import { describe, it, test, expect, beforeAll, beforeEach, afterEach, afterAll, vi } from 'vitest'; +import { Platform } from 'vitest/browser'; const TREE_ROOT_CLASS = 'igx-tree__root'; const NODE_TAG = 'igx-tree-node'; @@ -26,26 +28,32 @@ describe('IgxTree #treeView', () => { let mockNodesArray: IgxTreeNodeComponent[] = []; let tree: IgxTreeComponent = null; - beforeAll(() => { - jasmine.getEnv().allowRespy(true); - }); - - afterAll(() => { - jasmine.getEnv().allowRespy(false); - }); - beforeEach(() => { mockNodesArray = []; - mockNavService = jasmine.createSpyObj('navService', - ['register', 'update_disabled_cache', 'update_visible_cache', - 'init_invisible_cache', 'setFocusedAndActiveNode', 'handleKeydown']); - mockTreeService = jasmine.createSpyObj('treeService', - ['register', 'collapse', 'expand', 'collapsing', 'isExpanded']); - mockSelectionService = jasmine.createSpyObj('selectionService', - ['register', 'deselectNodesWithNoEvent', 'ensureStateOnNodeDelete', 'selectNodesWithNoEvent']); - mockElementRef = jasmine.createSpyObj('elementRef', [], { + mockNavService = { + register: vi.fn(), + update_disabled_cache: vi.fn(), + update_visible_cache: vi.fn(), + init_invisible_cache: vi.fn(), + setFocusedAndActiveNode: vi.fn(), + handleKeydown: vi.fn() + } as unknown as IgxTreeNavigationService; + mockTreeService = { + register: vi.fn(), + collapse: vi.fn(), + expand: vi.fn(), + collapsing: vi.fn(), + isExpanded: vi.fn() + } as unknown as IgxTreeService; + mockSelectionService = { + register: vi.fn(), + deselectNodesWithNoEvent: vi.fn(), + ensureStateOnNodeDelete: vi.fn(), + selectNodesWithNoEvent: vi.fn() + } as unknown as IgxTreeSelectionService; + mockElementRef = { nativeElement: document.createElement('div') - }); + } as ElementRef; TestBed.configureTestingModule({ providers: [ @@ -57,12 +65,16 @@ describe('IgxTree #treeView', () => { ] }); - const mockPlatform = jasmine.createSpyObj('platform', ['isBrowser', 'isServer']); - mockPlatform.isBrowser = true; + const mockPlatform = { + isBrowser: vi.fn(), + isServer: vi.fn() + }; + mockPlatform.isBrowser.mockReturnValue(true); tree = TestBed.inject(IgxTreeComponent); - mockNodes = jasmine.createSpyObj('mockList', ['toArray'], { + mockNodes = { + toArray: vi.fn().mockName("mockList.toArray"), changes: new Subject(), get first() { return mockNodesArray[0]; @@ -73,14 +85,13 @@ describe('IgxTree #treeView', () => { get length() { return mockNodesArray.length; }, - forEach: (cb: (n: IgxTreeNodeComponent) => void): void => { - mockNodesArray.forEach(cb); + forEach: (fn: (item: IgxTreeNodeComponent, index: number, array: IgxTreeNodeComponent[]) => void): void => { + mockNodesArray.forEach(fn); }, - find: (cb: (n: IgxTreeNodeComponent) => boolean): IgxTreeNodeComponent => mockNodesArray.find(cb), - filter: jasmine.createSpy('filter'). - and.callFake((cb: (n: IgxTreeNodeComponent) => boolean): IgxTreeNodeComponent[] => mockNodesArray.filter(cb)), - }); - spyOn(mockNodes, 'toArray').and.returnValue(mockNodesArray); + find: (fn: (item: IgxTreeNodeComponent, index: number, array: IgxTreeNodeComponent[]) => boolean): IgxTreeNodeComponent => mockNodesArray.find(fn), + filter: vi.fn().mockImplementation((cb: (n: IgxTreeNodeComponent) => boolean): IgxTreeNodeComponent[] => mockNodesArray.filter(cb)) + } as unknown as QueryList>; + vi.spyOn(mockNodes, 'toArray').mockReturnValue(mockNodesArray); }); afterEach(() => { tree?.ngOnDestroy(); @@ -113,11 +124,9 @@ describe('IgxTree #treeView', () => { closeAnimationDone: new EventEmitter(), openAnimationDone: new EventEmitter() }) as any; - mockNodesArray.push( - mockNode - ); + mockNodesArray.push(mockNode); - spyOnProperty(mockNodes, 'first', 'get').and.returnValue(mockNode); + vi.spyOn(mockNodes, 'first', 'get').mockReturnValue(mockNode); tree.ngAfterViewInit(); tick(); expect(mockNavService.init_invisible_cache).toHaveBeenCalledTimes(1); @@ -180,7 +189,9 @@ describe('IgxTree #treeView', () => { tree.nodes = mockNodes; const customArrayParam = []; for (let i = 0; i < 5; i++) { - const node = jasmine.createSpyObj('node', ['expand', 'collapse'], { + const node = { + expand: vi.fn().mockName("node.expand"), + collapse: vi.fn().mockName("node.collapse"), _expanded: false, get expanded() { return this._expanded; @@ -188,14 +199,14 @@ describe('IgxTree #treeView', () => { set expanded(val: boolean) { this._expanded = val; } - }); - node.spyProp = spyOnProperty(node, 'expanded', 'set').and.callThrough(); - mockNodesArray.push(node); + }; + (node as any).spyProp = vi.spyOn(node, 'expanded', 'set'); + mockNodesArray.push(node as any); if (i > 3) { - customArrayParam.push(node); + customArrayParam.push(node as any); } } - spyOn(mockNodesArray, 'forEach').and.callThrough(); + vi.spyOn(mockNodesArray, 'forEach'); tree.expandAll(); expect(mockNodesArray.forEach).toHaveBeenCalledTimes(1); mockNodesArray.forEach(n => { @@ -212,7 +223,9 @@ describe('IgxTree #treeView', () => { tree.nodes = mockNodes; const customArrayParam = []; for (let i = 0; i < 5; i++) { - const node = jasmine.createSpyObj('node', ['expand', 'collapse'], { + const node = { + expand: vi.fn().mockName("node.expand"), + collapse: vi.fn().mockName("node.collapse"), _expanded: false, get expanded() { return this._expanded; @@ -220,14 +233,14 @@ describe('IgxTree #treeView', () => { set expanded(val: boolean) { this._expanded = val; } - }); - node.spyProp = spyOnProperty(node, 'expanded', 'set').and.callThrough(); - mockNodesArray.push(node); + }; + (node as any).spyProp = vi.spyOn(node, 'expanded', 'set'); + mockNodesArray.push(node as any); if (i > 3) { - customArrayParam.push(node); + customArrayParam.push(node as any); } } - spyOn(mockNodesArray, 'forEach').and.callThrough(); + vi.spyOn(mockNodesArray, 'forEach'); tree.collapseAll(); expect(mockNodesArray.forEach).toHaveBeenCalledTimes(1); mockNodesArray.forEach(n => { @@ -244,8 +257,10 @@ describe('IgxTree #treeView', () => { tree.nodes = mockNodes; tree.deselectAll(); expect(mockSelectionService.deselectNodesWithNoEvent).toHaveBeenCalledWith(undefined); - const customParam = jasmine.createSpyObj('nodes', ['toArray']); - tree.deselectAll(customParam); + const customParam = { + toArray: vi.fn().mockName("nodes.toArray") + }; + tree.deselectAll(customParam as any); expect(mockSelectionService.deselectNodesWithNoEvent).toHaveBeenCalledWith(customParam); }); }); @@ -257,15 +272,28 @@ describe('IgxTree #treeView', () => { let treeService: IgxTreeService; beforeEach(() => { - mockTree = jasmine.createSpyObj('mockTree', ['findNodes'], - { - nodeCollapsing: jasmine.createSpyObj('spy', ['emit']), - nodeExpanding: jasmine.createSpyObj('spy', ['emit']), - nodeCollapsed: jasmine.createSpyObj('spy', ['emit']), - nodeExpanded: jasmine.createSpyObj('spy', ['emit']) - }); - mockCdr = jasmine.createSpyObj('mockCdr', ['detectChanges', 'markForCheck'], {}); - mockAnimationService = jasmine.createSpyObj('mockAB', ['buildAnimation'], {}); + mockTree = { + findNodes: vi.fn().mockName("mockTree.findNodes"), + nodeCollapsing: { + emit: vi.fn().mockName("spy.emit") + }, + nodeExpanding: { + emit: vi.fn().mockName("spy.emit") + }, + nodeCollapsed: { + emit: vi.fn().mockName("spy.emit") + }, + nodeExpanded: { + emit: vi.fn().mockName("spy.emit") + } + } as unknown as IgxTreeComponent; + mockCdr = { + detectChanges: vi.fn().mockName("mockCdr.detectChanges"), + markForCheck: vi.fn().mockName("mockCdr.markForCheck") + } as unknown as ChangeDetectorRef; + mockAnimationService = { + buildAnimation: vi.fn().mockName("mockAB.buildAnimation") + }; treeService = new IgxTreeService(); TestBed.resetTestingModule(); @@ -339,14 +367,18 @@ describe('IgxTree #treeView', () => { }); it('Should call service expand/collapse methods when calling API state methods', () => { treeService.register(mockTree); - node.expandedChange = jasmine.createSpyObj('emitter', ['emit']) - const openAnimationSpy = spyOn(node, 'playOpenAnimation'); - const closeAnimationSpy = spyOn(node, 'playCloseAnimation'); - const mockObj = jasmine.createSpyObj('mockElement', ['focus']); - spyOn(treeService, 'collapse').and.callThrough(); - spyOn(treeService, 'collapsing').and.callThrough(); - spyOn(treeService, 'expand').and.callThrough(); - spyOn(node, 'expandedChange').and.callThrough(); + node.expandedChange = { + emit: vi.fn().mockName("emitter.emit") + } as unknown as EventEmitter; + const openAnimationSpy = vi.spyOn(node, 'playOpenAnimation'); + const closeAnimationSpy = vi.spyOn(node, 'playCloseAnimation'); + const mockObj = { + focus: vi.fn().mockName("mockElement.focus") + }; + vi.spyOn(treeService, 'collapse'); + vi.spyOn(treeService, 'collapsing'); + vi.spyOn(treeService, 'expand'); + vi.spyOn(node, 'expandedChange' as any); const ingArgs = { owner: mockTree, cancel: false, @@ -396,12 +428,12 @@ describe('IgxTree #treeView', () => { expect(node.expandedChange.emit).toHaveBeenCalledWith(false); expect(mockTree.nodeCollapsed.emit).toHaveBeenCalledTimes(1); expect(mockTree.nodeCollapsed.emit).toHaveBeenCalledWith(edArgs); - spyOn(node, 'expand'); - spyOn(node, 'collapse'); + vi.spyOn(node, 'expand'); + vi.spyOn(node, 'collapse'); node.toggle(); expect(node.expand).toHaveBeenCalledTimes(1); expect(node.collapse).toHaveBeenCalledTimes(0); - spyOn(treeService, 'isExpanded').and.returnValue(true); + vi.spyOn(treeService, 'isExpanded').mockReturnValue(true); node.toggle(); expect(node.expand).toHaveBeenCalledTimes(1); expect(node.collapse).toHaveBeenCalledTimes(1); @@ -423,13 +455,16 @@ describe('IgxTree #treeView', () => { it('Should properly register tree', () => { const service = new IgxTreeService(); expect((service as any).tree).toBe(undefined); - const mockTree = jasmine.createSpyObj('tree', ['findNodes']); - service.register(mockTree); + const mockTree = { + findNodes: vi.fn().mockName("tree.findNodes") + }; + service.register(mockTree as any); expect((service as any).tree).toBe(mockTree); }); it('Should keep a proper collection of expanded and collapsing nodes at all time, firing `expandedChange` when needed', () => { const service = new IgxTreeService(); - const mockTree = jasmine.createSpyObj('tree', ['findNodes'], { + const mockTree = { + findNodes: vi.fn().mockName("tree.findNodes"), _singleBranchExpand: false, get singleBranchExpand(): boolean { return this._singleBranchExpand; @@ -437,18 +472,21 @@ describe('IgxTree #treeView', () => { set singleBranchExpand(val: boolean) { this._singleBranchExpand = val; } - }); - service.register(mockTree); - spyOn(service.expandedNodes, 'add').and.callThrough(); - spyOn(service.expandedNodes, 'delete').and.callThrough(); - spyOn(service.collapsingNodes, 'add').and.callThrough(); - spyOn(service.collapsingNodes, 'delete').and.callThrough(); + }; + service.register(mockTree as any); + vi.spyOn(service.expandedNodes, 'add'); + vi.spyOn(service.expandedNodes, 'delete'); + vi.spyOn(service.collapsingNodes, 'add'); + vi.spyOn(service.collapsingNodes, 'delete'); expect(service.expandedNodes.size).toBe(0); expect(service.collapsingNodes.size).toBe(0); - const mockNode = jasmine.createSpyObj('node', ['collapse'], { - expandedChange: jasmine.createSpyObj('emitter', ['emit']) - }); - service.expand(mockNode); + const mockNode = { + collapse: vi.fn().mockName("node.collapse"), + expandedChange: { + emit: vi.fn().mockName("emitter.emit") + } + }; + service.expand(mockNode as any); expect(service.collapsingNodes.delete).toHaveBeenCalledWith(mockNode); expect(service.collapsingNodes.delete).toHaveBeenCalledTimes(1); expect(service.expandedNodes.add).toHaveBeenCalledWith(mockNode); @@ -456,11 +494,11 @@ describe('IgxTree #treeView', () => { expect(mockNode.expandedChange.emit).toHaveBeenCalledWith(true); expect(service.expandedNodes.size).toBe(1); expect(mockNode.collapse).not.toHaveBeenCalled(); - service.expand(mockNode); + service.expand(mockNode as any); expect(service.collapsingNodes.delete).toHaveBeenCalledTimes(2); expect(mockNode.expandedChange.emit).toHaveBeenCalledTimes(1); expect(service.expandedNodes.size).toBe(1); - service.collapse(mockNode); + service.collapse(mockNode as any); expect(mockNode.expandedChange.emit).toHaveBeenCalledTimes(2); expect(mockNode.expandedChange.emit).toHaveBeenCalledWith(false); expect(service.collapsingNodes.delete).toHaveBeenCalledWith(mockNode); @@ -468,13 +506,14 @@ describe('IgxTree #treeView', () => { expect(service.expandedNodes.delete).toHaveBeenCalledTimes(1); expect(service.expandedNodes.delete).toHaveBeenCalledWith(mockNode); expect(service.expandedNodes.size).toBe(0); - service.collapse(mockNode); + service.collapse(mockNode as any); expect(mockNode.expandedChange.emit).toHaveBeenCalledTimes(2); expect(service.collapsingNodes.delete).toHaveBeenCalledTimes(4); expect(service.expandedNodes.delete).toHaveBeenCalledTimes(2); const mockArray = []; for (let i = 0; i < 5; i++) { - const node = jasmine.createSpyObj('node', ['collapse'], { + const node = { + collapse: vi.fn().mockName("node.collapse"), _expanded: false, get expanded() { return this._expanded; @@ -482,30 +521,30 @@ describe('IgxTree #treeView', () => { set expanded(val: boolean) { this._expanded = val; } - }); - node.spyProp = spyOnProperty(node, 'expanded', 'set').and.callThrough(); + }; + (node as any).spyProp = vi.spyOn(node, 'expanded', 'set'); mockArray.push(node); } - spyOn(mockTree, 'findNodes').and.returnValue(mockArray); - spyOnProperty(mockTree, 'singleBranchExpand', 'get').and.returnValue(true); - service.expand(mockNode); + vi.spyOn(mockTree, 'findNodes').mockReturnValue(mockArray); + vi.spyOn(mockTree, 'singleBranchExpand', 'get').mockReturnValue(true); + service.expand(mockNode as any); mockArray.forEach(n => { expect((n as any).spyProp).toHaveBeenCalledWith(false); expect(n.collapse).not.toHaveBeenCalled(); }); - service.collapse(mockNode); - service.expand(mockNode, true); + service.collapse(mockNode as any); + service.expand(mockNode as any, true); mockArray.forEach(n => { expect(n.collapse).toHaveBeenCalled(); expect(n.collapse).toHaveBeenCalledTimes(1); }); expect(service.collapsingNodes.size).toBe(0); - service.collapsing(mockNode); + service.collapsing(mockNode as any); expect(service.collapsingNodes.size).toBe(1); - service.collapse(mockNode); - spyOnProperty(mockTree, 'singleBranchExpand', 'get').and.returnValue(true); - spyOn(mockTree, 'findNodes').and.returnValue(null); - service.expand(mockNode, true); + service.collapse(mockNode as any); + vi.spyOn(mockTree, 'singleBranchExpand', 'get').mockReturnValue(true); + vi.spyOn(mockTree, 'findNodes').mockReturnValue(null); + service.expand(mockNode as any, true); expect(mockTree.findNodes).toHaveBeenCalledWith(mockNode, (service as any).siblingComparer); mockArray.forEach(n => { expect(n.collapse).toHaveBeenCalledTimes(1); @@ -560,13 +599,15 @@ describe('IgxTree #treeView', () => { }); }); - it('Should apply proper node classes depending on tree displayDensity', () => { - pending('Test not implemented'); + it.skip('Should apply proper node classes depending on tree displayDensity', () => { + // TODO: vitest-migration: The pending() function was converted to a skipped test (`it.skip`). See: https://vitest.dev/api/vi.html#it-skip + // pending('Test not implemented'); + ; }); it('Should do nothing when calling expand()/collapse() on expanded/collapsed node', fakeAsync(() => { - const expandingSpy = spyOn(tree.nodeExpanding, 'emit').and.callThrough(); - const collapsingSpy = spyOn(tree.nodeCollapsing, 'emit').and.callThrough(); + const expandingSpy = vi.spyOn(tree.nodeExpanding, 'emit'); + const collapsingSpy = vi.spyOn(tree.nodeCollapsing, 'emit'); tree.nodes.first.collapse(); expect(expandingSpy).not.toHaveBeenCalled(); @@ -578,10 +619,10 @@ describe('IgxTree #treeView', () => { it('Should properly emit state toggle events', fakeAsync(() => { // node event spies - const collapsingSpy = spyOn(tree.nodeCollapsing, 'emit').and.callThrough(); - const expandingSpy = spyOn(tree.nodeExpanding, 'emit').and.callThrough(); - const expandedSpy = spyOn(tree.nodeExpanded, 'emit').and.callThrough(); - const collapsedSpy = spyOn(tree.nodeCollapsed, 'emit').and.callThrough(); + const collapsingSpy = vi.spyOn(tree.nodeCollapsing, 'emit'); + const expandingSpy = vi.spyOn(tree.nodeExpanding, 'emit'); + const expandedSpy = vi.spyOn(tree.nodeExpanded, 'emit'); + const collapsedSpy = vi.spyOn(tree.nodeCollapsed, 'emit'); expect(collapsingSpy).not.toHaveBeenCalled(); expect(expandingSpy).not.toHaveBeenCalled(); expect(expandedSpy).not.toHaveBeenCalled(); @@ -640,19 +681,19 @@ describe('IgxTree #treeView', () => { unsub$.complete(); })); - it('Should collapse all sibling nodes when `singleBranchExpand` is set and node is toggled', fakeAsync(() => { - pending('Causes jasmine to hang'); + it.skip('Should collapse all sibling nodes when `singleBranchExpand` is set and node is toggled', fakeAsync(() => { + // Skipped: Causes the test runner to hang tree.rootNodes.forEach((n, index) => index > 0 ? n.expanded = true : n.expanded = false); fix.detectChanges(); expect(tree.nodes.filter(n => n.expanded).length).toBe(4); tree.singleBranchExpand = true; tree.rootNodes.forEach(n => { - spyOn(n.expandedChange, 'emit').and.callThrough(); + vi.spyOn(n.expandedChange, 'emit'); }); - const collapsingSpy = spyOn(tree.nodeCollapsing, 'emit').and.callThrough(); - const expandingSpy = spyOn(tree.nodeExpanding, 'emit').and.callThrough(); - const expandedSpy = spyOn(tree.nodeCollapsed, 'emit').and.callThrough(); - const collapsedSpy = spyOn(tree.nodeExpanded, 'emit').and.callThrough(); + const collapsingSpy = vi.spyOn(tree.nodeCollapsing, 'emit'); + const expandingSpy = vi.spyOn(tree.nodeExpanding, 'emit'); + const expandedSpy = vi.spyOn(tree.nodeCollapsed, 'emit'); + const collapsedSpy = vi.spyOn(tree.nodeExpanded, 'emit'); // should not emit event when nodes are toggled through input tree.rootNodes[0].expanded = true; fix.detectChanges(); @@ -688,9 +729,7 @@ describe('IgxTree #treeView', () => { const deepNode = tree.findNodes('2-1', (_id: '2-1', n: IgxTreeNodeComponent) => n.data.id === '2-1')[0]; expect(deepNode).not.toBeNull(); fix.componentInstance.expandToNode(deepNode); - const siblingNodes = tree.findNodes(deepNode, - (tn: IgxTreeNodeComponent, n: IgxTreeNodeComponent) => n.level === tn.level && n.parentNode === tn.parentNode - ); + const siblingNodes = tree.findNodes(deepNode, (tn: IgxTreeNodeComponent, n: IgxTreeNodeComponent) => n.level === tn.level && n.parentNode === tn.parentNode); expect(siblingNodes.length).toBe(5); siblingNodes.forEach(n => n.expanded = true); fix.detectChanges(); @@ -707,15 +746,21 @@ describe('IgxTree #treeView', () => { })); }); describe('ARIA', () => { - it('Should render proper roles for tree and nodes', () => { - pending('Test not implemented'); + it.skip('Should render proper roles for tree and nodes', () => { + // TODO: vitest-migration: The pending() function was converted to a skipped test (`it.skip`). See: https://vitest.dev/api/vi.html#it-skip + // pending('Test not implemented'); + ; }); - it('Should render proper label for expand/collapse indicator, depending on node state', () => { - pending('Test not implemented'); + it.skip('Should render proper label for expand/collapse indicator, depending on node state', () => { + // TODO: vitest-migration: The pending() function was converted to a skipped test (`it.skip`). See: https://vitest.dev/api/vi.html#it-skip + // pending('Test not implemented'); + ; }); - it('Should render proper roles for nodes containing link children', () => { - pending('Test not implemented'); + it.skip('Should render proper roles for nodes containing link children', () => { + // TODO: vitest-migration: The pending() function was converted to a skipped test (`it.skip`). See: https://vitest.dev/api/vi.html#it-skip + // pending('Test not implemented'); + ; }); }); }); diff --git a/projects/igniteui-angular/tsconfig.spec.json b/projects/igniteui-angular/tsconfig.spec.json index b925e22baa8..9e682e5880e 100644 --- a/projects/igniteui-angular/tsconfig.spec.json +++ b/projects/igniteui-angular/tsconfig.spec.json @@ -3,7 +3,6 @@ "compilerOptions": { "outDir": "../../out-tsc/spec", "types": [ - "jasmine", "node", "hammerjs" ] diff --git a/src/test.ts b/src/test.ts deleted file mode 100644 index 51bb0206a2e..00000000000 --- a/src/test.ts +++ /dev/null @@ -1,14 +0,0 @@ -// This file is required by karma.conf.js and loads recursively all the .spec and framework files - -import 'zone.js/testing'; -import { getTestBed } from '@angular/core/testing'; -import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting -} from '@angular/platform-browser-dynamic/testing'; - -// First, initialize the Angular testing environment. -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), -); diff --git a/src/tsconfig.spec.json b/src/tsconfig.spec.json index 12ac5090b6c..70b70847d67 100644 --- a/src/tsconfig.spec.json +++ b/src/tsconfig.spec.json @@ -3,15 +3,10 @@ "compilerOptions": { "outDir": "../out-tsc/spec", "types": [ - "jasmine", "node", "hammerjs" ] }, - "files": [ - "test.ts", - "polyfills.ts" - ], "include": [ "**/*.spec.ts", "**/*.d.ts" diff --git a/src/vitest.config.ts b/src/vitest.config.ts new file mode 100644 index 00000000000..3320480f120 --- /dev/null +++ b/src/vitest.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + globals: true, + }, +}); \ No newline at end of file