@theseam/ui-common 1.0.2-beta.83 → 1.0.2-beta.84

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import { __decorate } from 'tslib';
2
2
  import { trigger, transition, style, animate } from '@angular/animations';
3
- import { coerceArray } from '@angular/cdk/coercion';
3
+ import { coerceArray, coerceBooleanProperty } from '@angular/cdk/coercion';
4
4
  import { DataSource, isDataSource } from '@angular/cdk/collections';
5
5
  import * as i0 from '@angular/core';
6
6
  import { EventEmitter, Output, Input, ChangeDetectionStrategy, Component, ContentChildren, ViewChild, Directive, Injectable, inject, TemplateRef, ContentChild, Self, Inject, forwardRef, InjectionToken, Optional, isDevMode, input, ChangeDetectorRef, ElementRef, HostListener, HostBinding, NgModule } from '@angular/core';
@@ -14,7 +14,7 @@ import { InputBoolean, InputNumber } from '@theseam/ui-common/core';
14
14
  import { THESEAM_DATA_FILTER, THESEAM_DATA_FILTER_CONTAINER, composeDataFilterStates, composeDataFilters, TheSeamDataFiltersModule } from '@theseam/ui-common/data-filters';
15
15
  import { notNullOrUndefined, isNullOrUndefined, isNullOrUndefinedOrEmpty, notNullOrUndefinedOrEmpty, hasProperty, arrayMoveMutable, waitOnConditionAsync, observeControlValue } from '@theseam/ui-common/utils';
16
16
  import * as i4 from '@theseam/ui-common/menu';
17
- import { MenuComponent, TheSeamMenuModule } from '@theseam/ui-common/menu';
17
+ import { MenuComponent, TheSeamMenuModule, TheSeamMenuHarness } from '@theseam/ui-common/menu';
18
18
  import * as i1 from '@theseam/ui-common/confirm-dialog';
19
19
  import { TheSeamConfirmDialogModule } from '@theseam/ui-common/confirm-dialog';
20
20
  import * as i2 from '@angular/router';
@@ -41,7 +41,7 @@ import { NgSelectModule } from '@ng-select/ng-select';
41
41
  import * as i4$1 from '@theseam/ui-common/form-field';
42
42
  import { TheSeamFormFieldModule } from '@theseam/ui-common/form-field';
43
43
  import * as i4$2 from '@theseam/ui-common/checkbox';
44
- import { TheSeamCheckboxComponent } from '@theseam/ui-common/checkbox';
44
+ import { TheSeamCheckboxComponent, TheSeamCheckboxHarness } from '@theseam/ui-common/checkbox';
45
45
  import * as i3$2 from '@theseam/ui-common/dynamic';
46
46
  import { THESEAM_DYNAMIC_DATA } from '@theseam/ui-common/dynamic';
47
47
  import * as i1$3 from 'ngx-toastr';
@@ -58,6 +58,8 @@ import { OverlayModule } from '@angular/cdk/overlay';
58
58
  import * as i1$6 from '@theseam/ui-common/scrollbar';
59
59
  import { A11yModule } from '@angular/cdk/a11y';
60
60
  import { TheSeamToggleGroupModule } from '@theseam/ui-common/toggle-group';
61
+ import { ComponentHarness, HarnessPredicate, ContentContainerComponentHarness } from '@angular/cdk/testing';
62
+ import { TheSeamNgSelectHarness } from '@theseam/ui-common/testing';
61
63
 
62
64
  class DatatableActionMenuItemComponent {
63
65
  label;
@@ -4619,9 +4621,671 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImpo
4619
4621
  }]
4620
4622
  }] });
4621
4623
 
