@homebound/beam 3.0.0-alpha.2 → 3.0.0-alpha.3

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 +0,0 @@
1
- {"version":3,"sources":["../../src/utils/rtlUtils.tsx"],"sourcesContent":["import {\n blur as _blur,\n change as _change,\n click as _click,\n clickAndWait as _clickAndWait,\n focus as _focus,\n input as _input,\n type as _type,\n typeAndWait as _typeAndWait,\n wait as _wait,\n allowAndWaitForAsyncBehavior,\n RenderResult,\n} from \"@homebound/rtl-utils\";\nimport { prettyDOM } from \"@testing-library/react\";\nimport { fail } from \"src/utils/index\";\n\nexport {\n _blur as blur,\n _change as change,\n _click as click,\n _clickAndWait as clickAndWait,\n _focus as focus,\n _input as input,\n _type as type,\n _typeAndWait as typeAndWait,\n _wait as wait,\n};\n\n// This file is a collection of helpers for interacting with Beam components in tests.\n// We keep it separate from the `src/tests/rtl.tsx` file, which is the Beam tests\n// themselves use, which technically does re-export these `rtlUtils.tsx` helpers, but\n// also includes other helpers that are specific to Beam's test suite.\n//\n// (In particular, we cannot include/export any Beam components, i.e. BeamProvider, from\n// this file, because it ends up as a separate bundle in the `package.json` file, which\n// will be treated as separate components/providers than the primary bundle.)\n\nexport function cell(r: RenderResult, row: number, column: number): HTMLElement {\n return cellOf(r, \"gridTable\", row, column);\n}\n\nexport function cellOf(r: RenderResult, tableTestId: string, rowNum: number, column: number): HTMLElement {\n return row(r, rowNum, tableTestId).childNodes[column] as HTMLElement;\n}\n\nexport function cellAnd(r: RenderResult, row: number, column: number, testId: string): HTMLElement {\n return (\n cell(r, row, column).querySelector(`[data-testid=\"${testId}\"]`) ||\n fail(`Element not found ${prettyDOM(cell(r, row, column))}`)\n );\n}\n\nexport function row(r: RenderResult, row: number, tableTestId: string = \"gridTable\"): HTMLElement {\n const dataRows = Array.from(r.getByTestId(tableTestId).querySelectorAll(\"[data-gridrow]\"));\n return dataRows[row] as HTMLElement;\n}\n\nexport function rowAnd(r: RenderResult, rowNum: number, testId: string): HTMLElement {\n const e = row(r, rowNum);\n return e.querySelector(`[data-testid=\"${testId}\"]`) || fail(`Element not found ${prettyDOM(e)}`);\n}\n\n/** Intended to be used to generate a human-readable text\n * representation of a GridTable using the markdown table syntax.\n * * Example Use: expect(tableSnapshot(r)).toMatchInlineSnapshot(`\n \"\n | Name | Value |\n | ------------------------ | ----- |\n | Row 1 | 200 |\n | Row 2 with a longer name | 300 |\n | Row 3 | 1000 |\n \"\n `);\n * */\nexport function tableSnapshot(r: RenderResult, columnNames: string[] = []): string {\n const tableEl = r.getByTestId(\"gridTable\");\n const dataRows = Array.from(tableEl.querySelectorAll(\"[data-gridrow]\"));\n const hasExpandableHeader = !!tableEl.querySelector(`[data-testid=\"expandableColumn\"]`);\n\n let tableDataAsStrings = dataRows.map((row) => {\n return Array.from(row.childNodes).map(getTextFromTableCellNode);\n });\n\n // If the user wants a subset of columns, look for column names\n if (columnNames.length > 0) {\n const headerCells = tableDataAsStrings[0];\n if (headerCells) {\n const columnIndices = columnNames.map((name) => {\n const i = headerCells.indexOf(name);\n if (i === -1) throw new Error(`Could not find header '${name}' in ${headerCells.join(\", \")}`);\n return i;\n });\n tableDataAsStrings = tableDataAsStrings.map((row) => columnIndices.map((index) => row[index]));\n }\n }\n\n return toMarkupTableString(tableDataAsStrings, hasExpandableHeader);\n}\n\nfunction toMarkupTableString(tableRows: (string | null)[][], hasExpandableHeader: boolean): string {\n // Find the largest width of each column to set a consistent width for each row\n const columnWidths = tableRows.reduce((acc, row) => {\n row.forEach((cell, columnIndex) => {\n const cellWidth = cell?.length ?? 0;\n const currentMaxWidth = acc.get(columnIndex) ?? 0;\n if (cellWidth > currentMaxWidth || !currentMaxWidth) acc.set(columnIndex, cellWidth);\n });\n\n return acc;\n }, new Map<number, number>());\n\n const wrapTableRowEnds = (str: string) => `| ${str} |`;\n\n const rowsWithPaddingAndDividers = tableRows.map((tableCells) => {\n const formattedRow = tableCells\n .map((cell, columnIndex) => {\n const cellWidth = columnWidths.get(columnIndex) ?? 0;\n return cell?.padEnd(cellWidth, \" \") || \"\";\n })\n .join(\" | \");\n return wrapTableRowEnds(formattedRow);\n });\n\n const headerDivider = Array.from(columnWidths.values())\n .map((width) => \"-\".repeat(width) ?? \"\")\n .join(\" | \");\n\n const headerDividerRowNumber = hasExpandableHeader ? 2 : 1;\n rowsWithPaddingAndDividers.splice(headerDividerRowNumber, 0, wrapTableRowEnds(headerDivider));\n\n // Pad a newline on top and bottom for cleaner diffs\n return `\\n${rowsWithPaddingAndDividers.join(\"\\n\")}\\n`;\n}\n\n/** Prefer showing a `value` from a mocked input vs. the combined text content from an inputs markup */\nfunction getTextFromTableCellNode(node: ChildNode) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const element = node as HTMLElement;\n\n const maybeInput = element.getElementsByTagName(\"input\")[0];\n if (maybeInput) return maybeInput.value;\n\n const maybeTextarea = element.getElementsByTagName(\"textarea\")[0];\n if (maybeTextarea) return maybeTextarea.value;\n\n const maybeSelect = element.getElementsByTagName(\"select\")[0];\n if (maybeSelect) return maybeSelect.value;\n }\n\n return node.textContent;\n}\n\n/**\n * Selects an option from the Beam SelectField, MultiSelectField, and TreeSelectField components.\n *\n * For select fields that support multiple selections, subsequent calls to this function will toggle the selection state of an option.\n *\n * @param value The value or label of the option.\n * */\nexport function select(select: HTMLElement, value: string | string[]) {\n assertListBoxInput(select);\n ensureListBoxOpen(select);\n const optionValues = Array.isArray(value) ? value : [value];\n optionValues.forEach((optionValue) => selectOption(select, optionValue));\n}\n\nexport async function selectAndWait(select: HTMLElement, value: string | string[]): Promise<void> {\n // To work with React 18, we need to execute these as separate steps, otherwise\n // the `ensureListBoxOpen` async render won't flush, and the `selectOption` will fail.\n await allowAndWaitForAsyncBehavior(() => ensureListBoxOpen(select));\n return allowAndWaitForAsyncBehavior(() => {\n const optionValues = Array.isArray(value) ? value : [value];\n optionValues.forEach((optionValue) => selectOption(select, optionValue));\n });\n}\n\nfunction ensureListBoxOpen(select: HTMLElement): void {\n const expanded = select.getAttribute(\"aria-expanded\") === \"true\";\n if (!expanded) {\n _click(select);\n }\n}\n\nfunction selectOption(select: HTMLElement, optionValue: string) {\n const listbox = findListBox(select);\n const options: NodeListOf<HTMLElement> = listbox.querySelectorAll(\"[role=option]\");\n // Allow searching for options by their data-key (value) or textContent (label)\n const optionToSelect = Array.from(options).find(\n (o: HTMLElement) => o.dataset.key === optionValue || o.dataset.label === optionValue,\n );\n if (!optionToSelect) {\n throw new Error(`Could not find option with value or text content of ${optionValue}`);\n }\n if (optionToSelect.getAttribute(\"aria-disabled\")) {\n throw new Error(`Cannot select disabled option ${optionValue}`);\n }\n _click(optionToSelect);\n}\n\nexport function getSelected(select: HTMLElement): string[] | string | undefined {\n if (isSelectElement(select)) {\n throw new Error(\"Beam getSelected helper does not support <select> elements\");\n }\n\n if (!isInputOrTextAreaElement(select) && select.dataset.readonly === \"true\") {\n // For read-only fields that render as a 'div'\n return select.textContent ?? undefined;\n }\n\n ensureListBoxOpen(select);\n\n const listbox = findListBox(select);\n const options: NodeListOf<HTMLElement> = listbox.querySelectorAll(\"[role=option]\");\n\n const selections: string[] = Array.from(options)\n .filter((o: HTMLElement) => o.getAttribute(\"aria-selected\") === \"true\")\n .map((o: HTMLElement) => o.dataset.label ?? o.dataset.key ?? \"\")\n // Filter out empty strings\n .filter((o) => !!o);\n\n return selections.length > 0 ? (selections.length > 1 ? selections : selections[0]) : undefined;\n}\n\nexport function getOptions(select: HTMLElement): string[] {\n assertListBoxInput(select);\n ensureListBoxOpen(select);\n\n const listbox = findListBox(select);\n const options: NodeListOf<HTMLElement> = listbox.querySelectorAll(\"[role=option]\");\n\n return Array.from(options)\n .map((o: HTMLElement) => o.dataset.label ?? o.dataset.key ?? \"\")\n .filter((o) => !!o);\n}\n\nfunction findListBox(select: HTMLElement): HTMLElement {\n if (select.tagName === \"DIV\") fail(\"SelectField is readOnly\");\n const listboxId =\n select.getAttribute(\"aria-controls\") ||\n fail(\"aria-controls attribute not found, the SelectField is probably readOnly\");\n return document.getElementById(listboxId) || fail(\"listbox not found\");\n}\n\nfunction assertListBoxInput(select: HTMLElement): select is HTMLInputElement | HTMLTextAreaElement {\n if (isSelectElement(select)) {\n throw new Error(\"Beam getOptions helper does not support <select> elements\");\n }\n if (!isInputOrTextAreaElement(select)) {\n throw new Error(\n `Expected element to be INPUT or TEXTAREA, but got ${select.nodeName}. This field may be read-only. In that case we cannot get the list of options`,\n );\n }\n return true;\n}\n\nfunction isSelectElement(element: HTMLElement): element is HTMLSelectElement {\n return element.nodeName === \"SELECT\";\n}\n\nfunction isInputOrTextAreaElement(element: HTMLElement): element is HTMLInputElement | HTMLTextAreaElement {\n return element.nodeName === \"INPUT\" || element.nodeName === \"TEXTAREA\";\n}\n"],"mappings":"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","names":["row","cell","select"]}