ACS-8217: Remove internal Boolean pipe (#10101)

This commit is contained in:
Denys Vuika
2024-08-20 11:28:38 -04:00
committed by GitHub
parent 00304c1931
commit 291d5c826b
7 changed files with 143 additions and 187 deletions

View File

@@ -1,26 +0,0 @@
---
Title: Boolean pipe
Added: v6.4.0
Status: Active
Last reviewed: 2023-10-12
---
# [Boolean pipe](../../../lib/core/src/lib/pipes/boolean.pipe.ts "Defined in boolean.pipe.ts")
Converts the received values to one of the possible strings: 'true', 'false' or ""(empty string).
## Basic Usage
<!-- {% raw %} -->
```HTML
<div>
Is available: {{ isAvailable | adfBoolean }}
</div>
```
<!-- {% endraw %} -->
## Details
This pipe is prepared for any input values. The value `'true'` will be returned if true (boolean) or 'true' (exact string) appears on the input. The situation is identical for the value `'false'` - it will be returned in the case of false(boolean) or 'false'. In other cases, we can expect an `empty string('')`.

View File

@@ -23,17 +23,12 @@ import { ObjectDataColumn } from '../../data/object-datacolumn.model';
describe('BooleanCellComponent', () => { describe('BooleanCellComponent', () => {
let component: BooleanCellComponent; let component: BooleanCellComponent;
let fixture: ComponentFixture<BooleanCellComponent>; let fixture: ComponentFixture<BooleanCellComponent>;
const getBooleanCell = () => fixture.debugElement.nativeElement.querySelector('span'); let valueEl: HTMLElement;
const renderAndCheckResult = (value: any, expectedOccurrence: boolean, expectedLabel?: string) => {
const renderAndGetResult = async (value: any) => {
component.value$.next(value); component.value$.next(value);
fixture.detectChanges(); fixture.detectChanges();
return valueEl.textContent.trim();
const booleanCell = getBooleanCell();
expectedOccurrence ? expect(booleanCell).toBeTruthy() : expect(booleanCell).toBeFalsy();
if (expectedLabel) {
expect(booleanCell.textContent.trim()).toBe(expectedLabel);
}
}; };
beforeEach(() => { beforeEach(() => {
@@ -42,6 +37,7 @@ describe('BooleanCellComponent', () => {
}); });
fixture = TestBed.createComponent(BooleanCellComponent); fixture = TestBed.createComponent(BooleanCellComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
valueEl = fixture.nativeElement.querySelector('span');
}); });
describe('Initialization', () => { describe('Initialization', () => {
@@ -60,7 +56,7 @@ describe('BooleanCellComponent', () => {
nextSpy = spyOn(component.value$, 'next'); nextSpy = spyOn(component.value$, 'next');
}); });
it('should setup inital value', () => { it('should setup initial value', () => {
component.column = dataTableAdapter.getColumns()[0]; component.column = dataTableAdapter.getColumns()[0];
component.row = dataTableAdapter.getRows()[0]; component.row = dataTableAdapter.getRows()[0];
component.data = dataTableAdapter; component.data = dataTableAdapter;
@@ -70,7 +66,7 @@ describe('BooleanCellComponent', () => {
expect(nextSpy).toHaveBeenCalledOnceWith(rowData.value); expect(nextSpy).toHaveBeenCalledOnceWith(rowData.value);
}); });
it('should NOT setup inital value', () => { it('should NOT setup initial value', () => {
fixture.detectChanges(); fixture.detectChanges();
expect(nextSpy).not.toHaveBeenCalled(); expect(nextSpy).not.toHaveBeenCalled();
@@ -79,52 +75,63 @@ describe('BooleanCellComponent', () => {
describe('UI', () => { describe('UI', () => {
describe('should render "true" inside cell when', () => { describe('should render "true" inside cell when', () => {
it('boolean value is true', () => { it('boolean value is true', async () => {
renderAndCheckResult(true, true, 'true'); const result = await renderAndGetResult(true);
expect(result).toBe('true');
}); });
it('exact string is provided', () => { it('exact string is provided', async () => {
renderAndCheckResult('true', true, 'true'); const result = await renderAndGetResult('true');
expect(result).toBe('true');
}); });
}); });
describe('should render "false" inside cell when', () => { describe('should render "false" inside cell when', () => {
it('boolean value is false', () => { it('boolean value is false', async () => {
renderAndCheckResult(false, true, 'false'); const result = await renderAndGetResult(false);
expect(result).toBe('false');
}); });
it('exact string is provided', () => { it('exact string is provided', async () => {
renderAndCheckResult('false', true, 'false'); const result = await renderAndGetResult('false');
expect(result).toBe('false');
}); });
}); });
describe('should NOT render value inside cell in case of', () => { describe('should NOT render value inside cell in case of', () => {
it('invalid string', () => { it('invalid string', async () => {
renderAndCheckResult('tru', false); const result = await renderAndGetResult('tru');
expect(result).toBe('');
}); });
it('number', () => { it('number', async () => {
renderAndCheckResult(0, false); const result = await renderAndGetResult(0);
expect(result).toBe('');
}); });
it('object', () => { it('object', async () => {
renderAndCheckResult({}, false); const result = await renderAndGetResult({});
expect(result).toBe('');
}); });
it('null', () => { it('null', async () => {
renderAndCheckResult(null, false); const result = await renderAndGetResult(null);
expect(result).toBe('');
}); });
it('undefined', () => { it('undefined', async () => {
renderAndCheckResult(undefined, false); const result = await renderAndGetResult(undefined);
expect(result).toBe('');
}); });
it('empty string', () => { it('empty string', async () => {
renderAndCheckResult('', false); const result = await renderAndGetResult('');
expect(result).toBe('');
}); });
it('NaN', () => { it('NaN', async () => {
renderAndCheckResult(NaN, false); const result = await renderAndGetResult(NaN);
expect(result).toBe('');
}); });
}); });
}); });

View File

@@ -18,26 +18,39 @@
import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation } from '@angular/core'; import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation } from '@angular/core';
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component'; import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { BooleanPipe } from '../../../pipes/boolean.pipe'; import { takeUntil } from 'rxjs/operators';
@Component({ @Component({
standalone: true, standalone: true,
imports: [CommonModule, BooleanPipe], imports: [CommonModule],
selector: 'adf-boolean-cell', selector: 'adf-boolean-cell',
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
template: ` template: `
<ng-container *ngIf="value$ | async | adfBoolean as value">
<span [title]="tooltip"> <span [title]="tooltip">
{{ value }} {{ boolValue }}
</span> </span>
</ng-container>
`, `,
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
host: { class: 'adf-datatable-content-cell' } host: { class: 'adf-datatable-content-cell' }
}) })
export class BooleanCellComponent extends DataTableCellComponent implements OnInit { export class BooleanCellComponent extends DataTableCellComponent implements OnInit {
boolValue = '';
ngOnInit() { ngOnInit() {
super.ngOnInit(); super.ngOnInit();
this.value$.pipe(takeUntil(this.onDestroy$)).subscribe((value) => {
this.boolValue = this.transformBoolean(value);
});
}
private transformBoolean(value: any): string {
if (value === true || value === 'true') {
return 'true';
}
if (value === false || value === 'false') {
return 'false';
}
return '';
} }
} }

View File

@@ -1,85 +0,0 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { BooleanPipe } from './boolean.pipe';
describe('BooleanPipe', () => {
let pipe: BooleanPipe;
beforeEach(() => {
pipe = new BooleanPipe();
});
describe('should return "true" when', () => {
it('boolean value is true', () => {
expect(pipe.transform(true)).toBe('true');
});
it('exact string is provided', () => {
expect(pipe.transform('true')).toBe('true');
});
});
describe('should return "false" when', () => {
it('boolean value is false', () => {
expect(pipe.transform(false)).toBe('false');
});
it('exact string is provided', () => {
expect(pipe.transform('false')).toBe('false');
});
});
describe('should return empty string in case of', () => {
it('invalid string', () => {
expect(pipe.transform('fal')).toBe('');
expect(pipe.transform('truee')).toBe('');
expect(pipe.transform('0')).toBe('');
expect(pipe.transform('1')).toBe('');
expect(pipe.transform('122')).toBe('');
expect(pipe.transform('TRUE')).toBe('');
expect(pipe.transform('FALSE')).toBe('');
expect(pipe.transform(' false')).toBe('');
expect(pipe.transform(' true ')).toBe('');
});
it('falsy value (excluding false)', () => {
expect(pipe.transform(null)).toBe('');
expect(pipe.transform(undefined)).toBe('');
expect(pipe.transform(false)).not.toBe('');
expect(pipe.transform(NaN)).toBe('');
expect(pipe.transform(0)).toBe('');
expect(pipe.transform(-0)).toBe('');
expect(pipe.transform(BigInt(0))).toBe('');
expect(pipe.transform('')).toBe('');
});
it('number', () => {
expect(pipe.transform(-20.5)).toBe('');
expect(pipe.transform(-1)).toBe('');
expect(pipe.transform(0)).toBe('');
expect(pipe.transform(1)).toBe('');
expect(pipe.transform(100)).toBe('');
expect(pipe.transform(100.5)).toBe('');
});
it('object', () => {
expect(pipe.transform({})).toBe('');
expect(pipe.transform({ value: 'true'})).toBe('');
});
});
});

View File

@@ -1,35 +0,0 @@
/*!
* @license
* Copyright © 2005-2024 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'adfBoolean',
standalone: true
})
export class BooleanPipe implements PipeTransform {
transform(value: any): string {
if (typeof value === 'boolean') {
return value ? 'true' : 'false';
}
return this.isRecognizedAsBoolean(value) ? value : '';
}
private isRecognizedAsBoolean(value: any): boolean {
return value === 'true' || value === 'false';
}
}

View File

@@ -33,4 +33,3 @@ export * from './moment-datetime.pipe';
export * from './date-time.pipe'; export * from './date-time.pipe';
export * from './filter-string.pipe'; export * from './filter-string.pipe';
export * from './filter-out-every-object-by-prop.pipe'; export * from './filter-out-every-object-by-prop.pipe';
export * from './boolean.pipe';

View File

@@ -16,9 +16,92 @@
*/ */
import { browser, ElementFinder } from 'protractor'; import { browser, ElementFinder } from 'protractor';
import * as path from 'path';
import * as fs from 'fs';
import { BrowserActions } from '../utils/browser-actions'; import { BrowserActions } from '../utils/browser-actions';
const JS_BIND_INPUT = (target) => {
const input = document.createElement('input');
input.type = 'file';
input.style.display = 'none';
input.addEventListener(
'change',
() => {
target.scrollIntoView(true);
const rect = target.getBoundingClientRect();
const x = rect.left + (rect.width >> 1);
const y = rect.top + (rect.height >> 1);
const data = { files: input.files };
['dragenter', 'dragover', 'drop'].forEach((name) => {
const mouseEvent: any = document.createEvent('MouseEvent');
mouseEvent.initMouseEvent(name, !0, !0, window, 0, 0, 0, x, y, !1, !1, !1, !1, 0, null);
mouseEvent.dataTransfer = data;
target.dispatchEvent(mouseEvent);
});
document.body.removeChild(input);
},
false
);
document.body.appendChild(input);
return input;
};
const JS_BIND_INPUT_FOLDER = (target) => {
const input: any = document.createElement('input');
input.type = 'file';
input.style.display = 'none';
input.multiple = true;
input.webkitdirectory = true;
input.addEventListener(
'change',
() => {
target.scrollIntoView(true);
const rect = target.getBoundingClientRect();
const x = rect.left + (rect.width >> 1);
const y = rect.top + (rect.height >> 1);
const data = { files: input.files };
['dragenter', 'dragover', 'drop'].forEach((name) => {
const mouseEvent: any = document.createEvent('MouseEvent');
mouseEvent.initMouseEvent(name, !0, !0, window, 0, 0, 0, x, y, !1, !1, !1, !1, 0, null);
mouseEvent.dataTransfer = data;
target.dispatchEvent(mouseEvent);
});
document.body.removeChild(input);
},
false
);
document.body.appendChild(input);
return input;
};
export class DropActions { export class DropActions {
static async dropFile(dropArea, filePath) {
const absolutePath = path.resolve(path.join(browser.params.testConfig.main.rootPath, filePath));
fs.accessSync(absolutePath, fs.constants.F_OK);
const elem = await dropArea.getWebElement();
const input: any = await browser.executeScript(JS_BIND_INPUT, elem);
return input.sendKeys(absolutePath);
}
static async dropFolder(dropArea, folderPath) {
const absolutePath = path.resolve(path.join(browser.params.testConfig.main.rootPath, folderPath));
fs.accessSync(absolutePath, fs.constants.F_OK);
const elem = await dropArea.getWebElement();
const input: any = await browser.executeScript(JS_BIND_INPUT_FOLDER, elem);
return input.sendKeys(absolutePath);
}
static async dragAndDrop(elementToDrag: ElementFinder, locationToDragTo: ElementFinder, locationOffset = { x: 230, y: 280 }) { static async dragAndDrop(elementToDrag: ElementFinder, locationToDragTo: ElementFinder, locationOffset = { x: 230, y: 280 }) {
await BrowserActions.click(elementToDrag); await BrowserActions.click(elementToDrag);
await browser.actions().mouseDown(elementToDrag).mouseMove(locationToDragTo, locationOffset).mouseUp().perform(); await browser.actions().mouseDown(elementToDrag).mouseMove(locationToDragTo, locationOffset).mouseUp().perform();