4624
+ const SIMPLE_COLUMNS = [
4625
+ { prop: 'name', name: 'Name' },
4626
+ { prop: 'age', name: 'Age' },
4627
+ { prop: 'color', name: 'Color' },
4628
+ ];
4629
+ const SIMPLE_ROWS = [
4630
+ { name: 'Mark', age: 27, color: 'blue' },
4631
+ { name: 'Joe', age: 33, color: 'green' },
4632
+ { name: 'Alice', age: 30, color: 'red' },
4633
+ { name: 'Bill', age: 40, color: 'orange' },
4634
+ { name: 'Sally', age: 25, color: 'purple' },
4635
+ ];
4636
+ const FILTERABLE_COLUMNS = [
4637
+ { prop: 'name', name: 'Name', filterable: true },
4638
+ {
4639
+ prop: 'age',
4640
+ name: 'Age',
4641
+ filterable: true,
4642
+ filterOptions: { filterType: 'search-numeric' },
4643
+ },
4644
+ {
4645
+ prop: 'startDate',
4646
+ name: 'Start Date',
4647
+ cellType: 'date',
4648
+ cellTypeConfig: { type: 'date' },
4649
+ filterable: true,
4650
+ filterOptions: { dateType: 'date' },
4651
+ },
4652
+ { prop: 'color', name: 'Favorite Color', filterable: true },
4653
+ {
4654
+ prop: 'candy',
4655
+ name: 'Favorite Candy',
4656
+ filterable: true,
4657
+ filterOptions: {
4658
+ filterProp: 'candyAttributes',
4659
+ filterType: 'search-candy',
4660
+ },
4661
+ },
4662
+ ];
4663
+ const FILTERABLE_ROWS = [
4664
+ {
4665
+ name: 'Mark',
4666
+ age: 27,
4667
+ color: 'blue',
4668
+ candy: 'Reeses',
4669
+ candyAttributes: ['chocolatey', 'nutty'],
4670
+ startDate: '2017-01-21 20:15:20.4166667 +00:00',
4671
+ },
4672
+ {
4673
+ name: 'Joe',
4674
+ age: 33,
4675
+ color: 'green',
4676
+ candy: 'Hershey Bar',
4677
+ candyAttributes: ['chocolatey'],
4678
+ startDate: '2012-04-25 17:29:36.4266667 +00:00',
4679
+ },
4680
+ {
4681
+ name: 'Shelby',
4682
+ age: 30,
4683
+ color: 'purple',
4684
+ candy: 'Snickers',
4685
+ candyAttributes: ['chocolatey', 'nutty'],
4686
+ startDate: '2020-11-18 20:47:25.1733333 +00:00',
4687
+ },
4688
+ {
4689
+ name: 'Jason',
4690
+ age: 'abc',
4691
+ color: 'orange',
4692
+ candy: 'Whoppers',
4693
+ candyAttributes: ['chocolatey'],
4694
+ startDate: '2016-05-24 23:13:26.3400000 +00:00',
4695
+ },
4696
+ {
4697
+ name: 'David',
4698
+ age: null,
4699
+ color: 'blue',
4700
+ candy: 'Skittles',
4701
+ candyAttributes: ['fruity'],
4702
+ startDate: '2021-06-29 16:31:37.2733333 +00:00',
4703
+ },
4704
+ {
4705
+ name: 'Pam',
4706
+ age: null,
4707
+ color: 'red',
4708
+ candy: 'Starbursts',
4709
+ candyAttributes: ['fruity'],
4710
+ startDate: '2012-08-11 04:00:00.000000 +00:00',
4711
+ },
4712
+ {
4713
+ name: 'New Employee',
4714
+ age: null,
4715
+ color: null,
4716
+ candy: null,
4717
+ candyAttributes: undefined,
4718
+ startDate: null,
4719
+ },
4720
+ ];
4721
+ function createRows(count) {
4722
+ const colors = ['blue', 'green', 'red', 'orange', 'purple', 'grey'];
4723
+ return Array.from({ length: count }, (_, i) => ({
4724
+ name: `Person ${i + 1}`,
4725
+ age: 20 + (i % 50),
4726
+ color: colors[i % colors.length],
4727
+ }));
4728
+ }
4729
+
4730
+ class TheSeamDatatableActionMenuHarness extends ComponentHarness {
4731
+ static hostSelector = 'seam-datatable-action-menu';
4732
+ static with(options = {}) {
4733
+ return new HarnessPredicate(this, options);
4734
+ }
4735
+ async _getMenuHarness() {
4736
+ return this.locatorFor(TheSeamMenuHarness)();
4737
+ }
4738
+ /** Whether the action menu is open. */
4739
+ async isOpen() {
4740
+ return (await this._getMenuHarness()).isOpen();
4741
+ }
4742
+ /** Opens the action menu. */
4743
+ async open() {
4744
+ return (await this._getMenuHarness()).open();
4745
+ }
4746
+ /** Closes the action menu. */
4747
+ async close() {
4748
+ return (await this._getMenuHarness()).close();
4749
+ }
4750
+ /**
4751
+ * Gets the menu items in the action menu.
4752
+ * The menu must be opened first (call `open()`) or use `clickItem()` which opens automatically.
4753
+ */
4754
+ async getItems(filters) {
4755
+ return (await this._getMenuHarness()).getItems(filters);
4756
+ }
4757
+ /**
4758
+ * Opens the menu and clicks an item by text.
4759
+ * Supports sub-menu navigation via additional filter arguments.
4760
+ */
4761
+ async clickItem(itemFilter, ...subItemFilters) {
4762
+ return (await this._getMenuHarness()).clickItem(itemFilter, ...subItemFilters);
4763
+ }
4764
+ }
4765
+
4766
+ class TheSeamDatatableCellHarness extends ComponentHarness {
4767
+ static hostSelector = '.datatable-body-cell';
4768
+ static with(options = {}) {
4769
+ return new HarnessPredicate(this, options).addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.getText(), text));
4770
+ }
4771
+ /** Gets the text content of the cell. */
4772
+ async getText() {
4773
+ return (await this.host()).text();
4774
+ }
4775
+ /** Clicks the cell. */
4776
+ async click() {
4777
+ return (await this.host()).click();
4778
+ }
4779
+ /**
4780
+ * Gets a child harness of the given type from within this cell.
4781
+ * Useful for retrieving cell-type harnesses (e.g., currency, date, icon).
4782
+ *
4783
+ * Returns `null` if no matching harness is found.
4784
+ */
4785
+ async getCellTypeHarness(harnessType) {
4786
+ return this.locatorForOptional(harnessType)();
4787
+ }
4788
+ }
4789
+
4790
+ class TheSeamDatatableColumnFilterMenuHarness extends ComponentHarness {
4791
+ static hostSelector = 'seam-datatable-column-filter-menu';
4792
+ static with(options = {}) {
4793
+ return new HarnessPredicate(this, options);
4794
+ }
4795
+ /** Gets the filter type by checking which sub-component is rendered. */
4796
+ async getFilterType() {
4797
+ if ((await this.locatorForOptional('seam-datatable-column-filter-search-text')()) !== null) {
4798
+ return 'search-text';
4799
+ }
4800
+ if ((await this.locatorForOptional('seam-datatable-column-filter-search-numeric')()) !== null) {
4801
+ return 'search-numeric';
4802
+ }
4803
+ if ((await this.locatorForOptional('seam-datatable-column-filter-search-date')()) !== null) {
4804
+ return 'search-date';
4805
+ }
4806
+ return 'custom';
4807
+ }
4808
+ /** Gets the search type ng-select harness. */
4809
+ async getSearchTypeSelect() {
4810
+ return this.locatorFor(TheSeamNgSelectHarness)();
4811
+ }
4812
+ /** Gets the current search type value (e.g. "Contains", "Equals", "Between"). */
4813
+ async getSearchType() {
4814
+ const select = await this.getSearchTypeSelect();
4815
+ return select.getValue();
4816
+ }
4817
+ /**
4818
+ * Selects a search type from the dropdown by its displayed label
4819
+ * (e.g. `'Before'`, `'Contains'`, `'Between'`).
4820
+ *
4821
+ * Note: this matches the visible option text, not the underlying form value
4822
+ * (e.g. pass `'Before'` not `'lt'`).
4823
+ */
4824
+ async selectSearchType(label) {
4825
+ const select = await this.getSearchTypeSelect();
4826
+ await select.clickOption({ label });
4827
+ }
4828
+ /** Gets the primary search input (formControlName="searchText"). */
4829
+ async getSearchInput() {
4830
+ return this.locatorForOptional('input[formcontrolname="searchText"]')();
4831
+ }
4832
+ /** Gets the range start input (formControlName="fromText"). */
4833
+ async getRangeStartInput() {
4834
+ return this.locatorForOptional('input[formcontrolname="fromText"]')();
4835
+ }
4836
+ /** Gets the range end input (formControlName="toText"). */
4837
+ async getRangeEndInput() {
4838
+ return this.locatorForOptional('input[formcontrolname="toText"]')();
4839
+ }
4840
+ /**
4841
+ * Sets the primary search value.
4842
+ * Clears any existing value first, then types the new value.
4843
+ */
4844
+ async setSearchValue(value) {
4845
+ const input = await this.getSearchInput();
4846
+ if (!input) {
4847
+ throw Error('Search input not found. The current search type may not have a text input.');
4848
+ }
4849
+ await input.clear();
4850
+ await input.sendKeys(value);
4851
+ }
4852
+ /**
4853
+ * Sets the range values (for "Between" search types on numeric/date filters).
4854
+ */
4855
+ async setRangeValues(from, to) {
4856
+ const fromInput = await this.getRangeStartInput();
4857
+ const toInput = await this.getRangeEndInput();
4858
+ if (!fromInput || !toInput) {
4859
+ throw Error('Range inputs not found. The current search type may not support range values.');
4860
+ }
4861
+ await fromInput.clear();
4862
+ await fromInput.sendKeys(from);
4863
+ await toInput.clear();
4864
+ await toInput.sendKeys(to);
4865
+ }
4866
+ /** Clicks the "Clear" button to reset the filter. */
4867
+ async clear() {
4868
+ const buttons = await this.locatorForAll('button')();
4869
+ for (const btn of buttons) {
4870
+ if ((await btn.text()).trim() === 'Clear') {
4871
+ return btn.click();
4872
+ }
4873
+ }
4874
+ throw Error('Clear button not found.');
4875
+ }
4876
+ /** Clicks the "Apply" button (only present in submit mode). */
4877
+ async apply() {
4878
+ const submitBtn = await this.locatorForOptional('button[type="submit"]')();
4879
+ if (!submitBtn) {
4880
+ throw Error('Apply button not found. The filter may be using valueChanges mode.');
4881
+ }
4882
+ return submitBtn.click();
4883
+ }
4884
+ /** Whether the "Apply" button is present (submit mode). */
4885
+ async hasApplyButton() {
4886
+ return (await this.locatorForOptional('button[type="submit"]')()) !== null;
4887
+ }
4888
+ /** Whether the "Clear" button is disabled (filter is already at default). */
4889
+ async isClearDisabled() {
4890
+ const buttons = await this.locatorForAll('button')();
4891
+ for (const btn of buttons) {
4892
+ if ((await btn.text()).trim() === 'Clear') {
4893
+ const disabled = await btn.getAttribute('disabled');
4894
+ return disabled !== null;
4895
+ }
4896
+ }
4897
+ throw Error('Clear button not found.');
4898
+ }
4899
+ }
4900
+
4901
+ class TheSeamDatatableColumnPreferencesButtonHarness extends ComponentHarness {
4902
+ static hostSelector = 'seam-datatable-column-preferences-button';
4903
+ _documentRootLocator = this.documentRootLocatorFactory();
4904
+ static with(options = {}) {
4905
+ return new HarnessPredicate(this, options);
4906
+ }
4907
+ async _getMenuHarness() {
4908
+ return this.locatorFor(TheSeamMenuHarness)();
4909
+ }
4910
+ /** Opens the preferences menu by clicking the button. */
4911
+ async open() {
4912
+ return (await this._getMenuHarness()).open();
4913
+ }
4914
+ /** Closes the preferences menu. */
4915
+ async close() {
4916
+ return (await this._getMenuHarness()).close();
4917
+ }
4918
+ /** Whether the preferences menu is open. */
4919
+ async isOpen() {
4920
+ return (await this._getMenuHarness()).isOpen();
4921
+ }
4922
+ /**
4923
+ * Opens the "Show/Hide Columns" popover and returns the checkbox harnesses
4924
+ * for each column. The checkboxes are rendered inside a CDK overlay popover.
4925
+ */
4926
+ async getColumnCheckboxes() {
4927
+ await this.open();
4928
+ const menu = await this._getMenuHarness();
4929
+ const items = await menu.getItems({ text: /Show\/Hide Columns/ });
4930
+ if (items.length === 0) {
4931
+ throw Error('"Show/Hide Columns" menu item not found.');
4932
+ }
4933
+ await items[0].click();
4934
+ // The column preferences component renders in a popover (CDK overlay)
4935
+ return this._documentRootLocator.locatorForAll(TheSeamCheckboxHarness)();
4936
+ }
4937
+ /**
4938
+ * Toggles a column's visibility by name.
4939
+ * Opens the Show/Hide Columns popover and clicks the matching checkbox.
4940
+ */
4941
+ async toggleColumn(name) {
4942
+ const checkboxes = await this.getColumnCheckboxes();
4943
+ for (const checkbox of checkboxes) {
4944
+ const host = await checkbox.host();
4945
+ const text = await host.text();
4946
+ const matches = typeof name === 'string' ? text.trim() === name : name.test(text.trim());
4947
+ if (matches) {
4948
+ await checkbox.click();
4949
+ return;
4950
+ }
4951
+ }
4952
+ throw Error(`Column checkbox matching "${name}" not found.`);
4953
+ }
4954
+ /** Clicks the "Reset Columns" menu item. */
4955
+ async resetColumns() {
4956
+ const menu = await this._getMenuHarness();
4957
+ await menu.clickItem({ text: /Reset Columns/ });
4958
+ }
4959
+ }
4960
+
4961
+ class TheSeamDatatableExportButtonHarness extends ComponentHarness {
4962
+ static hostSelector = 'seam-datatable-export-button';
4963
+ static with(options = {}) {
4964
+ return new HarnessPredicate(this, options);
4965
+ }
4966
+ async _getMenuHarness() {
4967
+ return this.locatorFor(TheSeamMenuHarness)();
4968
+ }
4969
+ /** Opens the export menu. */
4970
+ async open() {
4971
+ return (await this._getMenuHarness()).open();
4972
+ }
4973
+ /** Closes the export menu. */
4974
+ async close() {
4975
+ return (await this._getMenuHarness()).close();
4976
+ }
4977
+ /** Whether the export menu is open. */
4978
+ async isOpen() {
4979
+ return (await this._getMenuHarness()).isOpen();
4980
+ }
4981
+ /** Whether the export button is disabled. */
4982
+ async isDisabled() {
4983
+ return (await this._getMenuHarness()).isDisabled();
4984
+ }
4985
+ /** Gets the exporter menu items. The menu must be opened first or use `clickExporter()`. */
4986
+ async getExporters(filters) {
4987
+ return (await this._getMenuHarness()).getItems(filters);
4988
+ }
4989
+ /** Opens the menu and clicks an exporter by label. */
4990
+ async clickExporter(label) {
4991
+ return (await this._getMenuHarness()).clickItem({ text: label });
4992
+ }
4993
+ }
4994
+
4995
+ class TheSeamDatatableHeaderCellHarness extends ComponentHarness {
4996
+ static hostSelector = '.datatable-header-cell';
4997
+ static with(options = {}) {
4998
+ return new HarnessPredicate(this, options)
4999
+ .addOption('name', options.name, (harness, name) => HarnessPredicate.stringMatches(harness.getName(), name))
5000
+ .addOption('sortDirection', options.sortDirection, async (harness, dir) => (await harness.getSortDirection()) === dir);
5001
+ }
5002
+ /** Gets the column name text. */
5003
+ async getName() {
5004
+ const sortBtn = await this.locatorForOptional('.datatable-sort-target')();
5005
+ if (sortBtn) {
5006
+ return sortBtn.text();
5007
+ }
5008
+ // Fallback: get text from the header cell itself
5009
+ return (await this.host()).text();
5010
+ }
5011
+ /** Gets the current sort direction of this column. */
5012
+ async getSortDirection() {
5013
+ const host = await this.host();
5014
+ if (await host.hasClass('sort-asc')) {
5015
+ return 'asc';
5016
+ }
5017
+ if (await host.hasClass('sort-desc')) {
5018
+ return 'desc';
5019
+ }
5020
+ return 'none';
5021
+ }
5022
+ /** Whether this column is sortable. */
5023
+ async isSortable() {
5024
+ return (await this.host()).hasClass('sortable');
5025
+ }
5026
+ /** Clicks the sort button to cycle the sort direction. */
5027
+ async sort() {
5028
+ const sortBtn = await this.locatorForOptional('.datatable-sort-target')();
5029
+ if (sortBtn) {
5030
+ return sortBtn.click();
5031
+ }
5032
+ // Fallback: click the header cell itself
5033
+ return (await this.host()).click();
5034
+ }
5035
+ /** Whether this column has a filter button. */
5036
+ async isFilterable() {
5037
+ const filterBtn = await this.locatorForOptional('.datatable-column-header-filter-button')();
5038
+ return filterBtn !== null;
5039
+ }
5040
+ /** Whether the column filter is currently active. */
5041
+ async isFilterActive() {
5042
+ const filterBtn = await this.locatorForOptional('.datatable-column-header-filter-button')();
5043
+ if (!filterBtn) {
5044
+ return false;
5045
+ }
5046
+ return filterBtn.hasClass('datatable-column-header-filter-button-active');
5047
+ }
5048
+ /** Opens the column filter menu by clicking the filter button. */
5049
+ async openFilter() {
5050
+ const filterBtn = await this.locatorForOptional('.datatable-column-header-filter-button')();
5051
+ if (!filterBtn) {
5052
+ throw Error('This column does not have a filter button.');
5053
+ }
5054
+ return filterBtn.click();
5055
+ }
5056
+ /**
5057
+ * Opens the filter and returns the filter menu harness.
5058
+ * The filter menu renders in a CDK overlay, so this uses the document root locator.
5059
+ */
5060
+ async getFilterMenu() {
5061
+ await this.openFilter();
5062
+ const rootLocator = this.documentRootLocatorFactory();
5063
+ const menu = await rootLocator.locatorForOptional(TheSeamDatatableColumnFilterMenuHarness)();
5064
+ if (!menu) {
5065
+ throw Error('Column filter menu not found after opening. It may not have rendered yet.');
5066
+ }
5067
+ return menu;
5068
+ }
5069
+ /** Whether this header cell is a checkbox column (select-all). */
5070
+ async isCheckboxColumn() {
5071
+ const checkbox = await this.locatorForOptional('.datatable-checkbox input[type="checkbox"]')();
5072
+ return checkbox !== null;
5073
+ }
5074
+ /** Clicks the select-all checkbox in this header cell. */
5075
+ async clickCheckbox() {
5076
+ const checkbox = await this.locatorForOptional('.datatable-checkbox input[type="checkbox"]')();
5077
+ if (!checkbox) {
5078
+ throw Error('This header cell does not have a select-all checkbox.');
5079
+ }
5080
+ return checkbox.click();
5081
+ }
5082
+ }
5083
+
5084
+ class TheSeamDatatableMenuBarHarness extends ContentContainerComponentHarness {
5085
+ static hostSelector = 'seam-datatable-menu-bar';
5086
+ static with(options = {}) {
5087
+ return new HarnessPredicate(this, options);
5088
+ }
5089
+ /** Gets the text content of the menu bar. */
5090
+ async getTextContent() {
5091
+ return (await this.host()).text();
5092
+ }
5093
+ }
5094
+
5095
+ class TheSeamDatatablePagerButtonHarness extends ComponentHarness {
5096
+ static hostSelector = '.pager .pages';
5097
+ /** Creates a `HarnessPredicate` used to locate a particular `MyMenuHarness`. */
5098
+ static with(options) {
5099
+ return new HarnessPredicate(TheSeamDatatablePagerButtonHarness, options).addOption('page number', options.pageNumber, (harness, index) => HarnessPredicate.stringMatches(harness.getLabel(), `page ${index}`));
5100
+ }
5101
+ async getLabel() {
5102
+ return (await this.host()).getAttribute('aria-label');
5103
+ }
5104
+ async getAnchor() {
5105
+ return this.locatorFor('a')();
5106
+ }
5107
+ }
5108
+
5109
+ class TheSeamDatatablePagerHarness extends ComponentHarness {
5110
+ static hostSelector = 'datatable-pager';
5111
+ _activePageButton = this.locatorFor('.pager .pages.active');
5112
+ async getPageButtonHarness(pageNumber) {
5113
+ const getBtnAtIndex = this.locatorFor(TheSeamDatatablePagerButtonHarness.with({ pageNumber }));
5114
+ return getBtnAtIndex();
5115
+ }
5116
+ async getCurrentPageNumber() {
5117
+ const btn = await this._activePageButton();
5118
+ const label = await btn.getAttribute('aria-label');
5119
+ if (label === null) {
5120
+ throw Error(`Current page label not found.`);
5121
+ }
5122
+ return parseInt(label.replace('page ', ''), 10);
5123
+ }
5124
+ }
5125
+
5126
+ class TheSeamDatatableRowHarness extends ComponentHarness {
5127
+ static hostSelector = '.datatable-body-row';
5128
+ static with(options = {}) {
5129
+ return new HarnessPredicate(this, options).addOption('selected', options.selected, async (harness, selected) => (await harness.isSelected()) === selected);
5130
+ }
5131
+ /** Gets all cells in this row, optionally filtered. */
5132
+ async getCells(filters) {
5133
+ return this.locatorForAll(filters
5134
+ ? TheSeamDatatableCellHarness.with(filters)
5135
+ : TheSeamDatatableCellHarness)();
5136
+ }
5137
+ /** Gets a cell by its index in the row. */
5138
+ async getCell(index) {
5139
+ const cells = await this.getCells();
5140
+ if (index < 0 || index >= cells.length) {
5141
+ throw Error(`Cell index ${index} is out of bounds. Row has ${cells.length} cells.`);
5142
+ }
5143
+ return cells[index];
5144
+ }
5145
+ /** Convenience method to get the text content of a cell by index. */
5146
+ async getCellText(index) {
5147
+ return (await this.getCell(index)).getText();
5148
+ }
5149
+ /** Whether this row is selected. */
5150
+ async isSelected() {
5151
+ return (await this.host()).hasClass('active');
5152
+ }
5153
+ /** Clicks the row to activate it. */
5154
+ async click() {
5155
+ return (await this.host()).click();
5156
+ }
5157
+ /** Gets the action menu harness for this row, or `null` if no action menu exists. */
5158
+ async getActionMenu() {
5159
+ return this.locatorForOptional(TheSeamDatatableActionMenuHarness)();
5160
+ }
5161
+ // -- Row Detail --
5162
+ /** Whether this row's detail section is expanded. */
5163
+ async isExpanded() {
5164
+ const detail = await this.locatorForOptional('.datatable-row-detail')();
5165
+ return detail !== null;
5166
+ }
5167
+ /** Gets the row detail content element, or `null` if not expanded. */
5168
+ async getDetailContent() {
5169
+ return this.locatorForOptional('.datatable-row-detail')();
5170
+ }
5171
+ // -- Selection --
5172
+ /** Whether this row has a selection checkbox. */
5173
+ async hasCheckbox() {
5174
+ const checkbox = await this.locatorForOptional('.datatable-checkbox input[type="checkbox"]')();
5175
+ return checkbox !== null;
5176
+ }
5177
+ /** Clicks the selection checkbox on this row. */
5178
+ async clickCheckbox() {
5179
+ const checkbox = await this.locatorForOptional('.datatable-checkbox input[type="checkbox"]')();
5180
+ if (!checkbox) {
5181
+ throw Error('This row does not have a selection checkbox.');
5182
+ }
5183
+ return checkbox.click();
5184
+ }
5185
+ }
5186
+
5187
+ class TheSeamDatatableHarness extends ComponentHarness {
5188
+ static hostSelector = 'seam-datatable';
5189
+ static with(options = {}) {
5190
+ return new HarnessPredicate(this, options);
5191
+ }
5192
+ _pager = this.locatorForOptional(TheSeamDatatablePagerHarness);
5193
+ // -- Pager --
5194
+ async getCurrentPage() {
5195
+ const pager = await this._pager();
5196
+ if (!pager) {
5197
+ throw Error('Pager not found on this datatable.');
5198
+ }
5199
+ return pager.getCurrentPageNumber();
5200
+ }
5201
+ async getPager() {
5202
+ return this._pager();
5203
+ }
5204
+ // -- Rows --
5205
+ /** Gets all visible body rows, optionally filtered. */
5206
+ async getRows(filters) {
5207
+ return this.locatorForAll(filters
5208
+ ? TheSeamDatatableRowHarness.with(filters)
5209
+ : TheSeamDatatableRowHarness)();
5210
+ }
5211
+ /** Gets a body row by its index. */
5212
+ async getRow(index) {
5213
+ const rows = await this.getRows();
5214
+ if (index < 0 || index >= rows.length) {
5215
+ throw Error(`Row index ${index} is out of bounds. Table has ${rows.length} rows.`);
5216
+ }
5217
+ return rows[index];
5218
+ }
5219
+ /** Gets the number of visible body rows. */
5220
+ async getRowCount() {
5221
+ return (await this.getRows()).length;
5222
+ }
5223
+ // -- Header Cells --
5224
+ /** Gets all header cells, optionally filtered. */
5225
+ async getHeaderCells(filters) {
5226
+ return this.locatorForAll(filters
5227
+ ? TheSeamDatatableHeaderCellHarness.with(filters)
5228
+ : TheSeamDatatableHeaderCellHarness)();
5229
+ }
5230
+ /** Gets a header cell by column name. */
5231
+ async getHeaderCell(name) {
5232
+ const cells = await this.getHeaderCells({ name });
5233
+ if (cells.length === 0) {
5234
+ throw Error(`Header cell with name matching "${name}" not found.`);
5235
+ }
5236
+ return cells[0];
5237
+ }
5238
+ /** Gets the number of visible columns. */
5239
+ async getColumnCount() {
5240
+ return (await this.getHeaderCells()).length;
5241
+ }
5242
+ // -- Selection --
5243
+ /** Gets all currently selected rows. */
5244
+ async getSelectedRows() {
5245
+ return this.getRows({ selected: true });
5246
+ }
5247
+ // -- Menu Bar & Preferences --
5248
+ /** Gets the menu bar harness, or `null` if no menu bar is present. */
5249
+ async getMenuBar() {
5250
+ return this.locatorForOptional(TheSeamDatatableMenuBarHarness)();
5251
+ }
5252
+ /** Gets the column preferences button harness, or `null` if not present. */
5253
+ async getColumnPreferencesButton() {
5254
+ return this.locatorForOptional(TheSeamDatatableColumnPreferencesButtonHarness)();
5255
+ }
5256
+ // -- Convenience --
5257
+ /** Gets the text content of a cell by row and column index. */
5258
+ async getCellText(rowIndex, colIndex) {
5259
+ const row = await this.getRow(rowIndex);
5260
+ return row.getCellText(colIndex);
5261
+ }
5262
+ /** Whether the table is showing its empty message (no rows). */
5263
+ async isEmpty() {
5264
+ const emptyRow = await this.locatorForOptional('.empty-row')();
5265
+ return emptyRow !== null;
5266
+ }
5267
+ }
5268
+
5269
+ class TheSeamDatatableRefreshButtonHarness extends ComponentHarness {
5270
+ static hostSelector = 'seam-datatable-refresh-button';
5271
+ static with(options = {}) {
5272
+ return new HarnessPredicate(this, options);
5273
+ }
5274
+ _button = this.locatorFor('button');
5275
+ /** Clicks the refresh button. */
5276
+ async click() {
5277
+ return (await this._button()).click();
5278
+ }
5279
+ /** Whether the underlying button is disabled. */
5280
+ async isDisabled() {
5281
+ const disabled = await (await this._button()).getAttribute('disabled');
5282
+ return coerceBooleanProperty(disabled);
5283
+ }
5284
+ }
5285
+
4622
5286
  /**
4623
5287
  * Generated bundle index. Do not edit.
4624
5288
  */
