- {me !== account.id && relationship && !isRedesign && (
-
- )}
-
{!suspendedOrHidden && (
-
- {!isRedesign && (
-
- )}
- {isRedesign && (
-
- )}
+
@@ -192,31 +173,19 @@ export const AccountHeader: React.FC<{
)}
- {!isRedesign && (
-
- )}
-
{!suspendedOrHidden && (
- {me &&
- account.id !== me &&
- (isRedesign ? (
-
- ) : (
-
- ))}
+ {me && account.id !== me && (
+
+ )}
@@ -231,20 +200,18 @@ export const AccountHeader: React.FC<{
)}
- {isRedesign && (
-
- )}
+
- {!hideTabs && !hidden &&
}
+ {!hideTabs && !hidden &&
}
diff --git a/app/javascript/mastodon/features/account_timeline/components/account_name.tsx b/app/javascript/mastodon/features/account_timeline/components/account_name.tsx
index ac6ab2735e..3fd9e30c28 100644
--- a/app/javascript/mastodon/features/account_timeline/components/account_name.tsx
+++ b/app/javascript/mastodon/features/account_timeline/components/account_name.tsx
@@ -14,10 +14,6 @@ import { useAppSelector } from '@/mastodon/store';
import AtIcon from '@/material-icons/400-24px/alternate_email.svg?react';
import HelpIcon from '@/material-icons/400-24px/help.svg?react';
import DomainIcon from '@/material-icons/400-24px/language.svg?react';
-import LockIcon from '@/material-icons/400-24px/lock.svg?react';
-
-import { DomainPill } from '../../account/components/domain_pill';
-import { isRedesignEnabled } from '../common';
import classes from './redesign.module.scss';
@@ -34,7 +30,6 @@ const messages = defineMessages({
});
export const AccountName: FC<{ accountId: string }> = ({ accountId }) => {
- const intl = useIntl();
const account = useAccount(accountId);
const me = useAppSelector((state) => state.meta.get('me') as string);
const localDomain = useAppSelector(
@@ -47,32 +42,6 @@ export const AccountName: FC<{ accountId: string }> = ({ accountId }) => {
const [username = '', domain = localDomain] = account.acct.split('@');
- if (!isRedesignEnabled()) {
- return (
-
-
-
-
- @{username}
- @{domain}
-
-
- {account.locked && (
-
- )}
-
-
- );
- }
-
return (
diff --git a/app/javascript/mastodon/features/account_timeline/components/badges.tsx b/app/javascript/mastodon/features/account_timeline/components/badges.tsx
index 9bfc3b5da5..75e0c31a18 100644
--- a/app/javascript/mastodon/features/account_timeline/components/badges.tsx
+++ b/app/javascript/mastodon/features/account_timeline/components/badges.tsx
@@ -20,8 +20,6 @@ import { useAccount } from '@/mastodon/hooks/useAccount';
import type { AccountRole } from '@/mastodon/models/account';
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
-import { isRedesignEnabled } from '../common';
-
import classes from './redesign.module.scss';
export const AccountBadges: FC<{ accountId: string }> = ({ accountId }) => {
@@ -46,9 +44,6 @@ export const AccountBadges: FC<{ accountId: string }> = ({ accountId }) => {
return null;
}
- const isRedesign = isRedesignEnabled();
- const className = isRedesign ? classes.badge : '';
-
const domain = account.acct.includes('@')
? account.acct.split('@')[1]
: localDomain;
@@ -58,7 +53,7 @@ export const AccountBadges: FC<{ accountId: string }> = ({ accountId }) => {
,
@@ -68,8 +63,8 @@ export const AccountBadges: FC<{ accountId: string }> = ({ accountId }) => {
,
);
@@ -77,17 +72,17 @@ export const AccountBadges: FC<{ accountId: string }> = ({ accountId }) => {
});
if (account.bot) {
- badges.push();
+ badges.push();
}
if (account.group) {
- badges.push();
+ badges.push();
}
- if (isRedesign && relationship) {
+ if (relationship) {
if (relationship.blocking) {
badges.push(
,
);
}
@@ -95,7 +90,7 @@ export const AccountBadges: FC<{ accountId: string }> = ({ accountId }) => {
badges.push(
= ({ accountId }) => {
badges.push(
,
);
@@ -136,5 +131,5 @@ export const PinnedBadge: FC = () => (
function isAdminBadge(role: AccountRole) {
const name = role.name.toLowerCase();
- return isRedesignEnabled() && (name === 'admin' || name === 'owner');
+ return name === 'admin' || name === 'owner';
}
diff --git a/app/javascript/mastodon/features/account_timeline/components/buttons.tsx b/app/javascript/mastodon/features/account_timeline/components/buttons.tsx
index fe0bbbfbd6..0c24207b6a 100644
--- a/app/javascript/mastodon/features/account_timeline/components/buttons.tsx
+++ b/app/javascript/mastodon/features/account_timeline/components/buttons.tsx
@@ -16,8 +16,6 @@ import NotificationsIcon from '@/material-icons/400-24px/notifications.svg?react
import NotificationsActiveIcon from '@/material-icons/400-24px/notifications_active-fill.svg?react';
import ShareIcon from '@/material-icons/400-24px/share.svg?react';
-import { isRedesignEnabled } from '../common';
-
import { AccountMenu } from './menu';
const messages = defineMessages({
@@ -97,7 +95,6 @@ const AccountButtonsOther: FC<
accountId={accountId}
className='account__header__follow-button'
labelLength='long'
- withUnmute={!isRedesignEnabled()}
/>
)}
{isFollowing && (
diff --git a/app/javascript/mastodon/features/account_timeline/components/fields.tsx b/app/javascript/mastodon/features/account_timeline/components/fields.tsx
index 5bad90aaae..80d6cc7f67 100644
--- a/app/javascript/mastodon/features/account_timeline/components/fields.tsx
+++ b/app/javascript/mastodon/features/account_timeline/components/fields.tsx
@@ -1,68 +1,30 @@
import { useCallback, useMemo, useRef, useState } from 'react';
import type { FC } from 'react';
-import { defineMessage, FormattedMessage, useIntl } from 'react-intl';
+import { defineMessage, useIntl } from 'react-intl';
import classNames from 'classnames';
import IconVerified from '@/images/icons/icon_verified.svg?react';
import { openModal } from '@/mastodon/actions/modal';
-import { AccountFields } from '@/mastodon/components/account_fields';
import { CustomEmojiProvider } from '@/mastodon/components/emoji/context';
import type { EmojiHTMLProps } from '@/mastodon/components/emoji/html';
import { EmojiHTML } from '@/mastodon/components/emoji/html';
-import { FormattedDateWrapper } from '@/mastodon/components/formatted_date';
import { Icon } from '@/mastodon/components/icon';
import { IconButton } from '@/mastodon/components/icon_button';
import { MiniCard } from '@/mastodon/components/mini_card';
import { useElementHandledLink } from '@/mastodon/components/status/handled_link';
import { useAccount } from '@/mastodon/hooks/useAccount';
import { useResizeObserver } from '@/mastodon/hooks/useObserver';
-import type { Account } from '@/mastodon/models/account';
import { useAppDispatch } from '@/mastodon/store';
import MoreIcon from '@/material-icons/400-24px/more_horiz.svg?react';
import { cleanExtraEmojis } from '../../emoji/normalize';
import type { AccountField } from '../common';
-import { isRedesignEnabled } from '../common';
import { useFieldHtml } from '../hooks/useFieldHtml';
import classes from './redesign.module.scss';
-export const AccountHeaderFields: FC<{ accountId: string }> = ({
- accountId,
-}) => {
- const account = useAccount(accountId);
-
- if (!account) {
- return null;
- }
-
- if (isRedesignEnabled()) {
- return ;
- }
-
- return (
-
- );
-};
-
const verifyMessage = defineMessage({
id: 'account.link_verified_on',
defaultMessage: 'Ownership of this link was checked on {date}',
@@ -75,13 +37,22 @@ const dateFormatOptions: Intl.DateTimeFormatOptions = {
minute: '2-digit',
};
-const RedesignAccountHeaderFields: FC<{ account: Account }> = ({ account }) => {
+export const AccountHeaderFields: FC<{ accountId: string }> = ({
+ accountId,
+}) => {
+ const account = useAccount(accountId);
+
const emojis = useMemo(
- () => cleanExtraEmojis(account.emojis),
- [account.emojis],
+ () => cleanExtraEmojis(account?.emojis),
+ [account?.emojis],
);
+ const accountFields = account?.fields;
const fields: AccountField[] = useMemo(() => {
- const fields = account.fields.toJS();
+ const fields = accountFields?.toJS();
+ if (!fields) {
+ return [];
+ }
+
if (!emojis) {
return fields.map((field) => ({
...field,
@@ -102,10 +73,10 @@ const RedesignAccountHeaderFields: FC<{ account: Account }> = ({ account }) => {
field.value_plain?.includes(`:${code}:`),
),
}));
- }, [account.fields, emojis]);
+ }, [accountFields, emojis]);
const htmlHandlers = useElementHandledLink({
- hashtagAccountId: account.id,
+ hashtagAccountId: account?.id,
});
const { wrapperRef } = useColumnWrap();
diff --git a/app/javascript/mastodon/features/account_timeline/components/menu.tsx b/app/javascript/mastodon/features/account_timeline/components/menu.tsx
index 6ef0375702..24ef091297 100644
--- a/app/javascript/mastodon/features/account_timeline/components/menu.tsx
+++ b/app/javascript/mastodon/features/account_timeline/components/menu.tsx
@@ -40,8 +40,6 @@ import PersonRemoveIcon from '@/material-icons/400-24px/person_remove.svg?react'
import ReportIcon from '@/material-icons/400-24px/report.svg?react';
import ShareIcon from '@/material-icons/400-24px/share.svg?react';
-import { isRedesignEnabled } from '../common';
-
import classes from './redesign.module.scss';
export const AccountMenu: FC<{ accountId: string }> = ({ accountId }) => {
@@ -63,19 +61,9 @@ export const AccountMenu: FC<{ accountId: string }> = ({ accountId }) => {
return [];
}
- if (isRedesignEnabled()) {
- return redesignMenuItems({
- account,
- signedIn: !isMe && signedIn,
- permissions,
- intl,
- relationship,
- dispatch,
- });
- }
- return currentMenuItems({
+ return redesignMenuItems({
account,
- signedIn,
+ signedIn: !isMe && signedIn,
permissions,
intl,
relationship,
@@ -178,270 +166,6 @@ const messages = defineMessages({
},
});
-function currentMenuItems({
- account,
- signedIn,
- permissions,
- intl,
- relationship,
- dispatch,
-}: MenuItemsParams): MenuItem[] {
- const items: MenuItem[] = [];
- const isRemote = account.acct !== account.username;
-
- if (signedIn && !account.suspended) {
- items.push(
- {
- text: intl.formatMessage(messages.mention, {
- name: account.username,
- }),
- action: () => {
- dispatch(mentionCompose(account));
- },
- },
- {
- text: intl.formatMessage(messages.direct, {
- name: account.username,
- }),
- action: () => {
- dispatch(directCompose(account));
- },
- },
- null,
- );
- }
-
- if (isRemote) {
- items.push({
- text: intl.formatMessage(messages.openOriginalPage),
- href: account.url,
- });
-
- if (signedIn) {
- items.push(null);
- }
- }
-
- if (!signedIn) {
- return items;
- }
-
- if (relationship?.following) {
- // Timeline options
- if (!relationship.muting) {
- if (relationship.showing_reblogs) {
- items.push({
- text: intl.formatMessage(messages.hideReblogs, {
- name: account.username,
- }),
- action: () => {
- dispatch(followAccount(account.id, { reblogs: false }));
- },
- });
- } else {
- items.push({
- text: intl.formatMessage(messages.showReblogs, {
- name: account.username,
- }),
- action: () => {
- dispatch(followAccount(account.id, { reblogs: true }));
- },
- });
- }
-
- items.push(
- {
- text: intl.formatMessage(messages.languages),
- action: () => {
- dispatch(
- openModal({
- modalType: 'SUBSCRIBED_LANGUAGES',
- modalProps: {
- accountId: account.id,
- },
- }),
- );
- },
- },
- null,
- );
- }
-
- items.push(
- {
- text: intl.formatMessage(
- relationship.endorsed ? messages.unendorse : messages.endorse,
- ),
- action: () => {
- if (relationship.endorsed) {
- dispatch(unpinAccount(account.id));
- } else {
- dispatch(pinAccount(account.id));
- }
- },
- },
- {
- text: intl.formatMessage(messages.add_or_remove_from_list),
- action: () => {
- dispatch(
- openModal({
- modalType: 'LIST_ADDER',
- modalProps: {
- accountId: account.id,
- },
- }),
- );
- },
- },
- null,
- );
- }
-
- if (relationship?.followed_by) {
- const handleRemoveFromFollowers = () => {
- dispatch(
- openModal({
- modalType: 'CONFIRM',
- modalProps: {
- title: intl.formatMessage(messages.confirmRemoveFromFollowersTitle),
- message: intl.formatMessage(
- messages.confirmRemoveFromFollowersMessage,
- { name: {account.acct} },
- ),
- confirm: intl.formatMessage(
- messages.confirmRemoveFromFollowersButton,
- ),
- onConfirm: () => {
- void dispatch(
- removeAccountFromFollowers({ accountId: account.id }),
- );
- },
- },
- }),
- );
- };
-
- items.push({
- text: intl.formatMessage(messages.removeFromFollowers, {
- name: account.username,
- }),
- action: handleRemoveFromFollowers,
- dangerous: true,
- });
- }
-
- if (relationship?.muting) {
- items.push({
- text: intl.formatMessage(messages.unmute, {
- name: account.username,
- }),
- action: () => {
- dispatch(unmuteAccount(account.id));
- },
- });
- } else {
- items.push({
- text: intl.formatMessage(messages.mute, {
- name: account.username,
- }),
- action: () => {
- dispatch(initMuteModal(account));
- },
- dangerous: true,
- });
- }
-
- if (relationship?.blocking) {
- items.push({
- text: intl.formatMessage(messages.unblock, {
- name: account.username,
- }),
- action: () => {
- dispatch(unblockAccount(account.id));
- },
- });
- } else {
- items.push({
- text: intl.formatMessage(messages.block, {
- name: account.username,
- }),
- action: () => {
- dispatch(blockAccount(account.id));
- },
- dangerous: true,
- });
- }
-
- if (!account.suspended) {
- items.push({
- text: intl.formatMessage(messages.report, {
- name: account.username,
- }),
- action: () => {
- dispatch(initReport(account));
- },
- dangerous: true,
- });
- }
-
- const remoteDomain = isRemote ? account.acct.split('@')[1] : null;
- if (remoteDomain) {
- items.push(null);
-
- if (relationship?.domain_blocking) {
- items.push({
- text: intl.formatMessage(messages.unblockDomain, {
- domain: remoteDomain,
- }),
- action: () => {
- dispatch(unblockDomain(remoteDomain));
- },
- });
- } else {
- items.push({
- text: intl.formatMessage(messages.blockDomain, {
- domain: remoteDomain,
- }),
- action: () => {
- dispatch(initDomainBlockModal(account));
- },
- dangerous: true,
- });
- }
- }
-
- if (
- (permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS ||
- (isRemote &&
- (permissions & PERMISSION_MANAGE_FEDERATION) ===
- PERMISSION_MANAGE_FEDERATION)
- ) {
- items.push(null);
- if ((permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS) {
- items.push({
- text: intl.formatMessage(messages.admin_account, {
- name: account.username,
- }),
- href: `/admin/accounts/${account.id}`,
- });
- }
- if (
- isRemote &&
- (permissions & PERMISSION_MANAGE_FEDERATION) ===
- PERMISSION_MANAGE_FEDERATION
- ) {
- items.push({
- text: intl.formatMessage(messages.admin_domain, {
- domain: remoteDomain,
- }),
- href: `/admin/instances/${remoteDomain}`,
- });
- }
- }
-
- return items;
-}
-
const redesignMessages = defineMessages({
share: { id: 'account.menu.share', defaultMessage: 'Share…' },
copy: { id: 'account.menu.copy', defaultMessage: 'Copy link' },
diff --git a/app/javascript/mastodon/features/account_timeline/components/number_fields.tsx b/app/javascript/mastodon/features/account_timeline/components/number_fields.tsx
index 0fa805ac6b..385ba2d28a 100644
--- a/app/javascript/mastodon/features/account_timeline/components/number_fields.tsx
+++ b/app/javascript/mastodon/features/account_timeline/components/number_fields.tsx
@@ -3,13 +3,6 @@ import type { FC } from 'react';
import { FormattedMessage, useIntl } from 'react-intl';
-import { NavLink } from 'react-router-dom';
-
-import {
- FollowersCounter,
- FollowingCounter,
- StatusesCounter,
-} from '@/mastodon/components/counters';
import { FormattedDateWrapper } from '@/mastodon/components/formatted_date';
import {
NumberFields,
@@ -18,54 +11,9 @@ import {
import { ShortNumber } from '@/mastodon/components/short_number';
import { useAccount } from '@/mastodon/hooks/useAccount';
-import { isRedesignEnabled } from '../common';
-
-const LegacyNumberFields: FC<{ accountId: string }> = ({ accountId }) => {
- const intl = useIntl();
- const account = useAccount(accountId);
-
- if (!account) {
- return null;
- }
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-};
-
-const RedesignNumberFields: FC<{ accountId: string }> = ({ accountId }) => {
+export const AccountNumberFields: FC<{ accountId: string }> = ({
+ accountId,
+}) => {
const intl = useIntl();
const account = useAccount(accountId);
const createdThisYear = useMemo(
@@ -125,7 +73,3 @@ const RedesignNumberFields: FC<{ accountId: string }> = ({ accountId }) => {
);
};
-
-export const AccountNumberFields = isRedesignEnabled()
- ? RedesignNumberFields
- : LegacyNumberFields;
diff --git a/app/javascript/mastodon/features/account_timeline/components/tabs.tsx b/app/javascript/mastodon/features/account_timeline/components/tabs.tsx
index 5febb8eaf8..021005d744 100644
--- a/app/javascript/mastodon/features/account_timeline/components/tabs.tsx
+++ b/app/javascript/mastodon/features/account_timeline/components/tabs.tsx
@@ -8,40 +8,13 @@ import { NavLink } from 'react-router-dom';
import { useAccount } from '@/mastodon/hooks/useAccount';
import { useAccountId } from '@/mastodon/hooks/useAccountId';
-import { isRedesignEnabled } from '../common';
-
import classes from './redesign.module.scss';
-export const AccountTabs: FC<{ acct: string }> = ({ acct }) => {
- if (isRedesignEnabled()) {
- return ;
- }
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-};
-
const isActive: Required['isActive'] = (match, location) =>
match?.url === location.pathname ||
(!!match?.url && location.pathname.startsWith(`${match.url}/tagged/`));
-const RedesignTabs: FC = () => {
+export const AccountTabs: FC = () => {
const accountId = useAccountId();
const account = useAccount(accountId);
diff --git a/app/javascript/mastodon/features/account_timeline/v2/filters.tsx b/app/javascript/mastodon/features/account_timeline/v2/filters.tsx
index 28dcb5f5c4..2dc8254a20 100644
--- a/app/javascript/mastodon/features/account_timeline/v2/filters.tsx
+++ b/app/javascript/mastodon/features/account_timeline/v2/filters.tsx
@@ -23,7 +23,7 @@ export const AccountFilters: FC = () => {
}
return (
<>
-
+
diff --git a/app/javascript/mastodon/features/account_timeline/v2/pinned_statuses.tsx b/app/javascript/mastodon/features/account_timeline/v2/pinned_statuses.tsx
index 694c107f3a..88503389c9 100644
--- a/app/javascript/mastodon/features/account_timeline/v2/pinned_statuses.tsx
+++ b/app/javascript/mastodon/features/account_timeline/v2/pinned_statuses.tsx
@@ -18,7 +18,6 @@ import type { StatusHeaderRenderFn } from '@/mastodon/components/status/header';
import { selectTimelineByKey } from '@/mastodon/selectors/timelines';
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
-import { isRedesignEnabled } from '../common';
import { PinnedBadge } from '../components/badges';
import { useAccountContext } from './context';
@@ -88,10 +87,6 @@ export const renderPinnedStatusHeader: StatusHeaderRenderFn = ({
export const PinnedShowAllButton: FC = () => {
const { onShowAllPinned } = useAccountContext();
- if (!isRedesignEnabled()) {
- return null;
- }
-
return (
,
-
- )
- } else {
- // If profile editing is not enabled, redirect to the home timeline as the current editing pages are outside React Router.
- profileRedesignRoutes.push(
- ,
- ,
- );
- }
-
return (
@@ -242,7 +227,8 @@ class SwitchingColumnsArea extends PureComponent {
- {...profileRedesignRoutes}
+
+
diff --git a/app/javascript/mastodon/features/ui/util/async-components.js b/app/javascript/mastodon/features/ui/util/async-components.js
index d6c0f70c70..f976604a4e 100644
--- a/app/javascript/mastodon/features/ui/util/async-components.js
+++ b/app/javascript/mastodon/features/ui/util/async-components.js
@@ -1,5 +1,3 @@
-import { isServerFeatureEnabled } from '@/mastodon/utils/environment';
-
export function EmojiPicker () {
return import('../../emoji/emoji_picker');
}
@@ -79,10 +77,7 @@ export function PinnedStatuses () {
}
export function AccountTimeline () {
- if (isServerFeatureEnabled('profile_redesign')) {
- return import('../../account_timeline/v2');
- }
- return import('../../account_timeline');
+ return import('../../account_timeline/v2');
}
export function AccountGallery () {
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json
index 19fc3c3efe..daf7d28f91 100644
--- a/app/javascript/mastodon/locales/en.json
+++ b/app/javascript/mastodon/locales/en.json
@@ -122,7 +122,6 @@
"account.note.title": "Personal note (visible only to you)",
"account.open_original_page": "Open original page",
"account.posts": "Posts",
- "account.posts_with_replies": "Posts and replies",
"account.remove_from_followers": "Remove {name} from followers",
"account.report": "Report @{name}",
"account.requested_follow": "{name} has requested to follow you",
diff --git a/app/javascript/mastodon/utils/environment.ts b/app/javascript/mastodon/utils/environment.ts
index 5f736fa80c..ded0fe05bb 100644
--- a/app/javascript/mastodon/utils/environment.ts
+++ b/app/javascript/mastodon/utils/environment.ts
@@ -12,7 +12,7 @@ export function isProduction() {
else return import.meta.env.PROD;
}
-export type ServerFeatures = 'fasp' | 'collections' | 'profile_redesign';
+export type ServerFeatures = 'fasp' | 'collections';
export function isServerFeatureEnabled(feature: ServerFeatures) {
return initialState?.features.includes(feature) ?? false;
diff --git a/spec/system/account_notes_spec.rb b/spec/system/account_notes_spec.rb
deleted file mode 100644
index eaef248347..0000000000
--- a/spec/system/account_notes_spec.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-RSpec.describe 'Account notes', :inline_jobs, :js, :streaming do
- include ProfileStories
-
- let(:email) { 'test@example.com' }
- let(:password) { 'password' }
- let(:confirmed_at) { Time.zone.now }
- let(:finished_onboarding) { true }
-
- let!(:other_account) { Fabricate(:account) }
- let(:note_text) { 'This is a personal note' }
-
- before { as_a_logged_in_user }
-
- it 'can be written and viewed' do
- visit_profile(other_account)
-
- fill_in frontend_translations('account_note.placeholder'), with: note_text
-
- # This is a bit awkward since there is no button to save the change
- # The easiest way is to send ctrl+enter ourselves
- find_field(class: 'account__header__account-note__content').send_keys [:control, :enter]
-
- expect(page)
- .to have_css('.account__header__account-note__content', text: note_text)
-
- # Navigate back and forth and ensure the comment is still here
- visit root_url
- visit_profile(other_account)
-
- expect(AccountNote.find_by(account: bob.account, target_account: other_account).comment)
- .to eq note_text
-
- expect(page)
- .to have_css('.account__header__account-note__content', text: note_text)
- end
-
- def visit_profile(account)
- visit short_account_path(account)
-
- expect(page)
- .to have_css('div.app-holder')
- .and have_css('form.compose-form')
- end
-end