+ @defer(on viewport){
+ >
+
+ } @placeholder {
+
+ }
|
diff --git a/libs/angular-accelerator/src/lib/components/data-table/data-table.component.ts b/libs/angular-accelerator/src/lib/components/data-table/data-table.component.ts
index 7fc1a518..3d0bf732 100644
--- a/libs/angular-accelerator/src/lib/components/data-table/data-table.component.ts
+++ b/libs/angular-accelerator/src/lib/components/data-table/data-table.component.ts
@@ -137,7 +137,8 @@ export class DataTableComponent extends DataSortBase implements OnInit, AfterCon
const obs = value.map((c) => this.getTemplate(c, TemplateType.CELL))
const filterObs = value.map((c) => this.getTemplate(c, TemplateType.FILTERCELL))
this.columnTemplates$ = combineLatest(obs).pipe(
- map((values) => Object.fromEntries(value.map((c, i) => [c.id, values[i]])))
+ map((values) => Object.fromEntries(value.map((c, i) => [c.id, values[i]]))),
+ debounceTime(50)
)
this.columnFilterTemplates$ = combineLatest(filterObs).pipe(
map((values) => Object.fromEntries(value.map((c, i) => [c.id, values[i]])))
@@ -908,8 +909,7 @@ export class DataTableComponent extends DataSortBase implements OnInit, AfterCon
return columnTemplate
}
return this.getColumnTypeTemplate(templates, column.columnType, templateType)
- }),
- debounceTime(50)
+ })
)
}
return templatesData.templatesObservables[column.id]
diff --git a/libs/angular-accelerator/src/lib/components/interactive-data-view/interactive-data-view.component.spec.ts b/libs/angular-accelerator/src/lib/components/interactive-data-view/interactive-data-view.component.spec.ts
index 59dfe9ac..b1aff25a 100644
--- a/libs/angular-accelerator/src/lib/components/interactive-data-view/interactive-data-view.component.spec.ts
+++ b/libs/angular-accelerator/src/lib/components/interactive-data-view/interactive-data-view.component.spec.ts
@@ -307,6 +307,8 @@ describe('InteractiveDataViewComponent', () => {
viewItemEvent = undefined
editItemEvent = undefined
deleteItemEvent = undefined
+
+ console.log("Global IntersectionObserver", global.IntersectionObserver)
})
it('should create', () => {
@@ -433,7 +435,6 @@ describe('InteractiveDataViewComponent', () => {
]
const sortButton = await tableHeaders[0].getSortButton()
await sortButton.click()
-
tableRows = (await dataTable?.getRows()) ?? []
const rows = await parallel(() => tableRows.map((row) => row.getData()))
diff --git a/libs/angular-accelerator/src/lib/components/interactive-data-view/interactive-data-view.component.stories.ts b/libs/angular-accelerator/src/lib/components/interactive-data-view/interactive-data-view.component.stories.ts
index fa0c6a8f..ad14111f 100644
--- a/libs/angular-accelerator/src/lib/components/interactive-data-view/interactive-data-view.component.stories.ts
+++ b/libs/angular-accelerator/src/lib/components/interactive-data-view/interactive-data-view.component.stories.ts
@@ -38,6 +38,8 @@ import { of } from 'rxjs'
import { Filter, FilterType } from '../../model/filter.model'
import { FilterViewComponent } from '../filter-view/filter-view.component'
import { FocusTrapModule } from 'primeng/focustrap'
+import { TooltipOnOverflowDirective } from '../../directives/tooltipOnOverflow.directive'
+import { SkeletonModule } from 'primeng/skeleton'
type InteractiveDataViewInputTypes = Pick<
InteractiveDataViewComponent,
@@ -85,6 +87,7 @@ const InteractiveDataViewComponentSBConfig: Meta =
DataListGridComponent,
DataListGridSortingComponent,
FilterViewComponent,
+ TooltipOnOverflowDirective
],
imports: [
TableModule,
@@ -105,6 +108,7 @@ const InteractiveDataViewComponentSBConfig: Meta =
OverlayPanelModule,
FocusTrapModule,
ChipModule,
+ SkeletonModule
],
}),
],
@@ -192,6 +196,71 @@ export const WithMockData = {
},
}
+function generateColumns(count: number) {
+ const data = []
+ for (let i = 0; i < count; i++) {
+ const row = {
+ id: `${i + 1}`,
+ columnType: ColumnType.STRING,
+ nameKey: `Product${i + 1}`,
+ sortable: false,
+ filterable: true,
+ predefinedGroupKeys: ['test'],
+ };
+ data.push(row)
+ }
+ return data
+}
+
+function generateRows(rowCount: number, columnCount: number) {
+ const data = []
+ for (let i = 0; i < rowCount; i++) {
+ const row = {} as any
+ for(let j = 0; j < columnCount; j++) {
+ row[j+1] = `Test value for ${j+1}`
+ }
+ data.push(row)
+ }
+ return data
+}
+
+function generateColumnTemplates(columnCount: number) {
+ let templates = ''
+ for(let i = 0; i < columnCount; i++) {
+ templates += `
+
+ ${i+1} {{ rowObject[${i+1}] }}
+ `
+ }
+ return templates
+}
+
+const columnCount = 30;
+const rowCount = 500
+
+const HugeMockDataTemplate: StoryFn = (args) => ({
+ props: args,
+ template: `
+
+ ${generateColumnTemplates(Math.ceil(columnCount/3))}
+ `,
+})
+
+export const WithHugeMockData = {
+ argTypes: {
+ componentStateChanged: { action: 'componentStateChanged' },
+ selectionChanged: { action: 'selectionChanged' },
+ },
+ render: HugeMockDataTemplate,
+ args: {
+ columns: generateColumns(columnCount),
+ data: generateRows(rowCount, columnCount),
+ emptyResultsMessage: 'No results',
+ selectedRows: [],
+ pageSize: 50,
+ },
+}
+
export const WithPageSizes = {
argTypes: {
componentStateChanged: { action: 'componentStateChanged' },
diff --git a/libs/angular-accelerator/testing/data-list-grid.harness.ts b/libs/angular-accelerator/testing/data-list-grid.harness.ts
index 576fcb0d..8463c73d 100644
--- a/libs/angular-accelerator/testing/data-list-grid.harness.ts
+++ b/libs/angular-accelerator/testing/data-list-grid.harness.ts
@@ -2,15 +2,20 @@ import { ContentContainerComponentHarness, TestElement, parallel } from '@angula
import { PPaginatorHarness } from '@onecx/angular-testing'
import { DefaultGridItemHarness } from './default-grid-item.harness'
import { DefaultListItemHarness } from './default-list-item.harness'
+import { waitForDeferredViewsToBeRendered } from '@onecx/angular-testing'
export class DataListGridHarness extends ContentContainerComponentHarness {
static hostSelector = 'ocx-data-list-grid'
getDefaultGridItems = this.locatorForAll(DefaultGridItemHarness)
- getDefaultListItems = this.locatorForAll(DefaultListItemHarness)
getPaginator = this.locatorFor(PPaginatorHarness)
getMenuButton = this.locatorFor(`[name="data-grid-item-menu-button"]`)
+ async getDefaultListItems() {
+ await waitForDeferredViewsToBeRendered(this)
+ return await this.locatorForAll(DefaultListItemHarness)()
+ }
+
async getActionButtons(actionButtonType: 'list' | 'grid' | 'grid-hidden') {
if (actionButtonType === 'list') {
return await this.locatorForAll(`[name="data-list-action-button"]`)()
diff --git a/libs/angular-accelerator/testing/default-list-item.harness.ts b/libs/angular-accelerator/testing/default-list-item.harness.ts
index 3e011086..3e5c2f8a 100644
--- a/libs/angular-accelerator/testing/default-list-item.harness.ts
+++ b/libs/angular-accelerator/testing/default-list-item.harness.ts
@@ -1,5 +1,6 @@
import { ComponentHarness } from '@angular/cdk/testing'
import { ButtonHarness, DivHarness } from '@onecx/angular-testing'
+import { waitForDeferredViewsToBeRendered } from '@onecx/angular-testing'
export class DefaultListItemHarness extends ComponentHarness {
static hostSelector = '.data-list-items'
@@ -12,6 +13,7 @@ export class DefaultListItemHarness extends ComponentHarness {
private getAllDivs = this.locatorForAll(DivHarness)
async getData() {
+ await waitForDeferredViewsToBeRendered(this)
const isDataListItemsDiv = await Promise.all(
(await this.getAllDivs()).map((innerDivHarness) => this.checkDivsHasClasses(innerDivHarness))
)
diff --git a/libs/angular-accelerator/testing/index.ts b/libs/angular-accelerator/testing/index.ts
index b1968f74..6872aaff 100644
--- a/libs/angular-accelerator/testing/index.ts
+++ b/libs/angular-accelerator/testing/index.ts
@@ -1,3 +1,5 @@
+import { ensureIntersectionObserverMockExists } from '@onecx/angular-testing'
+
export * from './column-group-selection.harness'
export * from './custom-group-column-selector.harness'
export * from './data-layout-selection.harness'
@@ -18,3 +20,7 @@ export * from './search-header.harness'
export * from '@angular/cdk/testing'
export * from '@angular/cdk/testing/testbed'
export * from '@onecx/angular-testing'
+
+ensureIntersectionObserverMockExists()
+declare let global: any
+global.origin = ''
\ No newline at end of file
diff --git a/libs/angular-testing/src/index.ts b/libs/angular-testing/src/index.ts
index 08577358..f8b76e9c 100644
--- a/libs/angular-testing/src/index.ts
+++ b/libs/angular-testing/src/index.ts
@@ -36,3 +36,6 @@ export * from './lib/harnesses/table-row.harness'
export * from '@angular/cdk/testing'
export * from '@angular/cdk/testing/testbed'
+
+export * from './lib/mocks/IntersectionObserverMock'
+export * from './lib/utils/waitForDeferredViewsToBeRendered'
diff --git a/libs/angular-testing/src/lib/harnesses/button.harness.ts b/libs/angular-testing/src/lib/harnesses/button.harness.ts
index 016dabf4..3f7c3eac 100644
--- a/libs/angular-testing/src/lib/harnesses/button.harness.ts
+++ b/libs/angular-testing/src/lib/harnesses/button.harness.ts
@@ -32,6 +32,7 @@ export class ButtonHarness extends ComponentHarness {
} else {
console.warn('Button cannot be clicked, because it is disabled!')
}
+ await this.waitForTasksOutsideAngular()
}
async isDisabled(): Promise {
diff --git a/libs/angular-testing/src/lib/harnesses/table-row.harness.ts b/libs/angular-testing/src/lib/harnesses/table-row.harness.ts
index e15e803d..e6b8b107 100644
--- a/libs/angular-testing/src/lib/harnesses/table-row.harness.ts
+++ b/libs/angular-testing/src/lib/harnesses/table-row.harness.ts
@@ -1,5 +1,6 @@
import { ContentContainerComponentHarness } from '@angular/cdk/testing'
import { ButtonHarness } from './button.harness'
+import { waitForDeferredViewsToBeRendered } from '../utils/waitForDeferredViewsToBeRendered'
export class TableRowHarness extends ContentContainerComponentHarness {
static hostSelector = 'tbody > tr'
@@ -10,6 +11,7 @@ export class TableRowHarness extends ContentContainerComponentHarness {
getDeleteButton = this.locatorForOptional(ButtonHarness.with({ class: 'deleteTableRowButton' }))
async getData(): Promise {
+ await waitForDeferredViewsToBeRendered(this)
const tds = await this.locatorForAll('td')()
const isActionsTd = await Promise.all(tds.map((t) => t.hasClass('actions')))
const textTds = tds.filter((_v, index) => !isActionsTd[index])
diff --git a/libs/angular-testing/src/lib/mocks/IntersectionObserverMock.ts b/libs/angular-testing/src/lib/mocks/IntersectionObserverMock.ts
new file mode 100644
index 00000000..7e862a8c
--- /dev/null
+++ b/libs/angular-testing/src/lib/mocks/IntersectionObserverMock.ts
@@ -0,0 +1,42 @@
+export class IntersectionObserverMock {
+ private callback: any
+ private entries: any[]
+ root: any
+ rootMargin: any
+ thresholds: any
+ constructor(callback: any, _options: any) {
+ this.callback = callback
+ this.entries = []
+ }
+
+ observe(target: Element) {
+ const entry = {
+ boundingClientRect: target.getBoundingClientRect(),
+ intersectionRatio: 1,
+ isIntersecting: true,
+ target: target,
+ }
+ this.entries.push(entry)
+ setTimeout(() => {
+ this.callback(this.entries, this)
+ })
+ }
+
+ takeRecords() {
+ return this.entries
+ }
+
+ unobserve(target: any) {
+ this.entries = this.entries.filter((entry) => entry.target !== target)
+ }
+
+ disconnect() {
+ this.entries = []
+ }
+}
+
+export function ensureIntersectionObserverMockExists() {
+ if (!global.IntersectionObserver || global.IntersectionObserver !== IntersectionObserverMock) {
+ global.IntersectionObserver = IntersectionObserverMock
+ }
+}
diff --git a/libs/angular-testing/src/lib/utils/waitForDeferredViewsToBeRendered.ts b/libs/angular-testing/src/lib/utils/waitForDeferredViewsToBeRendered.ts
new file mode 100644
index 00000000..23010b6f
--- /dev/null
+++ b/libs/angular-testing/src/lib/utils/waitForDeferredViewsToBeRendered.ts
@@ -0,0 +1,17 @@
+import { ComponentHarness, ContentContainerComponentHarness } from '@angular/cdk/testing'
+
+export async function waitForDeferredViewsToBeRendered(harness: ComponentHarness | ContentContainerComponentHarness) {
+ return await new Promise((resolve) => {
+ setTimeout(() => {
+ console.warn(
+ 'waitForTasksOutsideAngular has not finished within 500ms. We are not waiting any longer to not cause timeouts.'
+ );
+ (harness as any).forceStabilize().then(() => resolve())
+ }, 500)
+ // waitForTasksOutsideAngular makes sure that the observe method of the IntersectionObserver is called for each defer block.
+ // setTimeout makes sure that we are only continuing after the IntersectionObserverMock has called ther callback for each
+ // defer block, because js scheduling is making sure that all methods which are scheduled via setTimeout are executed in the
+ // respective order. This guarentees that the resolve method is called after the defer block was rendered.
+ ;(harness as any).waitForTasksOutsideAngular().then(() => setTimeout(() => resolve()))
+ })
+}
diff --git a/libs/angular-testing/tsconfig.json b/libs/angular-testing/tsconfig.json
index cd40c79f..5513af1b 100644
--- a/libs/angular-testing/tsconfig.json
+++ b/libs/angular-testing/tsconfig.json
@@ -7,7 +7,8 @@
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
- "esModuleInterop": true
+ "esModuleInterop": true,
+ "types": ["jest", "node"],
},
"files": [],
"include": [],
diff --git a/libs/angular-testing/tsconfig.lib.json b/libs/angular-testing/tsconfig.lib.json
index b9561ca9..33af08a4 100644
--- a/libs/angular-testing/tsconfig.lib.json
+++ b/libs/angular-testing/tsconfig.lib.json
@@ -5,7 +5,6 @@
"declaration": true,
"declarationMap": true,
"inlineSources": true,
- "types": [],
"target": "es2022",
"useDefineForClassFields": false
},
diff --git a/package-lock.json b/package-lock.json
index 81101900..10807c90 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@onecx/onecx-portal-ui-libs",
- "version": "5.13.0",
+ "version": "5.23.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@onecx/onecx-portal-ui-libs",
- "version": "5.13.0",
+ "version": "5.23.3",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
@@ -121,7 +121,7 @@
},
"libs/portal-layout-styles": {
"name": "@onecx/portal-layout-styles",
- "version": "5.13.0",
+ "version": "5.23.3",
"license": "Apache-2.0",
"peerDependencies": {
"tslib": "^2.6.3"
|