4625
5289
 
4626
- export { CURRENT_DATATABLE_PREFERENCES_VERSION, ColumnsAlteration, ColumnsDataFilter, ColumnsFiltersService, DatatableActionMenuComponent, DatatableActionMenuItemComponent, DatatableActionMenuItemDirective, DatatableActionMenuToggleDirective, DatatableCellTplDirective, DatatableColumnChangesService, DatatableColumnComponent, DatatableColumnFilterMenuComponent, DatatableColumnFilterSearchDateComponent, DatatableColumnFilterSearchNumericComponent, DatatableColumnFilterSearchTextComponent, DatatableColumnFilterTplDirective, DatatableColumnPreferencesButtonComponent, DatatableColumnPreferencesComponent, DatatableComponent, DatatableDataSource, DatatableExportButtonComponent, DatatableFilterDirective, DatatableFooterTplDirective, DatatableGqlDataSource, DatatableMenuBarColumnCenterComponent, DatatableMenuBarColumnLeftComponent, DatatableMenuBarColumnRightComponent, DatatableMenuBarComponent, DatatableMenuBarRowComponent, DatatableMenuBarTextComponent, DatatablePreferencesService, DatatableRefreshButtonComponent, DatatableRefreshService, DatatableRowActionItemDirective, DatatableRowDetailTplDirective, EMPTY_DATATABLE_PREFERENCES, SearchDateColumnsDataFilter, SearchNumericColumnsDataFilter, SearchTextColumnsDataFilter, THESEAM_COLUMNS_DATA_FILTER, THESEAM_COLUMNS_DATA_FILTERS_DEFAULT, THESEAM_COLUMNS_DATA_FILTER_DATE_RANGE_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_DATE_SEARCH_NAME, THESEAM_COLUMNS_DATA_FILTER_DATE_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_DATE_SELECT_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_DATE_TEXT_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_NUMERIC_RANGE_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_NUMERIC_SEARCH_NAME, THESEAM_COLUMNS_DATA_FILTER_NUMERIC_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_NUMERIC_SELECT_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_NUMERIC_TEXT_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_TEXT_SEARCH_NAME, THESEAM_COLUMNS_DATA_FILTER_TEXT_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_TEXT_SELECT_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_TEXT_TEXT_SEARCH_TYPES, THESEAM_DATATABLE, THESEAM_DATATABLE_CONFIG, THESEAM_DATATABLE_PREFERENCES_ACCESSOR, THESEAM_MENUBAR_ITEM_DATA, TheSeamDatatableColumnFilterDirective, TheSeamDatatableFooterDirective, TheSeamDatatableModule, TheSeamDatatableRowDetailDirective, TheSeamDatatableScrollbarHelperService, _THESEAM_DATATABLE, _THESEAM_DATATABLE_ACCESSOR, _THESEAM_DATA_FILTER_CONTAINER, getFormattedDateForComparison, isColumnBoundToProp, mapColumnsAlterationsStates, withStoredColumnInfo };
5290
+ export { CURRENT_DATATABLE_PREFERENCES_VERSION, ColumnsAlteration, ColumnsDataFilter, ColumnsFiltersService, DatatableActionMenuComponent, DatatableActionMenuItemComponent, DatatableActionMenuItemDirective, DatatableActionMenuToggleDirective, DatatableCellTplDirective, DatatableColumnChangesService, DatatableColumnComponent, DatatableColumnFilterMenuComponent, DatatableColumnFilterSearchDateComponent, DatatableColumnFilterSearchNumericComponent, DatatableColumnFilterSearchTextComponent, DatatableColumnFilterTplDirective, DatatableColumnPreferencesButtonComponent, DatatableColumnPreferencesComponent, DatatableComponent, DatatableDataSource, DatatableExportButtonComponent, DatatableFilterDirective, DatatableFooterTplDirective, DatatableGqlDataSource, DatatableMenuBarColumnCenterComponent, DatatableMenuBarColumnLeftComponent, DatatableMenuBarColumnRightComponent, DatatableMenuBarComponent, DatatableMenuBarRowComponent, DatatableMenuBarTextComponent, DatatablePreferencesService, DatatableRefreshButtonComponent, DatatableRefreshService, DatatableRowActionItemDirective, DatatableRowDetailTplDirective, EMPTY_DATATABLE_PREFERENCES, FILTERABLE_COLUMNS, FILTERABLE_ROWS, SIMPLE_COLUMNS, SIMPLE_ROWS, SearchDateColumnsDataFilter, SearchNumericColumnsDataFilter, SearchTextColumnsDataFilter, THESEAM_COLUMNS_DATA_FILTER, THESEAM_COLUMNS_DATA_FILTERS_DEFAULT, THESEAM_COLUMNS_DATA_FILTER_DATE_RANGE_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_DATE_SEARCH_NAME, THESEAM_COLUMNS_DATA_FILTER_DATE_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_DATE_SELECT_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_DATE_TEXT_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_NUMERIC_RANGE_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_NUMERIC_SEARCH_NAME, THESEAM_COLUMNS_DATA_FILTER_NUMERIC_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_NUMERIC_SELECT_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_NUMERIC_TEXT_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_TEXT_SEARCH_NAME, THESEAM_COLUMNS_DATA_FILTER_TEXT_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_TEXT_SELECT_SEARCH_TYPES, THESEAM_COLUMNS_DATA_FILTER_TEXT_TEXT_SEARCH_TYPES, THESEAM_DATATABLE, THESEAM_DATATABLE_CONFIG, THESEAM_DATATABLE_PREFERENCES_ACCESSOR, THESEAM_MENUBAR_ITEM_DATA, TheSeamDatatableActionMenuHarness, TheSeamDatatableCellHarness, TheSeamDatatableColumnFilterDirective, TheSeamDatatableColumnFilterMenuHarness, TheSeamDatatableColumnPreferencesButtonHarness, TheSeamDatatableExportButtonHarness, TheSeamDatatableFooterDirective, TheSeamDatatableHarness, TheSeamDatatableHeaderCellHarness, TheSeamDatatableMenuBarHarness, TheSeamDatatableModule, TheSeamDatatablePagerButtonHarness, TheSeamDatatablePagerHarness, TheSeamDatatableRefreshButtonHarness, TheSeamDatatableRowDetailDirective, TheSeamDatatableRowHarness, TheSeamDatatableScrollbarHelperService, _THESEAM_DATATABLE, _THESEAM_DATATABLE_ACCESSOR, _THESEAM_DATA_FILTER_CONTAINER, createRows, getFormattedDateForComparison, isColumnBoundToProp, mapColumnsAlterationsStates, withStoredColumnInfo };
4627
5291
  //# sourceMappingURL=theseam-ui-common-datatable.mjs.map