diff --git a/packages/angular-sdk-components/tests/e2e/DigV2/FormFields/Phone.spec.js b/packages/angular-sdk-components/tests/e2e/DigV2/FormFields/Phone.spec.js new file mode 100644 index 00000000..1b214096 --- /dev/null +++ b/packages/angular-sdk-components/tests/e2e/DigV2/FormFields/Phone.spec.js @@ -0,0 +1,158 @@ +/* eslint-disable no-template-curly-in-string */ +/* eslint-disable no-undef */ + +const { test, expect } = require('@playwright/test'); + +const config = require('../../../config'); +const common = require('../../../common'); + +// These values represent the data values used for the conditions and are initialised in pyDefault DT +const isDisabled = true; +const isVisible = true; + +test.beforeEach(async ({ page }) => { + await page.setViewportSize({ width: 1920, height: 1080 }); + await page.goto('http://localhost:3500/portal', { waitUntil: 'networkidle' }); +}); + +test.describe('E2E test', () => { + let attributes; + + test('should login, create case and run the Phone tests', async ({ page }) => { + await common.Login(config.config.apps.digv2.user.username, config.config.apps.digv2.user.password, page); + + /** Testing announcement banner presence */ + const announcementBanner = page.locator('h2:has-text("Announcements")'); + await expect(announcementBanner).toBeVisible(); + + /** Testing worklist presence */ + const worklist = page.locator('div[id="worklist"]:has-text("My Worklist")'); + await expect(worklist).toBeVisible(); + + let createCase = page.locator('mat-list-item[id="create-case-button"]'); + await createCase.click(); + + /** Creating a Form Field case-type */ + const formFieldCase = page.locator('mat-list-item[id="case-list-item"] > span:has-text("Form Field")'); + await formFieldCase.click(); + + /** Selecting Phone from the Category dropdown */ + const selectedCategory = page.locator('mat-select[data-test-id="76729937a5eb6b0fd88c42581161facd"]'); + await selectedCategory.click(); + await page.getByRole('option', { name: 'Phone' }).click(); + + /** Selecting Required from the Sub Category dropdown */ + let selectedSubCategory = page.locator('mat-select[data-test-id="9463d5f18a8924b3200b56efaad63bda"]'); + await selectedSubCategory.click(); + await page.getByRole('option', { name: 'Required' }).click(); + + /** Required tests */ + // const requiredPhone = page.locator( + // 'div[data-test-id="af983eaa1b85b015a7654702abd0b249"] >> input' + // ); + // attributes = await common.getAttributes(requiredPhone); + // await expect(attributes.includes('required')).toBeTruthy(); + + // const notrequiredPhone = page.locator( + // 'div[data-test-id="8e20f3ae84ebed6107f2672dd430500f"] >> input' + // ); + // attributes = await common.getAttributes(notrequiredPhone); + // await expect(attributes.includes('required')).toBeFalsy(); + await page.locator('button:has-text("submit")').click(); + await expect(page.locator('mat-error')).toBeVisible(); + + const requiredPhone = page.locator('ngx-mat-intl-tel-input[data-test-id="af983eaa1b85b015a7654702abd0b249"] >> input'); + requiredPhone.type('6175551212'); + await expect(page.locator('mat-error')).toBeHidden(); + + /** Selecting Disable from the Sub Category dropdown */ + selectedSubCategory = page.locator('mat-select[data-test-id="9463d5f18a8924b3200b56efaad63bda"]'); + await selectedSubCategory.click(); + await page.getByRole('option', { name: 'Disable' }).click(); + + // /** Disable tests */ + const alwaysDisabledPhone = page.locator('ngx-mat-intl-tel-input[data-test-id="d415da67e9764d6e7cdf3d993cb54f51"] >> input'); + attributes = await common.getAttributes(alwaysDisabledPhone); + await expect(attributes.includes('disabled')).toBeTruthy(); + + const conditionallyDisabledPhone = page.locator('ngx-mat-intl-tel-input[data-test-id="b6cee3728235ed1f6cef7b11ac850ea9"] >> input'); + attributes = await common.getAttributes(conditionallyDisabledPhone); + if (isDisabled) { + await expect(attributes.includes('disabled')).toBeTruthy(); + } else { + await expect(attributes.includes('disabled')).toBeFalsy(); + } + + const neverDisabledPhone = page.locator('ngx-mat-intl-tel-input[data-test-id="b23e38f877c8a40f18507b39893a8d61"] >> input'); + attributes = await common.getAttributes(neverDisabledPhone); + await expect(attributes.includes('disabled')).toBeFalsy(); + + /** Selecting Update from the Sub Category dropdown */ + selectedSubCategory = page.locator('mat-select[data-test-id="9463d5f18a8924b3200b56efaad63bda"]'); + await selectedSubCategory.click(); + await page.getByRole('option', { name: 'Update' }).click(); + + /** Update tests */ + // const readonlyPhone = page.locator( + // 'input[data-test-id="2c511e68e41cb70907b27a00de6b18b9"]' + // ); + // attributes = await common.getAttributes(readonlyPhone); + // await expect(attributes.includes('readonly')).toBeTruthy(); + + const editablePhone = page.locator('ngx-mat-intl-tel-input[data-test-id="591e127300787ad31c414b7159469b9e"]'); + const countrySelector = editablePhone.locator('button'); + await countrySelector.click(); + await page.locator('text=United States >> nth=0').click(); + const editablePhoneInput = editablePhone.locator('input'); + await editablePhoneInput.click(); + await editablePhoneInput.type('6175551212'); + + /** Validation tests */ + const validationMsg = 'Invalid Phone'; + await editablePhoneInput.clear(); + await countrySelector.click(); + await page.locator('text=United States >> nth=0').click(); + await editablePhoneInput.click(); + /** Entering an invalid Phone number */ + await editablePhoneInput.type('61'); + await editablePhoneInput.blur(); + /** Expecting an error for Invalid phone number */ + await expect(page.locator(`mat-error:has-text("${validationMsg}")`)).toBeVisible(); + + /** Entering a valid Phone number */ + await editablePhoneInput.clear(); + await countrySelector.click(); + await page.locator('text=United States >> nth=0').click(); + await editablePhoneInput.type('6175551212'); + + await editablePhoneInput.blur(); + /** Expecting the invalid Phone number error be no longer present */ + await expect(page.locator(`mat-error:has-text("${validationMsg}")`)).toBeHidden(); + + attributes = await common.getAttributes(editablePhone); + await expect(attributes.includes('readonly')).toBeFalsy(); + + /** Selecting Visibility from the Sub Category dropdown */ + selectedSubCategory = page.locator('mat-select[data-test-id="9463d5f18a8924b3200b56efaad63bda"]'); + await selectedSubCategory.click(); + await page.getByRole('option', { name: 'Visibility' }).click(); + + /** Visibility tests */ + await expect(page.locator('ngx-mat-intl-tel-input[data-test-id="6637b718c18a1fd292d28b6abaa68d50"] >> input')).toBeVisible(); + + const neverVisiblePhone = await page.locator('div[data-test-id="f425267235530e772d7daa0a0881c822"] >> input'); + await expect(neverVisiblePhone).not.toBeVisible(); + + const conditionallyVisiblePhone = await page.locator('ngx-mat-intl-tel-input[data-test-id="ad9995a1b5001e6d153d363465371528"] >> input'); + + if (isVisible) { + await expect(conditionallyVisiblePhone).toBeVisible(); + } else { + await expect(conditionallyVisiblePhone).not.toBeVisible(); + } + }, 10000); +}); + +test.afterEach(async ({ page }) => { + await page.close(); +}); diff --git a/packages/angular-sdk-components/tests/e2e/DigV2/FormFields/Picklist.spec.js b/packages/angular-sdk-components/tests/e2e/DigV2/FormFields/Picklist.spec.js new file mode 100644 index 00000000..d6a486aa --- /dev/null +++ b/packages/angular-sdk-components/tests/e2e/DigV2/FormFields/Picklist.spec.js @@ -0,0 +1,85 @@ +/* eslint-disable no-template-curly-in-string */ +/* eslint-disable no-undef */ + +const { test, expect } = require('@playwright/test'); + +const config = require('../../../config'); +const common = require('../../../common'); + +// These values represent the data values used for the conditions and are initialised in pyDefault DT +const isDisabled = true; +const isVisible = true; + +test.beforeEach(async ({ page }) => { + await page.setViewportSize({ width: 1920, height: 1080 }); + await page.goto('http://localhost:3500/portal', { waitUntil: 'networkidle' }); +}); + +test.describe('E2E test', () => { + let attributes; + + test('should login, create case and run the Email tests', async ({ page }) => { + await common.Login(config.config.apps.digv2.user.username, config.config.apps.digv2.user.password, page); + + /** Testing announcement banner presence */ + const announcementBanner = page.locator('h2:has-text("Announcements")'); + await expect(announcementBanner).toBeVisible(); + + /** Testing worklist presence */ + const worklist = page.locator('div[id="worklist"]:has-text("My Worklist")'); + await expect(worklist).toBeVisible(); + + /** Click on the Create Case button */ + let createCase = page.locator('mat-list-item[id="create-case-button"]'); + await createCase.click(); + + /** Creating a Form Field case-type */ + const formFieldCase = page.locator('mat-list-item[id="case-list-item"] > span:has-text("Form Field")'); + await formFieldCase.click(); + + /** Selecting PickList from the Category dropdown */ + const selectedCategory = page.locator('mat-select[data-test-id="76729937a5eb6b0fd88c42581161facd"]'); + await selectedCategory.click(); + await page.getByRole('option', { name: 'PickList' }).click(); + + /** Selecting Required from the Sub Category dropdown */ + let selectedSubCategory = page.locator('mat-select[data-test-id="9463d5f18a8924b3200b56efaad63bda"]'); + await selectedSubCategory.click(); + await page.getByRole('option', { name: 'DataPage' }).click(); + + /** Dropdown tests */ + let picklistAs = page.locator('mat-select[data-test-id="683ea3aece0dce7e065d31d43f1c269b"]'); + await picklistAs.click(); + await page.getByRole('option', { name: 'Dropdown' }).click(); + + let dropdown = page.locator('mat-select[data-test-id="94cb322b7468c7827d336398e525827e"]'); + await dropdown.click(); + await page.getByRole('option', { name: 'Massachusetts' }).click(); + + /** Autocomplete tests */ + await picklistAs.click(); + await page.getByRole('option', { name: 'AutoComplete' }).click(); + + const autocomplete = page.locator('input[data-test-id="ed90c4ad051fd65a1d9f0930ec4b2276"]'); + await autocomplete.click(); + await page.locator('mat-option:has-text("Colorado")').click(); + + /** Radiobutton tests */ + await picklistAs.click(); + await page.getByRole('option', { name: 'RadioButtons' }).click(); + + const radiobutton = page.locator('mat-radio-group[data-test-id="b33340542f8f3efd4e91279520a197cf"]'); + const requiredDateInput = radiobutton.locator('mat-radio-button >> nth=0'); + await requiredDateInput.click(); + + const radiobutton2 = page.locator('mat-radio-group[data-test-id="9649dad0b2aee94bc3250d26162cb593"]'); + const requiredDateInput2 = radiobutton2.locator('mat-radio-button >> nth=1'); + await requiredDateInput2.click(); + + await page.locator('button:has-text("submit")').click(); + }, 10000); +}); + +test.afterEach(async ({ page }) => { + await page.close(); +}); diff --git a/projects/angular-sdk-library/src/lib/_components/field/auto-complete/auto-complete.component.html b/projects/angular-sdk-library/src/lib/_components/field/auto-complete/auto-complete.component.html index a245cad8..d79f5a91 100644 --- a/projects/angular-sdk-library/src/lib/_components/field/auto-complete/auto-complete.component.html +++ b/projects/angular-sdk-library/src/lib/_components/field/auto-complete/auto-complete.component.html @@ -19,7 +19,8 @@ (blur)="fieldOnBlur($event)" /> - + + {{ opt.value }} diff --git a/projects/angular-sdk-library/src/lib/_components/field/auto-complete/auto-complete.component.ts b/projects/angular-sdk-library/src/lib/_components/field/auto-complete/auto-complete.component.ts index 7d926c72..f3a66190 100644 --- a/projects/angular-sdk-library/src/lib/_components/field/auto-complete/auto-complete.component.ts +++ b/projects/angular-sdk-library/src/lib/_components/field/auto-complete/auto-complete.component.ts @@ -5,7 +5,8 @@ import { MatOptionModule } from '@angular/material/core'; import { MatAutocompleteModule } from '@angular/material/autocomplete'; import { MatInputModule } from '@angular/material/input'; import { MatFormFieldModule } from '@angular/material/form-field'; -import { interval } from 'rxjs'; +import { interval, Observable } from 'rxjs'; +import { map, startWith } from 'rxjs/operators'; import { AngularPConnectService } from '../../../_bridge/angular-pconnect'; import { Utils } from '../../../_helpers/utils'; import { ComponentMapperComponent } from '../../../_bridge/component-mapper/component-mapper.component'; @@ -55,6 +56,7 @@ export class AutoCompleteComponent implements OnInit { fieldControl = new FormControl('', null); parameters: {}; hideLabel: any; + filteredOptions: Observable>; constructor( private angularPConnect: AngularPConnectService, @@ -63,7 +65,7 @@ export class AutoCompleteComponent implements OnInit { private dataPageService: DatapageService ) {} - ngOnInit(): void { + async ngOnInit(): Promise { // First thing in initialization is registering and subscribing to the AngularPConnect service this.angularPConnectData = this.angularPConnect.registerAndSubscribeComponent(this, this.onStateChange); this.controlName$ = this.angularPConnect.getComponentID(this); @@ -75,7 +77,7 @@ export class AutoCompleteComponent implements OnInit { // call updateSelf when initializing //this.updateSelf(); - this.checkAndUpdate(); + await this.checkAndUpdate(); if (this.formGroup$ != null) { // add control to formGroup @@ -86,6 +88,11 @@ export class AutoCompleteComponent implements OnInit { this.bReadonly$ = true; this.bHasForm$ = false; } + + this.filteredOptions = this.fieldControl.valueChanges.pipe( + startWith(''), + map((value) => this._filter(value || '')) + ); } ngOnDestroy(): void { @@ -98,24 +105,29 @@ export class AutoCompleteComponent implements OnInit { } } + private _filter(value: string): Array { + const filterValue = value.toLowerCase(); + return this.options$?.filter((option) => option.value.toLowerCase().includes(filterValue)); + } + // Callback passed when subscribing to store change - onStateChange() { - this.checkAndUpdate(); + async onStateChange() { + await this.checkAndUpdate(); } - checkAndUpdate() { + async checkAndUpdate() { // Should always check the bridge to see if the component should // update itself (re-render) const bUpdateSelf = this.angularPConnect.shouldComponentUpdate(this); // ONLY call updateSelf when the component should update if (bUpdateSelf) { - this.updateSelf(); + await this.updateSelf(); } } // updateSelf - updateSelf(): void { + async updateSelf(): Promise { // starting very simple... // moved this from ngOnInit() and call this from there instead... @@ -134,7 +146,8 @@ export class AutoCompleteComponent implements OnInit { let datasource = this.configProps$['datasource']; let columns = this.configProps$['columns']; this.hideLabel = this.configProps$['hideLabel']; - const { deferDatasource, datasourceMetadata } = this.configProps$; + //const { deferDatasource, datasourceMetadata } = this.configProps$; + const { deferDatasource, datasourceMetadata } = this.pConn$.getConfigProps(); this.helperText = this.configProps$['helperText']; this.parameters = this.configProps$?.parameters; const context = this.pConn$.getContextName(); @@ -200,21 +213,8 @@ export class AutoCompleteComponent implements OnInit { } if (!displayMode && this.listType !== 'associated') { - const workListData = this.PCore$.getDataApiUtils().getData(datasource, {}); - - workListData.then((workListJSON: Object) => { - const optionsData: Array = []; - const results = workListJSON['data'].data; - const displayColumn = this.getDisplayFieldsMetaData(this.columns); - results?.forEach((element) => { - const obj = { - key: element.pyGUID || element[displayColumn.primary], - value: element[displayColumn.primary]?.toString() - }; - optionsData.push(obj); - }); - this.options$ = optionsData; - }); + const results = await this.dataPageService.getDataPageData(datasource, this.parameters, context); + this.fillOptions(results); } // trigger display of error message with field control @@ -228,6 +228,19 @@ export class AutoCompleteComponent implements OnInit { } } + fillOptions(results: any) { + const optionsData: Array = []; + const displayColumn = this.getDisplayFieldsMetaData(this.columns); + results?.forEach((element) => { + const obj = { + key: element[displayColumn.key] || element.pyGUID, + value: element[displayColumn.primary]?.toString() + }; + optionsData.push(obj); + }); + this.options$ = optionsData; + } + flattenParameters(params = {}) { const flatParams = {}; Object.keys(params).forEach((key) => { diff --git a/projects/angular-sdk-library/src/lib/_components/field/phone/phone.component.html b/projects/angular-sdk-library/src/lib/_components/field/phone/phone.component.html index 722bcb58..6e777402 100644 --- a/projects/angular-sdk-library/src/lib/_components/field/phone/phone.component.html +++ b/projects/angular-sdk-library/src/lib/_components/field/phone/phone.component.html @@ -3,22 +3,23 @@
-
-
- - - - {{ getErrorMessage() }} - -
+
+ + + + + {{ label$ }} + {{ getErrorMessage() }} + +
diff --git a/projects/angular-sdk-library/src/lib/_components/field/phone/phone.component.scss b/projects/angular-sdk-library/src/lib/_components/field/phone/phone.component.scss index 40d8f616..5aa69dea 100644 --- a/projects/angular-sdk-library/src/lib/_components/field/phone/phone.component.scss +++ b/projects/angular-sdk-library/src/lib/_components/field/phone/phone.component.scss @@ -24,58 +24,58 @@ font-size: 0.7rem; } -::ng-deep .iti { - display: block !important; - margin-bottom: 20px; +// ::ng-deep .iti { +// display: block !important; +// margin-bottom: 20px; - .dropdown-menu.country-dropdown { - border-top-left-radius: 0px; - border-top-right-radius: 0px; - border-color: #c7cace; - margin-top: -1px; - } +// .dropdown-menu.country-dropdown { +// border-top-left-radius: 0px; +// border-top-right-radius: 0px; +// border-color: #c7cace; +// margin-top: -1px; +// } - .iti__country-list { - box-shadow: none; - font-size: 14px; - margin-left: 0; - width: 244px; - max-height: 170px; - } +// .iti__country-list { +// box-shadow: none; +// font-size: 14px; +// margin-left: 0; +// width: 244px; +// max-height: 170px; +// } - .search-container input { - font-size: 14px; - border-color: #c7cace; - border-radius: 0; - padding: 5px 10px; - } +// .search-container input { +// font-size: 14px; +// border-color: #c7cace; +// border-radius: 0; +// padding: 5px 10px; +// } - .search-container input:focus { - outline: none; - } -} +// .search-container input:focus { +// outline: none; +// } +// } -::ng-deep .iti__flag-container.open + input { - border-bottom-left-radius: 0px; - border-bottom-right-radius: 0px; -} +// ::ng-deep .iti__flag-container.open + input { +// border-bottom-left-radius: 0px; +// border-bottom-right-radius: 0px; +// } -::ng-deep ngx-mat-intl-tel-input { - .country-selector { - opacity: 1 !important; - bottom: 8px !important; - } +// ::ng-deep ngx-mat-intl-tel-input { +// .country-selector { +// opacity: 1 !important; +// bottom: 8px !important; +// } - input:not(.country-search) { - bottom: 3px; - left: 10px; - } +// input:not(.country-search) { +// bottom: 3px; +// left: 10px; +// } - .country-list-button { - font-size: 0.8rem !important; - } +// .country-list-button { +// font-size: 0.8rem !important; +// } - .mat-menu-content:not(:empty) { - max-height: 250px; - } -} +// .mat-menu-content:not(:empty) { +// max-height: 250px; +// } +// }