Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Backstage Interactors #187

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/backstage-ui/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.bigtest
.cache
dist
node_modules
*.tgz
storybook-static/
Empty file.
14 changes: 14 additions & 0 deletions packages/backstage-ui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# @interactors/backstage

[![npm](https://img.shields.io/npm/v/@interactors/backstage.svg)](https://www.npmjs.com/package/@interactors/backstage)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Created by Frontside](https://img.shields.io/badge/created%20by-frontside-26abe8.svg)](https://frontside.com)
[![Chat on Discord](https://img.shields.io/discord/700803887132704931?Label=Discord)](https://discord.gg/mv4uxxcAKd)

[Interactors][] are Page Objects for component libraries and design systems.
This package contains interactors for [Backstage UI][]. Learn more about using
Backstage Interactors at
[https://frontside.com/interactors/docs/existing-interactors#backstage](https://frontside.com/interactors/docs/existing-interactors#backstage)

[interactors]: https://frontside.com/interactors
[backstage ui]: https://backstage.io/storybook/
10 changes: 10 additions & 0 deletions packages/backstage-ui/bigtest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"port": 28000,
"launch": ["default"],
"app": {
"command": "yarn start --port 28001",
"url": "http://localhost:28001"
},
"testFiles": ["test/**/*.test.{tsx,js}"],
"tsconfig": "./tsconfig.json"
}
57 changes: 57 additions & 0 deletions packages/backstage-ui/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"name": "@interactors/backstage-ui",
"version": "0.8.9",
"description": "BigTest interactors for backstage core components.",
"main": "dist/cjs/index.js",
"browser": "dist/esm/index.js",
"types": "dist/index.d.ts",
"files": [
"dist/**/*",
"src/**/*",
"README.md"
],
"scripts": {
"lint": "eslint src test",
"test": "bigtest ci",
"build:cjs": "tsc --outdir dist/cjs --module commonjs --project tsconfig.build.json",
"build:esm": "tsc --outdir dist/esm --module es2015 --project tsconfig.build.json",
"prepack": "tsc --build tsconfig.build.json && run-p build:*",
"docs": "rm -rf docs && yarn typedoc --options typedoc.json",
"docs:netlify": "yarn prepack && yarn docs",
"docs:preview": "yarn parcel docs/api/backstage/index.html",
"start": "parcel serve test/harness.html"
},
"repository": {
"type": "git",
"url": "git+https://github.com/thefrontside/interactors.git"
},
"keywords": [
"material-ui",
"interactors"
],
"author": "Frontside Engineering <engineering@frontside.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/thefrontside/interactors/issues"
},
"homepage": "https://frontside.com/interactors",
"devDependencies": {
"@date-io/date-fns": "^1.3.13",
"@testing-library/react": "^12.0.0",
"@types/react": "^17.0.19",
"bigtest": "^0.16.0",
"date-fns": "^2.23.0",
"npm-run-all": "^4.1.5",
"parcel": "^2.0.0-beta.2",
"parcel-bundler": "^1.12.5",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"tslib": "^2.3.1",
"typedoc": "^0.22.7",
"typescript": "~4.4.4",
"webpack": "^5.53.0"
},
"dependencies": {
"@interactors/material-ui": "1.0.0-rc1.2"
}
}
12 changes: 12 additions & 0 deletions packages/backstage-ui/src/harness.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
<title>Backstage UI Test Harness</title>
</head>
<body>
</body>
</html>
82 changes: 82 additions & 0 deletions packages/backstage-ui/src/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { Interactor } from "@interactors/html";

type HTMLTypes<T> = T extends `HTML${infer C}Element` ? C : never;

type HTMLElementTypes = HTMLTypes<keyof typeof window>;

export function isHTMLElement<T extends HTMLElementTypes = "">(
element: unknown | null | undefined,
type: T = "" as T
): element is InstanceType<typeof window[`HTML${T}Element`]> {
if(element) {
let { defaultView } = (element as Element).ownerDocument;
let Constructor = (defaultView as unknown as Record<string, unknown>)?.[`HTML${type}Element`];
return typeof Constructor == "function" && element instanceof Constructor;
} else {
return false;
}
}
export const delay = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));

export function isDefined<T>(value: T | null | undefined): value is T {
return value !== null && value !== undefined;
}

