use ExternalLink components for external links (#10758)
* use ExternalLink components for external links * test * strict
This commit is contained in:
parent
42e6c9839c
commit
37b7dfe943
13 changed files with 281 additions and 47 deletions
|
@ -30,6 +30,7 @@ import AccessibleButton from "../views/elements/AccessibleButton";
|
||||||
import InlineSpinner from "../views/elements/InlineSpinner";
|
import InlineSpinner from "../views/elements/InlineSpinner";
|
||||||
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
import MatrixClientContext from "../../contexts/MatrixClientContext";
|
||||||
import { RoomStatusBarUnsentMessages } from "./RoomStatusBarUnsentMessages";
|
import { RoomStatusBarUnsentMessages } from "./RoomStatusBarUnsentMessages";
|
||||||
|
import ExternalLink from "../views/elements/ExternalLink";
|
||||||
|
|
||||||
const STATUS_BAR_HIDDEN = 0;
|
const STATUS_BAR_HIDDEN = 0;
|
||||||
const STATUS_BAR_EXPANDED = 1;
|
const STATUS_BAR_EXPANDED = 1;
|
||||||
|
@ -213,9 +214,9 @@ export default class RoomStatusBar extends React.PureComponent<IProps, IState> {
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
consentLink: (sub) => (
|
consentLink: (sub) => (
|
||||||
<a href={consentError!.data?.consent_uri} target="_blank" rel="noreferrer noopener">
|
<ExternalLink href={consentError!.data?.consent_uri} target="_blank" rel="noreferrer noopener">
|
||||||
{sub}
|
{sub}
|
||||||
</a>
|
</ExternalLink>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -77,6 +77,7 @@ import MainSplit from "./MainSplit";
|
||||||
import RightPanel from "./RightPanel";
|
import RightPanel from "./RightPanel";
|
||||||
import SpaceHierarchy, { showRoom } from "./SpaceHierarchy";
|
import SpaceHierarchy, { showRoom } from "./SpaceHierarchy";
|
||||||
import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
|
import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
|
||||||
|
import ExternalLink from "../views/elements/ExternalLink";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
space: Room;
|
space: Room;
|
||||||
|
@ -593,9 +594,9 @@ const SpaceSetupPrivateInvite: React.FC<{
|
||||||
{
|
{
|
||||||
b: (sub) => <b>{sub}</b>,
|
b: (sub) => <b>{sub}</b>,
|
||||||
link: () => (
|
link: () => (
|
||||||
<a href="https://app.element.io/" rel="noreferrer noopener" target="_blank">
|
<ExternalLink href="https://app.element.io/" rel="noreferrer noopener" target="_blank">
|
||||||
app.element.io
|
app.element.io
|
||||||
</a>
|
</ExternalLink>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import DialogButtons from "../elements/DialogButtons";
|
||||||
import Modal, { ComponentProps } from "../../../Modal";
|
import Modal, { ComponentProps } from "../../../Modal";
|
||||||
import SdkConfig from "../../../SdkConfig";
|
import SdkConfig from "../../../SdkConfig";
|
||||||
import { getPolicyUrl } from "../../../toasts/AnalyticsToast";
|
import { getPolicyUrl } from "../../../toasts/AnalyticsToast";
|
||||||
|
import ExternalLink from "../elements/ExternalLink";
|
||||||
|
|
||||||
export enum ButtonClicked {
|
export enum ButtonClicked {
|
||||||
Primary,
|
Primary,
|
||||||
|
@ -55,10 +56,10 @@ export const AnalyticsLearnMoreDialog: React.FC<IProps> = ({
|
||||||
{
|
{
|
||||||
PrivacyPolicyUrl: (sub) => {
|
PrivacyPolicyUrl: (sub) => {
|
||||||
return (
|
return (
|
||||||
<a href={privacyPolicyUrl} rel="norefferer noopener" target="_blank">
|
<ExternalLink href={privacyPolicyUrl} rel="norefferer noopener" target="_blank">
|
||||||
{sub}
|
{sub}
|
||||||
<span className="mx_AnalyticsPolicyLink" />
|
<span className="mx_AnalyticsPolicyLink" />
|
||||||
</a>
|
</ExternalLink>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -27,6 +27,7 @@ import InfoDialog from "./InfoDialog";
|
||||||
import { submitFeedback } from "../../../rageshake/submit-rageshake";
|
import { submitFeedback } from "../../../rageshake/submit-rageshake";
|
||||||
import { useStateToggle } from "../../../hooks/useStateToggle";
|
import { useStateToggle } from "../../../hooks/useStateToggle";
|
||||||
import StyledCheckbox from "../elements/StyledCheckbox";
|
import StyledCheckbox from "../elements/StyledCheckbox";
|
||||||
|
import ExternalLink from "../elements/ExternalLink";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
feature?: string;
|
feature?: string;
|
||||||
|
@ -130,16 +131,20 @@ const FeedbackDialog: React.FC<IProps> = (props: IProps) => {
|
||||||
{
|
{
|
||||||
existingIssuesLink: (sub) => {
|
existingIssuesLink: (sub) => {
|
||||||
return (
|
return (
|
||||||
<a target="_blank" rel="noreferrer noopener" href={existingIssuesUrl}>
|
<ExternalLink
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer noopener"
|
||||||
|
href={existingIssuesUrl}
|
||||||
|
>
|
||||||
{sub}
|
{sub}
|
||||||
</a>
|
</ExternalLink>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
newIssueLink: (sub) => {
|
newIssueLink: (sub) => {
|
||||||
return (
|
return (
|
||||||
<a target="_blank" rel="noreferrer noopener" href={newIssueUrl}>
|
<ExternalLink target="_blank" rel="noreferrer noopener" href={newIssueUrl}>
|
||||||
{sub}
|
{sub}
|
||||||
</a>
|
</ExternalLink>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -28,6 +28,7 @@ import StyledRadioButton from "../elements/StyledRadioButton";
|
||||||
import TextWithTooltip from "../elements/TextWithTooltip";
|
import TextWithTooltip from "../elements/TextWithTooltip";
|
||||||
import withValidation, { IFieldState, IValidationResult } from "../elements/Validation";
|
import withValidation, { IFieldState, IValidationResult } from "../elements/Validation";
|
||||||
import { ValidatedServerConfig } from "../../../utils/ValidatedServerConfig";
|
import { ValidatedServerConfig } from "../../../utils/ValidatedServerConfig";
|
||||||
|
import ExternalLink from "../elements/ExternalLink";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
title?: string;
|
title?: string;
|
||||||
|
@ -236,9 +237,13 @@ export default class ServerPickerDialog extends React.PureComponent<IProps, ISta
|
||||||
</AccessibleButton>
|
</AccessibleButton>
|
||||||
|
|
||||||
<h2>{_t("Learn more")}</h2>
|
<h2>{_t("Learn more")}</h2>
|
||||||
<a href="https://matrix.org/faq/#what-is-a-homeserver%3F" target="_blank" rel="noreferrer noopener">
|
<ExternalLink
|
||||||
|
href="https://matrix.org/faq/#what-is-a-homeserver%3F"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer noopener"
|
||||||
|
>
|
||||||
{_t("About homeservers")}
|
{_t("About homeservers")}
|
||||||
</a>
|
</ExternalLink>
|
||||||
</form>
|
</form>
|
||||||
</BaseDialog>
|
</BaseDialog>
|
||||||
);
|
);
|
||||||
|
|
|
@ -22,6 +22,7 @@ import { _t, pickBestLanguage } from "../../../languageHandler";
|
||||||
import DialogButtons from "../elements/DialogButtons";
|
import DialogButtons from "../elements/DialogButtons";
|
||||||
import BaseDialog from "./BaseDialog";
|
import BaseDialog from "./BaseDialog";
|
||||||
import { ServicePolicyPair } from "../../../Terms";
|
import { ServicePolicyPair } from "../../../Terms";
|
||||||
|
import ExternalLink from "../elements/ExternalLink";
|
||||||
|
|
||||||
interface ITermsCheckboxProps {
|
interface ITermsCheckboxProps {
|
||||||
onChange: (url: string, checked: boolean) => void;
|
onChange: (url: string, checked: boolean) => void;
|
||||||
|
@ -148,9 +149,9 @@ export default class TermsDialog extends React.PureComponent<ITermsDialogProps,
|
||||||
<td className="mx_TermsDialog_summary">{summary}</td>
|
<td className="mx_TermsDialog_summary">{summary}</td>
|
||||||
<td>
|
<td>
|
||||||
{termDoc[termsLang].name}
|
{termDoc[termsLang].name}
|
||||||
<a rel="noreferrer noopener" target="_blank" href={termDoc[termsLang].url}>
|
<ExternalLink rel="noreferrer noopener" target="_blank" href={termDoc[termsLang].url}>
|
||||||
<span className="mx_TermsDialog_link" />
|
<span className="mx_TermsDialog_link" />
|
||||||
</a>
|
</ExternalLink>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<TermsCheckbox
|
<TermsCheckbox
|
||||||
|
|
|
@ -26,6 +26,7 @@ import EventIndexPeg from "../../../indexing/EventIndexPeg";
|
||||||
import { SettingLevel } from "../../../settings/SettingLevel";
|
import { SettingLevel } from "../../../settings/SettingLevel";
|
||||||
import SeshatResetDialog from "../dialogs/SeshatResetDialog";
|
import SeshatResetDialog from "../dialogs/SeshatResetDialog";
|
||||||
import InlineSpinner from "../elements/InlineSpinner";
|
import InlineSpinner from "../elements/InlineSpinner";
|
||||||
|
import ExternalLink from "../elements/ExternalLink";
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
enabling: boolean;
|
enabling: boolean;
|
||||||
|
@ -197,9 +198,9 @@ export default class EventIndexPanel extends React.Component<{}, IState> {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
nativeLink: (sub) => (
|
nativeLink: (sub) => (
|
||||||
<a href={nativeLink} target="_blank" rel="noreferrer noopener">
|
<ExternalLink href={nativeLink} target="_blank" rel="noreferrer noopener">
|
||||||
{sub}
|
{sub}
|
||||||
</a>
|
</ExternalLink>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
)}
|
)}
|
||||||
|
@ -217,9 +218,13 @@ export default class EventIndexPanel extends React.Component<{}, IState> {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
desktopLink: (sub) => (
|
desktopLink: (sub) => (
|
||||||
<a href="https://element.io/get-started" target="_blank" rel="noreferrer noopener">
|
<ExternalLink
|
||||||
|
href="https://element.io/get-started"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer noopener"
|
||||||
|
>
|
||||||
{sub}
|
{sub}
|
||||||
</a>
|
</ExternalLink>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -31,6 +31,7 @@ import { Action } from "../../../../../dispatcher/actions";
|
||||||
import { UserTab } from "../../../dialogs/UserTab";
|
import { UserTab } from "../../../dialogs/UserTab";
|
||||||
import dis from "../../../../../dispatcher/dispatcher";
|
import dis from "../../../../../dispatcher/dispatcher";
|
||||||
import CopyableText from "../../../elements/CopyableText";
|
import CopyableText from "../../../elements/CopyableText";
|
||||||
|
import ExternalLink from "../../../elements/ExternalLink";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
closeSettingsFn: () => void;
|
closeSettingsFn: () => void;
|
||||||
|
@ -114,9 +115,9 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
|
||||||
for (const tocEntry of tocLinks) {
|
for (const tocEntry of tocLinks) {
|
||||||
legalLinks.push(
|
legalLinks.push(
|
||||||
<div key={tocEntry.url}>
|
<div key={tocEntry.url}>
|
||||||
<a href={tocEntry.url} rel="noreferrer noopener" target="_blank">
|
<ExternalLink href={tocEntry.url} rel="noreferrer noopener" target="_blank">
|
||||||
{tocEntry.text}
|
{tocEntry.text}
|
||||||
</a>
|
</ExternalLink>
|
||||||
</div>,
|
</div>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -143,27 +144,31 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
photo: (sub) => (
|
photo: (sub) => (
|
||||||
<a
|
<ExternalLink
|
||||||
href="themes/element/img/backgrounds/lake.jpg"
|
href="themes/element/img/backgrounds/lake.jpg"
|
||||||
rel="noreferrer noopener"
|
rel="noreferrer noopener"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
{sub}
|
{sub}
|
||||||
</a>
|
</ExternalLink>
|
||||||
),
|
),
|
||||||
author: (sub) => (
|
author: (sub) => (
|
||||||
<a href="https://www.flickr.com/golan" rel="noreferrer noopener" target="_blank">
|
<ExternalLink
|
||||||
|
href="https://www.flickr.com/golan"
|
||||||
|
rel="noreferrer noopener"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
{sub}
|
{sub}
|
||||||
</a>
|
</ExternalLink>
|
||||||
),
|
),
|
||||||
terms: (sub) => (
|
terms: (sub) => (
|
||||||
<a
|
<ExternalLink
|
||||||
href="https://creativecommons.org/licenses/by-sa/4.0/"
|
href="https://creativecommons.org/licenses/by-sa/4.0/"
|
||||||
rel="noreferrer noopener"
|
rel="noreferrer noopener"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
{sub}
|
{sub}
|
||||||
</a>
|
</ExternalLink>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
)}
|
)}
|
||||||
|
@ -175,27 +180,27 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
colr: (sub) => (
|
colr: (sub) => (
|
||||||
<a
|
<ExternalLink
|
||||||
href="https://github.com/matrix-org/twemoji-colr"
|
href="https://github.com/matrix-org/twemoji-colr"
|
||||||
rel="noreferrer noopener"
|
rel="noreferrer noopener"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
{sub}
|
{sub}
|
||||||
</a>
|
</ExternalLink>
|
||||||
),
|
),
|
||||||
author: (sub) => (
|
author: (sub) => (
|
||||||
<a href="https://mozilla.org" rel="noreferrer noopener" target="_blank">
|
<ExternalLink href="https://mozilla.org" rel="noreferrer noopener" target="_blank">
|
||||||
{sub}
|
{sub}
|
||||||
</a>
|
</ExternalLink>
|
||||||
),
|
),
|
||||||
terms: (sub) => (
|
terms: (sub) => (
|
||||||
<a
|
<ExternalLink
|
||||||
href="https://www.apache.org/licenses/LICENSE-2.0"
|
href="https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
rel="noreferrer noopener"
|
rel="noreferrer noopener"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
{sub}
|
{sub}
|
||||||
</a>
|
</ExternalLink>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
)}
|
)}
|
||||||
|
@ -208,23 +213,31 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
twemoji: (sub) => (
|
twemoji: (sub) => (
|
||||||
<a href="https://twemoji.twitter.com/" rel="noreferrer noopener" target="_blank">
|
<ExternalLink
|
||||||
|
href="https://twemoji.twitter.com/"
|
||||||
|
rel="noreferrer noopener"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
{sub}
|
{sub}
|
||||||
</a>
|
</ExternalLink>
|
||||||
),
|
),
|
||||||
author: (sub) => (
|
author: (sub) => (
|
||||||
<a href="https://twemoji.twitter.com/" rel="noreferrer noopener" target="_blank">
|
<ExternalLink
|
||||||
|
href="https://twemoji.twitter.com/"
|
||||||
|
rel="noreferrer noopener"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
{sub}
|
{sub}
|
||||||
</a>
|
</ExternalLink>
|
||||||
),
|
),
|
||||||
terms: (sub) => (
|
terms: (sub) => (
|
||||||
<a
|
<ExternalLink
|
||||||
href="https://creativecommons.org/licenses/by/4.0/"
|
href="https://creativecommons.org/licenses/by/4.0/"
|
||||||
rel="noreferrer noopener"
|
rel="noreferrer noopener"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
{sub}
|
{sub}
|
||||||
</a>
|
</ExternalLink>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
)}
|
)}
|
||||||
|
@ -256,9 +269,9 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
a: (sub) => (
|
a: (sub) => (
|
||||||
<a href="https://element.io/help" rel="noreferrer noopener" target="_blank">
|
<ExternalLink href="https://element.io/help" rel="noreferrer noopener" target="_blank">
|
||||||
{sub}
|
{sub}
|
||||||
</a>
|
</ExternalLink>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -273,9 +286,9 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
a: (sub) => (
|
a: (sub) => (
|
||||||
<a href="https://element.io/help" rel="noreferrer noopener" target="_blank">
|
<ExternalLink href="https://element.io/help" rel="noreferrer noopener" target="_blank">
|
||||||
{sub}
|
{sub}
|
||||||
</a>
|
</ExternalLink>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
)}
|
)}
|
||||||
|
@ -321,13 +334,13 @@ export default class HelpUserSettingsTab extends React.Component<IProps, IState>
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
a: (sub) => (
|
a: (sub) => (
|
||||||
<a
|
<ExternalLink
|
||||||
href="https://matrix.org/security-disclosure-policy/"
|
href="https://matrix.org/security-disclosure-policy/"
|
||||||
rel="noreferrer noopener"
|
rel="noreferrer noopener"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
{sub}
|
{sub}
|
||||||
</a>
|
</ExternalLink>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import { MatrixError, ConnectionError } from "matrix-js-sdk/src/http-api";
|
||||||
import { _t, _td, Tags, TranslatedString } from "../languageHandler";
|
import { _t, _td, Tags, TranslatedString } from "../languageHandler";
|
||||||
import SdkConfig from "../SdkConfig";
|
import SdkConfig from "../SdkConfig";
|
||||||
import { ValidatedServerConfig } from "./ValidatedServerConfig";
|
import { ValidatedServerConfig } from "./ValidatedServerConfig";
|
||||||
|
import ExternalLink from "../components/views/elements/ExternalLink";
|
||||||
|
|
||||||
export const resourceLimitStrings = {
|
export const resourceLimitStrings = {
|
||||||
"monthly_active_user": _td("This homeserver has hit its Monthly Active User limit."),
|
"monthly_active_user": _td("This homeserver has hit its Monthly Active User limit."),
|
||||||
|
@ -183,9 +184,9 @@ export function messageForConnectionError(
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
a: (sub) => (
|
a: (sub) => (
|
||||||
<a target="_blank" rel="noreferrer noopener" href={serverConfig.hsUrl}>
|
<ExternalLink target="_blank" rel="noreferrer noopener" href={serverConfig.hsUrl}>
|
||||||
{sub}
|
{sub}
|
||||||
</a>
|
</ExternalLink>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -14,11 +14,15 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { render } from "@testing-library/react";
|
||||||
import { MatrixClient, PendingEventOrdering } from "matrix-js-sdk/src/client";
|
import { MatrixClient, PendingEventOrdering } from "matrix-js-sdk/src/client";
|
||||||
import { EventStatus, MatrixEvent } from "matrix-js-sdk/src/models/event";
|
import { EventStatus, MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
import { Room } from "matrix-js-sdk/src/models/room";
|
||||||
|
import { MatrixError } from "matrix-js-sdk/src/http-api";
|
||||||
|
|
||||||
import { getUnsentMessages } from "../../../src/components/structures/RoomStatusBar";
|
import RoomStatusBar, { getUnsentMessages } from "../../../src/components/structures/RoomStatusBar";
|
||||||
|
import MatrixClientContext from "../../../src/contexts/MatrixClientContext";
|
||||||
import { MatrixClientPeg } from "../../../src/MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../src/MatrixClientPeg";
|
||||||
import { mkEvent, stubClient } from "../../test-utils/test-utils";
|
import { mkEvent, stubClient } from "../../test-utils/test-utils";
|
||||||
import { mkThread } from "../../test-utils/threads";
|
import { mkThread } from "../../test-utils/threads";
|
||||||
|
@ -34,6 +38,7 @@ describe("RoomStatusBar", () => {
|
||||||
|
|
||||||
stubClient();
|
stubClient();
|
||||||
client = MatrixClientPeg.get();
|
client = MatrixClientPeg.get();
|
||||||
|
client.getSyncStateData = jest.fn().mockReturnValue({});
|
||||||
room = new Room(ROOM_ID, client, client.getUserId()!, {
|
room = new Room(ROOM_ID, client, client.getUserId()!, {
|
||||||
pendingEventOrdering: PendingEventOrdering.Detached,
|
pendingEventOrdering: PendingEventOrdering.Detached,
|
||||||
});
|
});
|
||||||
|
@ -47,6 +52,13 @@ describe("RoomStatusBar", () => {
|
||||||
event.status = EventStatus.NOT_SENT;
|
event.status = EventStatus.NOT_SENT;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const getComponent = () =>
|
||||||
|
render(<RoomStatusBar room={room} />, {
|
||||||
|
wrapper: ({ children }) => (
|
||||||
|
<MatrixClientContext.Provider value={client}>{children}</MatrixClientContext.Provider>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
describe("getUnsentMessages", () => {
|
describe("getUnsentMessages", () => {
|
||||||
it("returns no unsent messages", () => {
|
it("returns no unsent messages", () => {
|
||||||
expect(getUnsentMessages(room)).toHaveLength(0);
|
expect(getUnsentMessages(room)).toHaveLength(0);
|
||||||
|
@ -88,4 +100,55 @@ describe("RoomStatusBar", () => {
|
||||||
expect(pendingEvents.every((ev) => ev.getId() !== event.getId())).toBe(true);
|
expect(pendingEvents.every((ev) => ev.getId() !== event.getId())).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("<RoomStatusBar />", () => {
|
||||||
|
it("should render nothing when room has no error or unsent messages", () => {
|
||||||
|
const { container } = getComponent();
|
||||||
|
expect(container.firstChild).toBe(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("unsent messages", () => {
|
||||||
|
it("should render warning when messages are unsent due to consent", () => {
|
||||||
|
const unsentMessage = mkEvent({
|
||||||
|
event: true,
|
||||||
|
type: "m.room.message",
|
||||||
|
user: "@user1:server",
|
||||||
|
room: "!room1:server",
|
||||||
|
content: {},
|
||||||
|
});
|
||||||
|
unsentMessage.status = EventStatus.NOT_SENT;
|
||||||
|
unsentMessage.error = new MatrixError({
|
||||||
|
errcode: "M_CONSENT_NOT_GIVEN",
|
||||||
|
data: { consent_uri: "terms.com" },
|
||||||
|
});
|
||||||
|
|
||||||
|
room.addPendingEvent(unsentMessage, "123");
|
||||||
|
|
||||||
|
const { container } = getComponent();
|
||||||
|
|
||||||
|
expect(container).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should render warning when messages are unsent due to resource limit", () => {
|
||||||
|
const unsentMessage = mkEvent({
|
||||||
|
event: true,
|
||||||
|
type: "m.room.message",
|
||||||
|
user: "@user1:server",
|
||||||
|
room: "!room1:server",
|
||||||
|
content: {},
|
||||||
|
});
|
||||||
|
unsentMessage.status = EventStatus.NOT_SENT;
|
||||||
|
unsentMessage.error = new MatrixError({
|
||||||
|
errcode: "M_RESOURCE_LIMIT_EXCEEDED",
|
||||||
|
data: { limit_type: "monthly_active_user" },
|
||||||
|
});
|
||||||
|
|
||||||
|
room.addPendingEvent(unsentMessage, "123");
|
||||||
|
|
||||||
|
const { container } = getComponent();
|
||||||
|
|
||||||
|
expect(container).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`RoomStatusBar <RoomStatusBar /> unsent messages should render warning when messages are unsent due to consent 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="mx_RoomStatusBar mx_RoomStatusBar_unsentMessages"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
role="alert"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_RoomStatusBar_unsentBadge"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_NotificationBadge mx_NotificationBadge_visible mx_NotificationBadge_highlighted mx_NotificationBadge_2char"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="mx_NotificationBadge_count"
|
||||||
|
>
|
||||||
|
!
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="mx_RoomStatusBar_unsentTitle"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
You can't send any messages until you review and agree to
|
||||||
|
<a
|
||||||
|
class="mx_ExternalLink"
|
||||||
|
rel="noreferrer noopener"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
our terms and conditions
|
||||||
|
<i
|
||||||
|
class="mx_ExternalLink_icon"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx_RoomStatusBar_unsentDescription"
|
||||||
|
>
|
||||||
|
You can select all or individual messages to retry or delete
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx_RoomStatusBar_unsentButtonBar"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_AccessibleButton mx_RoomStatusBar_unsentCancelAllBtn"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
Delete all
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx_AccessibleButton mx_RoomStatusBar_unsentRetry"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
Retry all
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`RoomStatusBar <RoomStatusBar /> unsent messages should render warning when messages are unsent due to resource limit 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="mx_RoomStatusBar mx_RoomStatusBar_unsentMessages"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
role="alert"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_RoomStatusBar_unsentBadge"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_NotificationBadge mx_NotificationBadge_visible mx_NotificationBadge_highlighted mx_NotificationBadge_2char"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="mx_NotificationBadge_count"
|
||||||
|
>
|
||||||
|
!
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="mx_RoomStatusBar_unsentTitle"
|
||||||
|
>
|
||||||
|
Your message wasn't sent because this homeserver has exceeded a resource limit. Please contact your service administrator to continue using the service.
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx_RoomStatusBar_unsentDescription"
|
||||||
|
>
|
||||||
|
You can select all or individual messages to retry or delete
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx_RoomStatusBar_unsentButtonBar"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="mx_AccessibleButton mx_RoomStatusBar_unsentCancelAllBtn"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
Delete all
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx_AccessibleButton mx_RoomStatusBar_unsentRetry"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
Retry all
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
|
@ -38,19 +38,27 @@ exports[`FeedbackDialog should respect feedback config 1`] = `
|
||||||
<span>
|
<span>
|
||||||
Please view
|
Please view
|
||||||
<a
|
<a
|
||||||
|
class="mx_ExternalLink"
|
||||||
href="http://existing?foo=bar"
|
href="http://existing?foo=bar"
|
||||||
rel="noreferrer noopener"
|
rel="noreferrer noopener"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
existing bugs on Github
|
existing bugs on Github
|
||||||
|
<i
|
||||||
|
class="mx_ExternalLink_icon"
|
||||||
|
/>
|
||||||
</a>
|
</a>
|
||||||
first. No match?
|
first. No match?
|
||||||
<a
|
<a
|
||||||
|
class="mx_ExternalLink"
|
||||||
href="https://new.issue.url?foo=bar"
|
href="https://new.issue.url?foo=bar"
|
||||||
rel="noreferrer noopener"
|
rel="noreferrer noopener"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
Start a new one
|
Start a new one
|
||||||
|
<i
|
||||||
|
class="mx_ExternalLink_icon"
|
||||||
|
/>
|
||||||
</a>
|
</a>
|
||||||
.
|
.
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -6,11 +6,15 @@ exports[`messageForConnectionError should match snapshot for ConnectionError 1`]
|
||||||
<span>
|
<span>
|
||||||
Can't connect to homeserver - please check your connectivity, ensure your
|
Can't connect to homeserver - please check your connectivity, ensure your
|
||||||
<a
|
<a
|
||||||
|
class="mx_ExternalLink"
|
||||||
href="hsUrl"
|
href="hsUrl"
|
||||||
rel="noreferrer noopener"
|
rel="noreferrer noopener"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
homeserver's SSL certificate
|
homeserver's SSL certificate
|
||||||
|
<i
|
||||||
|
class="mx_ExternalLink_icon"
|
||||||
|
/>
|
||||||
</a>
|
</a>
|
||||||
is trusted, and that a browser extension is not blocking requests.
|
is trusted, and that a browser extension is not blocking requests.
|
||||||
</span>
|
</span>
|
||||||
|
|
Loading…
Reference in a new issue