mattermost-mobile-upstream/app/components/section_notice/index.test.tsx
Elias Nahum b6fc85385e
Migrate from RNN to Expo router (#9402)
* Expo-Router partial migration

* Full migration to ExpoRouter

* i18n

* add tests

* Merge branch 'main' into expo-router

* align package-lock.json

* i18n

* feedback review

* feedback review

* android 16kb patch

* Refactored emoji picker keyboard using a state machine

* set android launch_screen in drawables instead of layout

* no conditional hooks

* remove duplicate call in test

* address feedback

* fix tests and address more feedback

* small corrections

* small corrections

* small corrections

* fix draft test

* fix draft test 2

* remove navigateToScreen in draff test

* fix nit in draft test

* remove doc file

* Feedback review

* fix snapshots

* improve test coverage

* fix i18n

* Upgrade t o RN 0.83, other dependencies and new architecture (#9737)

* library hardware-keyboard android new arch support fix

* library rnshare android new arch support fix

* library rnutils android new arch support fix

* library secure-pdf-viewer add new arch support

* Enable new arch on iOS and Android

* update emm and network client with new-arch

* update intune to use new-arch

* performance improvements

* fix tests

* fixes post input on new-arch

* fix android emoji picker

* remove doc

* run tests in parallel

* upgrade to React Native 0.83.9, Expo 55, React 19, and New Architecture

Bumps core dependencies to their latest versions:
- React Native 0.77.3 → 0.83.9 (New Architecture enabled)
- React 18.3.1 → 19.2.5
- Expo SDK 52 → 55
- TypeScript 5.8.3 → 6.0.3
- Node.js 22.16.0 → 24.15.0
- react-native-reanimated 3.17.3 → 4.3.0
- Various other dependency upgrades

Migrates iOS AppDelegate from Objective-C to Swift, updates Android
build tooling and Gradle wrapper, refreshes all patches and font
assets, and adapts app code, tests, and CI workflows throughout for
API changes introduced by these upgrades.

* remove unecessary dismissKeyboard in notifications

* feedback review

* update intune to use new-arch

* update @mattermost deps

* missing i18n string

* additional fixes

* update fastlane
2026-05-13 17:44:55 +08:00

221 lines
9.3 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {type ComponentProps} from 'react';
import {Screens} from '@constants';
import {fireEvent, renderWithEverything} from '@test/intl-test-helper';
import TestHelper from '@test/test_helper';
import SectionNotice from './index';
import type Database from '@nozbe/watermelondb/Database';
function getBaseProps(): ComponentProps<typeof SectionNotice> {
return {
title: 'Some title',
text: 'Some text',
type: 'info',
isDismissable: true,
primaryButton: {
onClick: jest.fn(),
text: 'primary button',
leadingIcon: 'chevron-left',
trailingIcon: 'chevron-right',
loading: true,
},
secondaryButton: {
onClick: jest.fn(),
text: 'secondary button',
leadingIcon: 'chevron-left',
trailingIcon: 'chevron-right',
loading: true,
},
linkButton: {
onClick: jest.fn(),
text: 'link button',
leadingIcon: 'chevron-left',
trailingIcon: 'chevron-right',
loading: true,
},
onDismissClick: jest.fn(),
location: Screens.SETTINGS_NOTIFICATION_PUSH,
};
}
describe('Section notice', () => {
let database: Database;
beforeAll(async () => {
const server = await TestHelper.setupServerDatabase();
database = server.database;
});
it('match snapshot', () => {
const props = getBaseProps();
const wrapper = renderWithEverything(<SectionNotice {...props}/>, {database});
expect(wrapper.toJSON()).toMatchSnapshot();
});
it('should show buttons only if defined', () => {
const props = getBaseProps();
const wrapper = renderWithEverything(<SectionNotice {...props}/>, {database});
const primaryText = props.primaryButton!.text;
const secondaryText = props.secondaryButton!.text;
const linkText = props.linkButton!.text;
expect(wrapper.getAllByRole('button')).toHaveLength(4);
expect(wrapper.getByText(primaryText)).toBeVisible();
expect(wrapper.getByText(secondaryText)).toBeVisible();
expect(wrapper.getByText(linkText)).toBeVisible();
expect(wrapper.getByTestId('sectionNoticeDismissButton')).toBeVisible();
props.primaryButton = undefined;
wrapper.rerender(<SectionNotice {...props}/>);
expect(wrapper.getAllByRole('button')).toHaveLength(3);
expect(wrapper.queryByText(primaryText)).not.toBeVisible();
expect(wrapper.getByText(secondaryText)).toBeVisible();
expect(wrapper.getByText(linkText)).toBeVisible();
expect(wrapper.getByTestId('sectionNoticeDismissButton')).toBeVisible();
props.secondaryButton = undefined;
wrapper.rerender(<SectionNotice {...props}/>);
expect(wrapper.getAllByRole('button')).toHaveLength(2);
expect(wrapper.queryByText(primaryText)).not.toBeVisible();
expect(wrapper.queryByText(secondaryText)).not.toBeVisible();
expect(wrapper.getByText(linkText)).toBeVisible();
expect(wrapper.getByTestId('sectionNoticeDismissButton')).toBeVisible();
props.linkButton = undefined;
wrapper.rerender(<SectionNotice {...props}/>);
expect(wrapper.getAllByRole('button')).toHaveLength(1);
expect(wrapper.queryByText(primaryText)).not.toBeVisible();
expect(wrapper.queryByText(secondaryText)).not.toBeVisible();
expect(wrapper.queryByText(linkText)).not.toBeVisible();
expect(wrapper.getByTestId('sectionNoticeDismissButton')).toBeVisible();
props.isDismissable = false;
wrapper.rerender(<SectionNotice {...props}/>);
expect(wrapper.queryAllByRole('button')).toHaveLength(0);
expect(wrapper.queryByText(primaryText)).not.toBeVisible();
expect(wrapper.queryByText(secondaryText)).not.toBeVisible();
expect(wrapper.queryByText(linkText)).not.toBeVisible();
expect(wrapper.queryByTestId('sectionNoticeDismissButton')).not.toBeVisible();
});
it('should show the correct icon on each section type', () => {
// CompassIcon renders as a Text node; `name` is consumed internally and does not appear on
// rendered props. Verify the correct glyph character is rendered as children instead.
const INFORMATION_OUTLINE = String.fromCodePoint(0xf02fd); // information-outline
const ALERT_OUTLINE = String.fromCodePoint(0xf002a); // alert-outline
const LIGHTBULB_OUTLINE = String.fromCodePoint(0xf0336); // lightbulb-outline
const CHECK = String.fromCodePoint(0xf012c); // check
const props = getBaseProps();
props.type = 'info';
const wrapper = renderWithEverything(<SectionNotice {...props}/>, {database});
let icon = wrapper.getByTestId('sectionNoticeHeaderIcon');
expect(icon).toBeVisible();
expect(icon.props.children).toContain(INFORMATION_OUTLINE);
props.type = 'danger';
wrapper.rerender(<SectionNotice {...props}/>);
icon = wrapper.getByTestId('sectionNoticeHeaderIcon');
expect(icon).toBeVisible();
expect(icon.props.children).toContain(ALERT_OUTLINE);
props.type = 'hint';
wrapper.rerender(<SectionNotice {...props}/>);
icon = wrapper.getByTestId('sectionNoticeHeaderIcon');
expect(icon).toBeVisible();
expect(icon.props.children).toContain(LIGHTBULB_OUTLINE);
props.type = 'success';
wrapper.rerender(<SectionNotice {...props}/>);
icon = wrapper.getByTestId('sectionNoticeHeaderIcon');
expect(icon).toBeVisible();
expect(icon.props.children).toContain(CHECK);
props.type = 'warning';
wrapper.rerender(<SectionNotice {...props}/>);
icon = wrapper.getByTestId('sectionNoticeHeaderIcon');
expect(icon).toBeVisible();
expect(icon.props.children).toContain(ALERT_OUTLINE);
props.type = 'welcome';
wrapper.rerender(<SectionNotice {...props}/>);
expect(wrapper.queryByTestId('sectionNoticeHeaderIcon')).not.toBeVisible();
});
it('should have the correct background on each section type', () => {
const props = getBaseProps();
props.type = 'info';
const wrapper = renderWithEverything(<SectionNotice {...props}/>, {database});
let container = wrapper.getByTestId('sectionNoticeContainer');
expect(container).toHaveStyle({backgroundColor: 'rgba(93,137,234,0.08)'});
props.type = 'danger';
wrapper.rerender(<SectionNotice {...props}/>);
container = wrapper.getByTestId('sectionNoticeContainer');
expect(container).toHaveStyle({backgroundColor: 'rgba(210,75,78,0.08)'});
props.type = 'hint';
wrapper.rerender(<SectionNotice {...props}/>);
container = wrapper.getByTestId('sectionNoticeContainer');
expect(container).toHaveStyle({backgroundColor: 'rgba(93,137,234,0.08)'});
props.type = 'success';
wrapper.rerender(<SectionNotice {...props}/>);
container = wrapper.getByTestId('sectionNoticeContainer');
expect(container).toHaveStyle({backgroundColor: 'rgba(61,184,135,0.08)'});
props.type = 'warning';
wrapper.rerender(<SectionNotice {...props}/>);
container = wrapper.getByTestId('sectionNoticeContainer');
expect(container).toHaveStyle({backgroundColor: 'rgba(255,188,31,0.08)'});
props.type = 'welcome';
wrapper.rerender(<SectionNotice {...props}/>);
container = wrapper.getByTestId('sectionNoticeContainer');
expect(container).toHaveStyle({backgroundColor: 'rgba(63,67,80,0.04)'});
});
it('all buttons perform the expected action', () => {
const props = getBaseProps();
const wrapper = renderWithEverything(<SectionNotice {...props}/>, {database});
fireEvent.press(wrapper.getByText(props.primaryButton!.text));
expect(props.primaryButton!.onClick).toHaveBeenCalled();
expect(props.secondaryButton!.onClick).not.toHaveBeenCalled();
expect(props.linkButton!.onClick).not.toHaveBeenCalled();
expect(props.onDismissClick!).not.toHaveBeenCalled();
jest.clearAllMocks();
fireEvent.press(wrapper.getByText(props.secondaryButton!.text));
expect(props.primaryButton!.onClick).not.toHaveBeenCalled();
expect(props.secondaryButton!.onClick).toHaveBeenCalled();
expect(props.linkButton!.onClick).not.toHaveBeenCalled();
expect(props.onDismissClick!).not.toHaveBeenCalled();
jest.clearAllMocks();
fireEvent.press(wrapper.getByText(props.linkButton!.text));
expect(props.primaryButton!.onClick).not.toHaveBeenCalled();
expect(props.secondaryButton!.onClick).not.toHaveBeenCalled();
expect(props.linkButton!.onClick).toHaveBeenCalled();
expect(props.onDismissClick!).not.toHaveBeenCalled();
jest.clearAllMocks();
fireEvent.press(wrapper.getByTestId('sectionNoticeDismissButton'));
expect(props.primaryButton!.onClick).not.toHaveBeenCalled();
expect(props.secondaryButton!.onClick).not.toHaveBeenCalled();
expect(props.linkButton!.onClick).not.toHaveBeenCalled();
expect(props.onDismissClick!).toHaveBeenCalled();
});
});