Skip to content

Commit

Permalink
Merge branch 'main' into merx-1310-add-source-header
Browse files Browse the repository at this point in the history
  • Loading branch information
poulch authored Dec 18, 2024
2 parents 547e95f + 28e63c7 commit 283632d
Show file tree
Hide file tree
Showing 12 changed files with 256 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/poor-gifts-hear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---

Added switch focus using tab button, that may delay saving before input is filled.
5 changes: 5 additions & 0 deletions .changeset/soft-spoons-agree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---

Now category and subcategories show proper description
5 changes: 5 additions & 0 deletions .changeset/stale-swans-serve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---

You can now close order manual transaction modal by clicking the close button
5 changes: 5 additions & 0 deletions .changeset/tasty-jobs-cry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"saleor-dashboard": patch
---

Add GitHub Workflow to check licenses
48 changes: 48 additions & 0 deletions .github/workflows/check-licenses.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Check Licenses
on:
pull_request:
types:
- opened
- synchronize
# Labels are needed to handle external contributors
- labeled
- unlabeled
paths:
# Self
- ".github/workflows/check-licenses.yaml"
# Python Ecosystem
- "**/pyproject.toml"
- "**/setup.py"
- "**/requirements*.txt"
- "**/Pipfile.lock"
- "**/poetry.lock"
# JS/TS Ecosystem
- "**/package.json"
- "**/pnpm-lock.yaml"
- "**/package-lock.json"

