mirror of
https://github.com/mattermost/mattermost-mobile.git
synced 2026-11-06 10:50:13 +00:00
* 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
221 lines
9.3 KiB
TypeScript
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();
|
|
});
|
|
});
|