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 testing and storybook component for CatalogDiffModal #15426

Merged
merged 7 commits into from
Aug 10, 2022
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
import { cleanup, render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { IntlProvider } from "react-intl";

import {
AirbyteCatalog,
CatalogDiff,
DestinationSyncMode,
StreamTransform,
SyncMode,
} from "core/request/AirbyteClient";

import messages from "../../../locales/en.json";
import { CatalogDiffModal } from "./CatalogDiffModal";

const mockCatalogDiff: CatalogDiff = {
transforms: [],
};

const removedItems: StreamTransform[] = [
{
transformType: "remove_stream",
streamDescriptor: { namespace: "apple", name: "dragonfruit" },
},
{
transformType: "remove_stream",
streamDescriptor: { namespace: "apple", name: "eclair" },
},
{
transformType: "remove_stream",
streamDescriptor: { namespace: "apple", name: "fishcake" },
},
{
transformType: "remove_stream",
streamDescriptor: { namespace: "apple", name: "gelatin_mold" },
},
];

const addedItems: StreamTransform[] = [
{
transformType: "add_stream",
streamDescriptor: { namespace: "apple", name: "banana" },
},
{
transformType: "add_stream",
streamDescriptor: { namespace: "apple", name: "carrot" },
},
];

const updatedItems: StreamTransform[] = [
{
transformType: "update_stream",
streamDescriptor: { namespace: "apple", name: "harissa_paste" },
updateStream: [
{ transformType: "add_field", fieldName: ["users", "phone"] },
{ transformType: "add_field", fieldName: ["users", "email"] },
{ transformType: "remove_field", fieldName: ["users", "lastName"] },

{
transformType: "update_field_schema",
fieldName: ["users", "address"],
updateFieldSchema: { oldSchema: { type: "number" }, newSchema: { type: "string" } },
},
],
},
];

const mockCatalog: AirbyteCatalog = {
streams: [
{
stream: {
namespace: "apple",
name: "banana",
},
config: {
syncMode: SyncMode.full_refresh,
destinationSyncMode: DestinationSyncMode.overwrite,
},
},
{
stream: {
namespace: "apple",
name: "carrot",
},
config: {
syncMode: SyncMode.full_refresh,
destinationSyncMode: DestinationSyncMode.overwrite,
},
},
{
stream: {
namespace: "apple",
name: "dragonfruit",
},
config: {
syncMode: SyncMode.full_refresh,
destinationSyncMode: DestinationSyncMode.overwrite,
},
},
{
stream: {
namespace: "apple",
name: "eclair",
},
config: {
syncMode: SyncMode.full_refresh,
destinationSyncMode: DestinationSyncMode.overwrite,
},
},
{
stream: {
namespace: "apple",
name: "fishcake",
},
config: {
syncMode: SyncMode.incremental,
destinationSyncMode: DestinationSyncMode.append_dedup,
},
},
{
stream: {
namespace: "apple",
name: "gelatin_mold",
},
config: {
syncMode: SyncMode.incremental,
destinationSyncMode: DestinationSyncMode.append_dedup,
},
},
{
stream: {
namespace: "apple",
name: "harissa_paste",
},
config: {
syncMode: SyncMode.full_refresh,
destinationSyncMode: DestinationSyncMode.overwrite,
},
},
],
};

describe("catalog diff modal", () => {
afterEach(cleanup);
beforeEach(() => {
mockCatalogDiff.transforms = [];
});

test("it renders the correct section for each type of transform", () => {
mockCatalogDiff.transforms.push(...addedItems, ...removedItems, ...updatedItems);

render(
<IntlProvider messages={messages} locale="en">
<CatalogDiffModal
catalogDiff={mockCatalogDiff}
catalog={mockCatalog}
onClose={() => {
return null;
}}
/>
</IntlProvider>
);

/**
* tests for:
* - proper sections being created
* - syncmode string is only rendered for removed streams
*/

const newStreamsTable = screen.getByRole("table", { name: /new streams/ });
expect(newStreamsTable).toBeInTheDocument();

const newStreamRow = screen.getByRole("row", { name: "apple banana" });
expect(newStreamRow).toBeInTheDocument();

const newStreamRowWithSyncMode = screen.queryByRole("row", { name: "apple carrot incremental | append_dedup" });
expect(newStreamRowWithSyncMode).not.toBeInTheDocument();

const removedStreamsTable = screen.getByRole("table", { name: /removed streams/ });
expect(removedStreamsTable).toBeInTheDocument();

const removedStreamRowWithSyncMode = screen.getByRole("row", {
name: "apple dragonfruit full_refresh | overwrite",
});
expect(removedStreamRowWithSyncMode).toBeInTheDocument();

const updatedStreamsSection = screen.getByRole("list", { name: /table with changes/ });
expect(updatedStreamsSection).toBeInTheDocument();

const updatedStreamRowWithSyncMode = screen.queryByRole("row", {
name: "apple harissa_paste full_refresh | overwrite",
});
expect(updatedStreamRowWithSyncMode).not.toBeInTheDocument();
});

test("added fields are not rendered when not in the diff", () => {
mockCatalogDiff.transforms.push(...removedItems, ...updatedItems);

render(
<IntlProvider messages={messages} locale="en">
<CatalogDiffModal
catalogDiff={mockCatalogDiff}
catalog={mockCatalog}
onClose={() => {
return null;
}}
/>
</IntlProvider>
);

const newStreamsTable = screen.queryByRole("table", { name: /new streams/ });
expect(newStreamsTable).not.toBeInTheDocument();
});

test("removed fields are not rendered when not in the diff", () => {
mockCatalogDiff.transforms.push(...addedItems, ...updatedItems);

render(
<IntlProvider messages={messages} locale="en">
<CatalogDiffModal
catalogDiff={mockCatalogDiff}
catalog={mockCatalog}
onClose={() => {
return null;
}}
/>
</IntlProvider>
);

const removedStreamsTable = screen.queryByRole("table", { name: /removed streams/ });
expect(removedStreamsTable).not.toBeInTheDocument();
});

test("changed streams accordion opens/closes on clicking the description row", () => {
mockCatalogDiff.transforms.push(...addedItems, ...updatedItems);

render(
<IntlProvider messages={messages} locale="en">
<CatalogDiffModal
catalogDiff={mockCatalogDiff}
catalog={mockCatalog}
onClose={() => {
return null;
}}
/>
</IntlProvider>
);

const accordionHeader = screen.getByRole("button", { name: /toggle accordion/ });

expect(accordionHeader).toBeInTheDocument();

const nullAccordionBody = screen.queryByRole("table", { name: /removed fields/ });
expect(nullAccordionBody).not.toBeInTheDocument();

userEvent.click(accordionHeader);
const openAccordionBody = screen.getByRole("table", { name: /removed fields/ });
expect(openAccordionBody).toBeInTheDocument();

userEvent.click(accordionHeader);
const nullAccordionBodyAgain = screen.queryByRole("table", { name: /removed fields/ });
expect(nullAccordionBodyAgain).not.toBeInTheDocument();
mockCatalogDiff.transforms = [];
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const DiffAccordion: React.FC<DiffAccordionProps> = ({ streamTransform })
<Disclosure>
{({ open }) => (
<>
<Disclosure.Button className={styles.accordionButton}>
<Disclosure.Button className={styles.accordionButton} aria-label="toggle accordion">
<DiffAccordionHeader
streamDescriptor={streamTransform.streamDescriptor}
removedCount={removedItems.length}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ interface DiffFieldTableProps {

export const DiffFieldTable: React.FC<DiffFieldTableProps> = ({ fieldTransforms, diffVerb }) => {
return (
<table className={styles.table}>
<table className={styles.table} aria-label={`${diffVerb} fields`}>
<thead>
<tr className={styles.accordionSubHeader}>
<th>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ export const DiffIconBlock: React.FC<DiffIconBlockProps> = ({ newCount, removedC
num={removedCount}
color="red"
light
ariaLabel={`${removedCount} ${formatMessage(
ariaLabel={`${formatMessage(
{
id: "connection.updateSchema.removed",
},
{
value: removedCount,
item: formatMessage({ id: "field" }, { values: { count: removedCount } }),
item: formatMessage({ id: "connection.updateSchema.field" }, { count: removedCount }),
}
)}`}
/>
Expand All @@ -35,13 +35,13 @@ export const DiffIconBlock: React.FC<DiffIconBlockProps> = ({ newCount, removedC
num={newCount}
color="green"
light
ariaLabel={`${newCount} ${formatMessage(
ariaLabel={`${formatMessage(
{
id: "connection.updateSchema.new",
},
{
value: newCount,
item: formatMessage({ id: "field" }, { values: { count: newCount } }),
item: formatMessage({ id: "connection.updateSchema.field" }, { count: newCount }),
}
)}`}
/>
Expand All @@ -51,13 +51,13 @@ export const DiffIconBlock: React.FC<DiffIconBlockProps> = ({ newCount, removedC
num={changedCount}
color="blue"
light
ariaLabel={`${changedCount} ${formatMessage(
ariaLabel={`${formatMessage(
{
id: "connection.updateSchema.changed",
},
{
value: changedCount,
item: formatMessage({ id: "field" }, { values: { count: changedCount } }),
item: formatMessage({ id: "connection.updateSchema.field" }, { count: changedCount }),
}
)}`}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const DiffSection: React.FC<DiffSectionProps> = ({ streams, catalog, diff
<div className={styles.sectionHeader}>
<DiffHeader diffCount={streams.length} diffVerb={diffVerb} diffType="stream" />
</div>
<table>
<table aria-label={`${diffVerb} streams table`}>
<thead className={styles.sectionSubHeader}>
<tr>
<th>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const FieldRow: React.FC<FieldRowProps> = ({ transform }) => {
[styles.mod]: diffType === "update",
});

const contentStyle = classnames(styles.content, {
const contentStyle = classnames(styles.content, styles.cell, {
[styles.add]: diffType === "add",
[styles.remove]: diffType === "remove",
[styles.update]: diffType === "update",
Expand All @@ -50,16 +50,16 @@ export const FieldRow: React.FC<FieldRowProps> = ({ transform }) => {
)}
</td>
<td className={contentStyle}>
<td className={styles.cell}>
<div className={styles.cell}>
<span>{fieldName}</span>
</td>
<td className={updateCellStyle}>
</div>
<div className={updateCellStyle}>
{oldType && newType && (
<span>
{oldType} <FontAwesomeIcon icon={faArrowRight} /> {newType}
</span>
)}
</td>
</div>
</td>
</tr>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,15 @@ export const FieldSection: React.FC<FieldSectionProps> = ({ streams, diffVerb })
</div>
<div className={styles.fieldRowsContainer}>
{streams.length > 0 && (
<ul>
<ul
aria-label={formatMessage(
{ id: "connection.updateSchema.changed" },
{
value: streams.length,
item: formatMessage({ id: "connection.updateSchema.stream" }, { count: streams.length }),
}
)}
>
{streams.map((stream) => {
return (
<li key={`${stream.streamDescriptor.namespace}.${stream.streamDescriptor.name}`}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const StreamRow: React.FC<StreamRowProps> = ({ streamTransform, syncMode,
)}
</td>
<td className={styles.nameCell}>{namespace}</td>
<td className={styles.nameCell}>{itemName}</td>{" "}
<td className={styles.nameCell}>{itemName}</td>
<td>{diffVerb === "removed" && syncMode && <SyncModeBox syncModeString={syncMode} />} </td>
</tr>
);
Expand Down
Loading