jobs:
default:
permissions:
contents: read
pull-requests: write
uses: saleor/saleor-internal-actions/.github/workflows/run-license-check.yaml@v1
with:
# List of ecosystems to scan.
ecosystems: >-
python
javascript
# Grant rules (https://github.com/anchore/grant/blob/4362dc22cf5ea9baeccfa59b2863879afe0c30d7/README.md#usage)
rules: |
# Explicitly allow LGPL as "*GPL*" rule will cause to reject them otherwise.
- pattern: "*lgpl*"
name: "allow-lgpl"
mode: "allow"
reason: "LGPL is allowed."
- pattern: "*gpl*"
name: "deny-gpl"
mode: "deny"
reason: "GPL licenses are not compatible with BSD-3-Clause"
- pattern: "*proprietary*"
name: "deny-proprietary"
mode: "deny"
2 changes: 2 additions & 0 deletions playwright/tests/attributes.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ for (const attr of ATTRIBUTES.attributesToBeUpdated) {
await attributesPage.metadataAddFieldButton.click();

await attributesPage.fillMetadataFields("new key", "new value");
//Clicking tab only to change focus from the input, allowing to save metadata
await attributesPage.page.keyboard.press("Tab");

await attributesPage.clickSaveButton();
await attributesPage.expectSuccessBanner();
Expand Down
8 changes: 7 additions & 1 deletion src/components/Modal/Close.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ import React from "react";
export const Close = ({ onClose, ...rest }: PropsWithBox<{ onClose: () => void }>) => {
return (
<Modal.Close {...rest}>
<Button icon={<CloseIcon />} size="small" variant="tertiary" onClick={onClose} />
<Button
data-test-id="close-button"
icon={<CloseIcon />}
size="small"
variant="tertiary"
onClick={onClose}
/>
</Modal.Close>
);
};
13 changes: 12 additions & 1 deletion src/components/RichTextEditor/RichTextEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import clsx from "clsx";
import React from "react";

import { tools } from "./consts";
import { useHasRendered } from "./hooks";
import { useHasRendered, useUpdateOnRerender } from "./hooks";
import { ReactEditorJS } from "./ReactEditorJS";
import useStyles from "./styles";

Expand Down Expand Up @@ -41,6 +41,7 @@ const RichTextEditor: React.FC<RichTextEditorProps> = ({
}) => {
const classes = useStyles({});
const id = useId(defaultId);
const ref = React.useRef<EditorCore | null>(null);
const [isFocused, setIsFocused] = React.useState(false);
const [hasValue, setHasValue] = React.useState(false);
const isTyped = Boolean(hasValue || isFocused);
Expand All @@ -54,12 +55,22 @@ const RichTextEditor: React.FC<RichTextEditorProps> = ({
}

if (editorRef) {
ref.current = editor;

return (editorRef.current = editor);
}
}, []);
// We need to render FormControl first to get id from @reach/auto-id
const hasRendered = useHasRendered();

// EditorJS does not rerender when default value changes,
// so we need to manually update it
useUpdateOnRerender({
render: ref.current?.render.bind(ref.current),
defaultValue: props.defaultValue,
hasRendered,
});

return (
<FormControl
data-test-id={"rich-text-editor-" + name}
Expand Down
93 changes: 93 additions & 0 deletions src/components/RichTextEditor/hooks.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { renderHook } from "@testing-library/react-hooks";

import { useUpdateOnRerender } from "./hooks";

describe("useUpdateOnRerender", () => {
it("should call render when defaultValue changes after initial render", () => {
// Arrange
const mockRender = jest.fn();

const { rerender } = renderHook(
({ render, defaultValue, hasRendered }) =>
useUpdateOnRerender({ render, defaultValue, hasRendered }),
{
initialProps: {
render: mockRender,
defaultValue: { blocks: [{ type: "paragraph", data: { text: "Initial" } }] },
hasRendered: true,
},
},
);

// Act
rerender({
render: mockRender,
defaultValue: { blocks: [{ type: "paragraph", data: { text: "Updated" } }] },
hasRendered: true,
});

// Assert
expect(mockRender).toHaveBeenCalledWith({
blocks: [{ type: "paragraph", data: { text: "Updated" } }],
});
});

it("should call render once when defaultValue change", () => {
// Arrange
const mockRender = jest.fn();

const { rerender } = renderHook(
({ render, defaultValue, hasRendered }) =>
useUpdateOnRerender({ render, defaultValue, hasRendered }),
{
initialProps: {
render: mockRender,
defaultValue: { blocks: [{ type: "paragraph", data: { text: "Initial" } }] },
hasRendered: false,
},
},
);

// Act
rerender({
render: mockRender,
defaultValue: { blocks: [{ type: "paragraph", data: { text: "Initial" } }] },
hasRendered: true,
});
rerender({
render: mockRender,
defaultValue: { blocks: [{ type: "paragraph", data: { text: "Initial" } }] },
hasRendered: true,
});

// Assert
expect(mockRender).toHaveBeenCalledTimes(1);
});

it("should not call render if hasRendered is false", () => {
// Arrange
const mockRender = jest.fn();

const { rerender } = renderHook(
({ render, defaultValue, hasRendered }) =>
useUpdateOnRerender({ render, defaultValue, hasRendered }),
{
initialProps: {
render: mockRender,
defaultValue: { blocks: [{ type: "paragraph", data: { text: "Initial" } }] },
hasRendered: false,
},
},
);

// Act
rerender({
render: mockRender,
defaultValue: { blocks: [{ type: "paragraph", data: { text: "Updated" } }] },
hasRendered: false,
});

// Assert
expect(mockRender).not.toHaveBeenCalled();
});
});
33 changes: 32 additions & 1 deletion src/components/RichTextEditor/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { useLayoutEffect, useState } from "react";
import { EditorConfig } from "@editorjs/editorjs";
import { EditorCore } from "@react-editor-js/core";
import { useEffect, useLayoutEffect, useRef, useState } from "react";

export const useHasRendered = () => {
const [hasRendered, setHasRendereed] = useState(false);
Expand All @@ -9,3 +11,32 @@ export const useHasRendered = () => {

return hasRendered;
};

export const useUpdateOnRerender = ({
render,
defaultValue,
hasRendered,
}: {
render: EditorCore["render"] | undefined;
defaultValue: EditorConfig["data"];
hasRendered: boolean;
}) => {
const prevDefaultValue = useRef<EditorConfig["data"] | undefined>(undefined);

useEffect(() => {
if (!hasRendered) {
return;
}

// Prevent call render when defaultValue doesn't change
if (JSON.stringify(defaultValue) === JSON.stringify(prevDefaultValue.current)) {
return;
}

prevDefaultValue.current = defaultValue;

render?.({
blocks: defaultValue?.blocks ?? [],
});
}, [defaultValue, hasRendered, render]);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { act, render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import React from "react";

import { OrderManualTransactionDialog } from "./OrderManualTransactionDialog";

jest.mock("react-intl", () => ({
useIntl: jest.fn(() => ({
formatMessage: jest.fn(x => x.defaultMessage),
})),
defineMessages: jest.fn(x => x),
FormattedMessage: ({ defaultMessage }: { defaultMessage: string }) => <>{defaultMessage}</>,
}));

describe("OrderManualTransactionDialog", () => {
it("should call onClose when click in close button", async () => {
// Arrange
const onClose = jest.fn();

render(
<OrderManualTransactionDialog
error={undefined}
dialogProps={{
open: true,
onClose,
}}
submitState="default"
currency="USD"
onAddTransaction={jest.fn()}
/>,
);

// Act
await act(async () => {
await userEvent.click(screen.getByTestId("close-button"));
});

// Assert
expect(onClose).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const OrderManualTransactionDialog: React.FC<OrderManualTransactionDialog

return (
<OrderManualTransactionForm {...props}>
<DashboardModal {...dialogProps}>
<DashboardModal {...dialogProps} onChange={onClose}>
<DashboardModal.Content size="xs">
<DashboardModal.Header>
<FormattedMessage {...manualTransactionMessages.dialogTitle} />
Expand Down

0 comments on commit 283632d

Please sign in to comment.