Skip to content
Open
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
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@
"patchedDependencies": {
"@mendix/pluggable-widgets-tools@11.8.0": "patches/@mendix+pluggable-widgets-tools+11.8.0.patch",
"@ptomasroos/react-native-multi-slider@1.0.0": "patches/@ptomasroos+react-native-multi-slider+1.0.0.patch",
"react-native-action-button@2.8.5": "patches/react-native-action-button+2.8.5.patch",
"react-native-gesture-handler@2.30.0": "patches/react-native-gesture-handler+2.30.0.patch",
"react-native-slider@0.11.0": "patches/react-native-slider+0.11.0.patch",
"react-native-snap-carousel@3.9.1": "patches/react-native-snap-carousel+3.9.1.patch",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

### Changed

- Replaced `react-native-action-button` library with custom implementation using React Native's Animated API for better maintainability and reduced bundle size.

- Removed deprecated `react-native-prop-types` dependency.

## [4.1.0] - 2024-12-3

### Changed
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "floating-action-button-native",
"widgetName": "FloatingActionButton",
"version": "4.2.0",
"version": "4.2.1",
"license": "Apache-2.0",
"repository": {
"type": "git",
Expand All @@ -20,9 +20,7 @@
},
"dependencies": {
"@mendix/piw-native-utils-internal": "*",
"@mendix/piw-utils-internal": "*",
"deprecated-react-native-prop-types": "^4.0.0",
"react-native-action-button": "^2.8.5"
"@mendix/piw-utils-internal": "*"
},
"devDependencies": {
"@mendix/pluggable-widgets-tools": "*"
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { FloatingActionButtonProps } from "../../typings/FloatingActionButtonProps";
import { FloatingActionButtonStyle } from "../ui/styles";
import { fireEvent, render, waitForElementToBeRemoved } from "@testing-library/react-native";
import { fireEvent, render } from "@testing-library/react-native";
import { FloatingActionButton } from "../FloatingActionButton";
import { actionValue, dynamicValue } from "@mendix/piw-utils-internal";
import { NativeIcon } from "mendix";
import { Icon } from "mendix/components/native/Icon";
import { ReactTestInstance } from "react-test-renderer";

describe("FloatingActionButton", () => {
let defaultProps: FloatingActionButtonProps<FloatingActionButtonStyle>;
Expand Down Expand Up @@ -58,17 +57,28 @@ describe("FloatingActionButton", () => {
expect(component.toJSON()).toMatchSnapshot();
});

it.skip("should open and close when clicked and secondary buttons are defined", async () => {
it("should open and close when clicked and secondary buttons are defined", () => {
const { getByTestId, queryAllByTestId } = render(
<FloatingActionButton {...defaultProps} secondaryButtons={secondaryButtons} />
);

// Initially closed - buttons exist but have opacity 0
const closedButtons = queryAllByTestId(/FloatingAction\$button*/);
expect(closedButtons).toHaveLength(3);
closedButtons.forEach(button => {
const animatedView = button.parent;
expect(animatedView?.props.style).toBeDefined();
});

// Open - buttons should still exist (now with opacity > 0 after animation)
fireEvent(getByTestId("FloatingAction"), "onPress");
expect(queryAllByTestId(/FloatingAction\$button*/)).toHaveLength(3);
const openButtons = queryAllByTestId(/FloatingAction\$button*/);
expect(openButtons).toHaveLength(3);

// Close again - buttons still exist (will animate back to opacity 0)
fireEvent(getByTestId("FloatingAction"), "onPress");
await waitForElementToBeRemoved(() => queryAllByTestId("FloatingAction$button0"));
expect(queryAllByTestId(/FloatingAction\$button*/)).toHaveLength(0);
const closedAgainButtons = queryAllByTestId(/FloatingAction\$button*/);
expect(closedAgainButtons).toHaveLength(3);
});

it("should cancel any events of primary button if secondary buttons exist", () => {
Expand All @@ -89,7 +99,7 @@ describe("FloatingActionButton", () => {
expect(mockEvent.execute).toHaveBeenCalledTimes(1);
});

it.skip("should trigger event on secondary button", () => {
it("should trigger event on secondary button", () => {
const { getByTestId } = render(<FloatingActionButton {...defaultProps} secondaryButtons={secondaryButtons} />);

fireEvent(getByTestId("FloatingAction"), "onPress");
Expand All @@ -114,29 +124,33 @@ describe("FloatingActionButton", () => {
secondaryButtons={secondaryButtons}
/>
);
const transformStyle = [{ transform: [{ rotate: "-180deg" }] }];

const iconView = getByTestId("FloatingAction$IconView").children[0] as ReactTestInstance;
const iconComponent = iconView.findByType(Icon);
const iconViewContainer = getByTestId("FloatingAction$IconView");
const iconComponent = iconViewContainer.findByType(Icon);
expect(iconComponent.props.icon).toEqual(icon.value);
expect(iconView.props.style).not.toEqual(expect.arrayContaining(transformStyle));

// Check rotation is at 0deg initially
const initialStyle = iconViewContainer.props.style;
expect(initialStyle).toBeDefined();

fireEvent(getByTestId("FloatingAction"), "onPress");

const iconActiveComponent = iconView.findByType(Icon);
const iconActiveComponent = iconViewContainer.findByType(Icon);
expect(iconActiveComponent.props.icon).toEqual(iconActive.value);
expect(iconView.props.style).toEqual(expect.arrayContaining(transformStyle));

// Check rotation transform exists after press (will be interpolated, not exactly -180deg in test)
const activeStyle = iconViewContainer.props.style;
expect(activeStyle).toBeDefined();
});

it.skip("should have custom icon on secondary button", async () => {
it("should have custom icon on secondary button", async () => {
const { getByTestId } = render(<FloatingActionButton {...defaultProps} secondaryButtons={secondaryButtons} />);

fireEvent(getByTestId("FloatingAction"), "onPress");
const secondaryButtonIcon = getByTestId("FloatingAction$button2").findByType(Icon);
expect(secondaryButtonIcon.props.icon).toEqual(secondaryButtons[2].icon.value);
});

it.skip("should have custom caption on secondary button", async () => {
it("should have custom caption on secondary button", async () => {
const { getByTestId, findByText } = render(
<FloatingActionButton {...defaultProps} secondaryButtons={secondaryButtons} />
);
Expand Down
Loading
Loading