Skip to content
This repository has been archived by the owner on Mar 6, 2024. It is now read-only.

Commit

Permalink
Improve the type system around options in widgets
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Bradford <[email protected]>
  • Loading branch information
ryan-bradford committed Apr 9, 2021
1 parent 2a03a17 commit 83abca7
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 65 deletions.
6 changes: 3 additions & 3 deletions cypress/integration/find-cypress-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
DataExporterWidgetObject,
FindableWidget,
} from '@vcd/ui-components';
import { FindCypressWidgetOptions } from '@vcd/ui-components';
import { FindElementOptions } from '@vcd/ui-components';
import Cypress from 'cypress';

type Chainable = Cypress.Chainable;
Expand All @@ -27,11 +27,11 @@ type Chainable = Cypress.Chainable;
*/
export function findCypressWidget<W extends BaseWidgetObject<Chainable>>(
widgetConstructor: FindableWidget<Chainable, W>,
findOptions?: FindCypressWidgetOptions
findOptions?: FindElementOptions<Chainable>
): W {
return new CypressWidgetObjectFinder<Chainable>().find(widgetConstructor, findOptions) as W;
}

export function findDataExporter(options?: FindCypressWidgetOptions): DataExporterWidgetObject<Chainable> {
export function findDataExporter(options?: FindElementOptions<Chainable>): DataExporterWidgetObject<Chainable> {
return findCypressWidget<DataExporterWidgetObject<Chainable>>(DataExporterWidgetObject, options);
}
7 changes: 5 additions & 2 deletions projects/components/CHANGELOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [2.0.0-dev.8]

### Added
- Find widget by data ui attribute.

### Change
- Widget find/action options are now type safe

## [2.0.0-dev.8]

### Added
- `clear` is now a method in a widget object.
- Added functionality to disable an option in `FormSelectComponent`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,6 @@ import { By } from '@angular/platform-browser';
import { BaseWidgetObject, FindableWidget, FindElementOptions } from '../widget-object';
import { AngularWidgetObjectElement, TestElement } from './angular-widget-object-element';

/**
* Adds Angular specific options for finding widgets
*/
export interface FindAngularWidgetOptions extends FindElementOptions {
ancestor?: DebugElement;
}

/**
* Knows how to find and instantiate Angular Widgets objects.
*/
Expand Down Expand Up @@ -49,7 +42,7 @@ export class AngularWidgetObjectFinder<H = unknown> {
*/
public find<W extends BaseWidgetObject<TestElement>>(
widgetConstructor: FindableWidget<TestElement, W>,
findOptions: FindAngularWidgetOptions = {}
findOptions: FindElementOptions<TestElement> = {}
): W {
const { ancestor } = findOptions;

Expand All @@ -60,7 +53,7 @@ export class AngularWidgetObjectFinder<H = unknown> {
if (findOptions?.cssSelector) {
query = query + findOptions.cssSelector;
}
const parentQuery: FindAngularWidgetOptions = {
const parentQuery: FindElementOptions<TestElement> = {
cssSelector: query,
dataUiSelector: findOptions?.dataUiSelector,
text: findOptions?.text,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { ComponentFixture } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { SelectorUtil } from '../selector-util';
import { BaseWidgetObject, FindableWidget, FindElementOptions, WidgetObjectElement } from '../widget-object';
import { AngularWidgetObjectFinder, FindAngularWidgetOptions } from './angular-widget-finder';
import { AngularWidgetObjectFinder } from './angular-widget-finder';

/**
* Angular implementation of the Widget Object's internal HTML Element wrapper
Expand All @@ -21,7 +21,7 @@ export class AngularWidgetObjectElement implements WidgetObjectElement<TestEleme
/**
* @inheritdoc
*/
get(selector: string | FindElementOptions): AngularWidgetObjectElement {
get(selector: string | FindElementOptions<TestElement>): AngularWidgetObjectElement {
const cssSelector = SelectorUtil.extractSelector(selector);
const elements = this.testElement.elements;
let matches = [].concat(...elements.map((element) => element.queryAll(By.css(cssSelector))));
Expand Down Expand Up @@ -118,7 +118,7 @@ export class AngularWidgetObjectElement implements WidgetObjectElement<TestEleme
*/
findWidget<W extends BaseWidgetObject<TestElement>>(
widgetCtor: FindableWidget<TestElement, W>,
findOptions: FindAngularWidgetOptions
findOptions: FindElementOptions<TestElement>
): W {
return new AngularWidgetObjectFinder(this.testElement.fixture).find(widgetCtor, {
...findOptions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,12 @@
*/

import { IdGenerator } from '../../../id-generator/id-generator';
import { BaseWidgetObject, FindableWidget, FindElementOptions } from '../widget-object';
import { BaseWidgetObject, CypressWidgetActionOptions, FindableWidget, FindElementOptions } from '../widget-object';
import { CypressWidgetObjectElement } from './cypress-widget-object-element';

declare const cy;
const idGenerator = new IdGenerator('cy-id');

export interface FindCypressWidgetOptions extends FindElementOptions {
ancestor?: string;
options?: { timeout: number };
}

/**
* Knows how to find and construct Cypress widget objects within the DOM.
*
Expand All @@ -34,19 +29,20 @@ export class CypressWidgetObjectFinder<T> {
*/
public find<W extends BaseWidgetObject<T>>(
widgetConstructor: FindableWidget<T, W>,
findOptions?: FindCypressWidgetOptions
findOptions?: FindElementOptions<T>
): W {
const id = idGenerator.generate();

const options: CypressWidgetActionOptions = findOptions?.options;
const ancestor = findOptions?.ancestor
? cy.get(findOptions?.ancestor, { timeout: findOptions?.options?.timeout })
: cy.get('body', { timeout: findOptions?.options?.timeout });
? cy.get(findOptions?.ancestor, { timeout: options?.timeout })
: cy.get('body', { timeout: options?.timeout });
const parentWidget = new CypressWidgetObjectElement(ancestor, false, undefined);
let query = widgetConstructor.tagName;
if (findOptions?.cssSelector) {
query = query + findOptions.cssSelector;
}
const parentQuery: FindCypressWidgetOptions = {
const parentQuery: FindElementOptions<T> = {
cssSelector: query,
dataUiSelector: findOptions?.dataUiSelector,
text: findOptions?.text,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ describe('CypressWidgetObjectElement', () => {
it('clears the given input', () => {
const clearSpy = spyOn(cy, 'clear').and.callThrough();
const widget = new CypressWidgetObjectElement(cy, true, '1');
widget.clear({ a: 'test' });
expect(clearSpy).toHaveBeenCalledWith({ a: 'test' });
widget.clear({ timeout: 1 });
expect(clearSpy).toHaveBeenCalledWith({ timeout: 1 });
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
import { SelectorUtil } from '../selector-util';
import {
BaseWidgetObject,
CypressWidgetActionOptions,
ElementActions,
FindableWidget,
FindElementOptions,
WidgetActionOptions,
WidgetObjectElement,
} from '../widget-object';
import { CypressWidgetObjectFinder, FindCypressWidgetOptions } from './cypress-widget-finder';
import { CypressWidgetObjectFinder } from './cypress-widget-finder';

declare const cy;

Expand All @@ -24,13 +26,13 @@ declare const cy;
* [this PR](https://github.com/vmware/vmware-cloud-director-ui-components/pull/248)
* we could not load the Cypress types in our library.
*/
export class CypressWidgetObjectElement<T extends ElementActions> implements WidgetObjectElement<T> {
export class CypressWidgetObjectElement<T extends ElementActions<T>> implements WidgetObjectElement<T> {
constructor(private chainable: T, private isRoot: boolean, private alias: string) {}

/**
* @inheritdoc
*/
get(selector: string | FindElementOptions): CypressWidgetObjectElement<T> {
get(selector: string | FindElementOptions<T>): CypressWidgetObjectElement<T> {
const root = this.getBase();
const cssSelector = SelectorUtil.extractSelector(selector);
let chainable: any;
Expand All @@ -50,7 +52,7 @@ export class CypressWidgetObjectElement<T extends ElementActions> implements Wid
/**
* @inheritdoc
*/
parents(selector: string | FindElementOptions): CypressWidgetObjectElement<T> {
parents(selector: string | FindElementOptions<T>): CypressWidgetObjectElement<T> {
const root = this.getBase();
if (typeof selector === 'string') {
return new CypressWidgetObjectElement(root.parents(selector), false, this.alias);
Expand All @@ -72,50 +74,53 @@ export class CypressWidgetObjectElement<T extends ElementActions> implements Wid
/**
* @inheritdoc
*/
click(options?: unknown): void {
click(options?: WidgetActionOptions<T>): void {
this.chainable.click(options);
}

/**
* @inheritdoc
*/
type(value: string, options: unknown): void {
type(value: string, options: WidgetActionOptions<T>): void {
this.chainable.type(value, options);
}

/**
* @inheritdoc
*/
select(text: string, options: unknown): void {
select(text: string, options: WidgetActionOptions<T>): void {
this.chainable.select(text, options);
}

/**
* @inheritdoc
*/
check(options?: unknown): void {
check(options?: WidgetActionOptions<T>): void {
this.chainable.check(options);
}

/**
* @inheritdoc
*/
uncheck(options?: unknown): void {
uncheck(options?: WidgetActionOptions<T>): void {
this.chainable.uncheck(options);
}

/**
* @inheritdoc
*/
clear(options?: unknown): void {
clear(options?: WidgetActionOptions<T>): void {
this.chainable.clear(options);
}

/**
* @inheritdoc
*/
findWidget<W extends BaseWidgetObject<T>>(widget: FindableWidget<T, W>, findOptions: FindCypressWidgetOptions): W {
return new CypressWidgetObjectFinder<T>().find(widget, { ancestor: '@' + this.alias, ...findOptions });
findWidget<W extends BaseWidgetObject<T>>(widget: FindableWidget<T, W>, findOptions: FindElementOptions<T>): W {
return new CypressWidgetObjectFinder<T>().find(widget, {
ancestor: '@' + this.alias,
...findOptions,
} as FindElementOptions<T>);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions projects/components/src/utils/test/widget-object/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

export { BaseWidgetObject, FindableWidget } from './widget-object';
export { CypressWidgetObjectFinder, FindCypressWidgetOptions } from './cypress/cypress-widget-finder';
export { CypressWidgetObjectFinder } from './cypress/cypress-widget-finder';
export { AngularWidgetObjectFinder } from './angular/angular-widget-finder';
export { TestElement } from './angular/angular-widget-object-element';
export { FindElementOptions } from './widget-object';
export { FindElementOptions, WidgetActionOptions } from './widget-object';
Loading

0 comments on commit 83abca7

Please sign in to comment.