export function isDisabled<T extends Element>(element: T): boolean;
export function isDisabled<T extends Element>(element?: T | null): boolean | undefined;
export function isDisabled<T extends Element>(element?: T | null): boolean | undefined {
if (isHTMLElement(element, "Button")) return element.disabled;
return element ? element.getAttribute("aria-disabled") == "true" : undefined;
}

export function getInputLabel(
input: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
): HTMLLabelElement | undefined {
return (
input.labels?.[0] ??
input.previousElementSibling
?.getAttribute("aria-labelledby")
?.split(" ")
.map((labelId) => input.ownerDocument.getElementById(labelId))
.map((element) => (isHTMLElement(element, "Label") ? element : null))
.find(isDefined) ??
[input.parentElement?.previousElementSibling]
.map((element) => (isHTMLElement(element, "Label") ? element : null))
.find(isDefined)
);
}

export async function applyGetter<E extends Element, I, R>(
interactor: Interactor<E, I>,
getter: (element: E) => R
): Promise<R> {
let value: unknown;

await interactor.perform((element) => (value = getter(element)));

return value as R;
}

// NOTE: Copy-paste from https://github.com/thefrontside/bigtest/blob/v0/packages/interactor/src/fill-in.ts
export function setValue(element: HTMLInputElement, value: string): void {
let property = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(element), "value");
if (property && property.set) {
property.set.call(element, value);
} else {
// if the value property on the element protoype is not present
// then there are worse problems. But this is very typesafe!
element.value = value;
}
}

export function dispatchChange(element: HTMLElement): boolean {
let Event = element.ownerDocument.defaultView?.Event || window.Event;
return element.dispatchEvent(new Event("change", { bubbles: true, cancelable: false }));
}

export function dispatchMouseDown(element: HTMLElement, options: MouseEventInit = {}): boolean {
let MouseEvent = element.ownerDocument.defaultView?.MouseEvent || window.MouseEvent;
return element.dispatchEvent(
new MouseEvent("mousedown", Object.assign({ bubbles: true, cancelable: true }, options))
);
}
42 changes: 42 additions & 0 deletions packages/backstage-ui/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
export * from '@interactors/core';
export {
Button as HTMLButton,
CheckBox as HTMLCheckbox,
FormField,
HTML,
Heading,
Link as HTMLLink,
MultiSelect as HTMLMultiSelect,
Page,
RadioButton as HTMLRadio,
Select as HTMLSelect,
TextField as HTMLTextField,
} from "@interactors/html";

export * from "./types";

// export * from "./date-field";
// export * from "./time-field";
// export * from "./datetime-field";

// export * from "./checkbox";
// export * from "./calendar";
// export * from "./accordion";
// export * from "./menu";
// export * from "./switch";
// export * from "./bottom-navigation";
// export * from "./link";
// export * from "./list";
// export * from "./menu";
// export * from "./tabs";
// export * from "./select";
// export * from "./native-select";
// export * from "./popover";
// export * from "./text-field";
// export * from "./button";
// export * from "./snackbar";
// export * from "./form-control";
// export * from "./dialog";
// export * from "./fab";
// export * from "./slider";
// export * from "./radio";
22 changes: 22 additions & 0 deletions packages/backstage-ui/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { InteractorConstructor } from "@interactors/html";

/**
* Helper functions from `@date-io/*` utils
*/
export interface DatePickerUtils {
parse(value: string, format: string): Date | null;
getMonth(value: Date | null): number;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type GetElementType<I extends InteractorConstructor<any, any, any, any>> = I extends InteractorConstructor<
infer E,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
any
>
? E
: unknown;
15 changes: 15 additions & 0 deletions packages/backstage-ui/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"extends": "../../tsconfig-base.json",
"compilerOptions": {
"outDir": "dist/cjs",
"rootDir": "./src",
"declarationDir": "dist"
},
"include": [
"src/**/*.ts",
"types"
],
"references": [
{ "path": "../html/tsconfig.build.json" }
]
}
7 changes: 7 additions & 0 deletions packages/backstage-ui/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "@frontside/tsconfig",
"compilerOptions": {
"outDir": "dist",
"jsx": "react-jsx"
}
}
9 changes: 9 additions & 0 deletions packages/backstage-ui/typedoc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"out": "docs/api/backstage",
"name": "@interactors/backstage",
"entryPoints": "src/index.ts",
"readme": "README.md",
"includeVersion": true,
"excludePrivate": true,
"readme": "none"
}