-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(redlist): add red list option in settings
- Loading branch information
marc.sirisak
committed
Oct 24, 2024
1 parent
a4867ec
commit 55f272d
Showing
8 changed files
with
516 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
src/tchap/components/views/settings/tabs/user/TchapRedListSettings.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import React, { useEffect, useState } from 'react'; | ||
import LabelledToggleSwitch from 'matrix-react-sdk/src/components/views/elements/LabelledToggleSwitch'; | ||
import SettingsSubsection from 'matrix-react-sdk/src/components/views/settings/shared/SettingsSubsection'; | ||
import { _t } from "matrix-react-sdk/src/languageHandler"; | ||
import TchapUtils from '../../../../../util/TchapUtils'; | ||
|
||
interface TchapRedListSettingsProps { | ||
} | ||
|
||
/** | ||
* A group of settings views to allow the user to set their profile information. | ||
*/ | ||
const TchapRedListSettings: React.FC<TchapRedListSettingsProps> = () => { | ||
|
||
const [isOnRedList, setIsOnRedList] = useState(false); | ||
const [loading, setLoading] = useState(false); | ||
|
||
useEffect(() => { | ||
const fetchInitialRedListValue = async () => { | ||
const initialValue = await TchapUtils.getUserRedListInfo(); | ||
console.log("initialRedListValue", initialValue); | ||
setIsOnRedList(initialValue); | ||
} | ||
fetchInitialRedListValue(); | ||
}, []); | ||
|
||
const _onRedlistOptionChange = async (checked: boolean) => { | ||
try { | ||
if (!loading) { | ||
setLoading(true) | ||
await TchapUtils.setUserRedListInfo(checked); | ||
setIsOnRedList(checked); | ||
} | ||
setLoading(false) | ||
} catch (err) { | ||
console.error("Error setting AccountData 'im.vector.hide_profile': " + err); | ||
setIsOnRedList(!checked); // return to initial state because of error | ||
setLoading(false) | ||
} | ||
} | ||
|
||
return <SettingsSubsection | ||
heading={_t("settings|general|redlist")} | ||
stretchContent> | ||
<LabelledToggleSwitch value={isOnRedList} | ||
onChange={(checked: boolean) => _onRedlistOptionChange(checked)} | ||
label={_t('settings|general|redlist_title')} | ||
disabled={loading} | ||
/> | ||
<p className="mx_SettingsTab_subsectionText"> | ||
({_t("settings|general|redlist_description")}) | ||
</p> | ||
</SettingsSubsection> | ||
} | ||
|
||
export default TchapRedListSettings; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
95 changes: 95 additions & 0 deletions
95
test/unit-tests/tchap/components/views/settings/AccountUserSettingsTab-test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import { render } from "@testing-library/react"; | ||
import React from "react"; | ||
import { MatrixClient } from "matrix-js-sdk/src/matrix"; | ||
import { logger } from "matrix-js-sdk/src/logger"; | ||
import { MockedObject } from "jest-mock"; | ||
import AccountUserSettingsTab from "matrix-react-sdk/src/components/views/settings/tabs/user/AccountUserSettingsTab"; | ||
import { SdkContextClass, SDKContext } from "matrix-react-sdk/src/contexts/SDKContext"; | ||
import SettingsStore from "matrix-react-sdk/src/settings/SettingsStore"; | ||
import { UIFeature } from "matrix-react-sdk/src/settings/UIFeature"; | ||
import { OidcClientStore } from "matrix-react-sdk/src/stores/oidc/OidcClientStore"; | ||
import MatrixClientContext from "matrix-react-sdk/src/contexts/MatrixClientContext"; | ||
import { | ||
getMockClientWithEventEmitter, | ||
mockClientMethodsServer, | ||
mockClientMethodsUser, | ||
mockPlatformPeg, | ||
} from "matrix-react-sdk/test/test-utils"; | ||
|
||
|
||
jest.mock( | ||
"matrix-react-sdk/src/components/views/settings/ChangePassword", | ||
() => | ||
({ onError, onFinished }: { onError: (e: Error) => void; onFinished: () => void }) => { | ||
return <button>Mock change password</button>; | ||
}, | ||
); | ||
|
||
describe("<AccountUserSettingsTab />", () => { | ||
const defaultProps = { | ||
closeSettingsFn: jest.fn(), | ||
}; | ||
|
||
const userId = "@alice:server.org"; | ||
let mockClient: MockedObject<MatrixClient>; | ||
|
||
let stores: SdkContextClass; | ||
|
||
const getComponent = () => ( | ||
<MatrixClientContext.Provider value={mockClient}> | ||
<SDKContext.Provider value={stores}> | ||
<AccountUserSettingsTab {...defaultProps} /> | ||
</SDKContext.Provider> | ||
</MatrixClientContext.Provider> | ||
); | ||
|
||
beforeEach(() => { | ||
jest.spyOn(SettingsStore, "getValue").mockReturnValue(false); | ||
mockPlatformPeg(); | ||
jest.clearAllMocks(); | ||
jest.spyOn(SettingsStore, "getValue").mockRestore(); | ||
jest.spyOn(logger, "error").mockRestore(); | ||
|
||
mockClient = getMockClientWithEventEmitter({ | ||
...mockClientMethodsUser(userId), | ||
...mockClientMethodsServer(), | ||
getCapabilities: jest.fn(), | ||
getThreePids: jest.fn(), | ||
getIdentityServerUrl: jest.fn(), | ||
deleteThreePid: jest.fn(), | ||
}); | ||
|
||
mockClient.getCapabilities.mockResolvedValue({}); | ||
mockClient.getThreePids.mockResolvedValue({ | ||
threepids: [], | ||
}); | ||
mockClient.deleteThreePid.mockResolvedValue({ | ||
id_server_unbind_result: "success", | ||
}); | ||
|
||
stores = new SdkContextClass(); | ||
stores.client = mockClient; | ||
// stub out this store completely to avoid mocking initialisation | ||
const mockOidcClientStore = {} as unknown as OidcClientStore; | ||
jest.spyOn(stores, "oidcClientStore", "get").mockReturnValue(mockOidcClientStore); | ||
jest.spyOn(SettingsStore, "getValue").mockImplementation( | ||
(settingName: string) => settingName === UIFeature.Deactivate, | ||
); | ||
}); | ||
|
||
afterEach(() => { | ||
jest.restoreAllMocks(); | ||
}); | ||
|
||
|
||
describe("common view snapshot", () => { | ||
|
||
it("should render section when account deactivation feature is enabled", () => { | ||
const { container } = render(getComponent()); | ||
|
||
expect(container).toMatchSnapshot(); | ||
}); | ||
}); | ||
|
||
|
||
}); |
109 changes: 109 additions & 0 deletions
109
test/unit-tests/tchap/components/views/settings/TchapRedListSettings-test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import { act, logRoles, render, screen, waitFor } from '@testing-library/react'; | ||
import React from 'react'; | ||
import { flushPromises, stubClient } from 'matrix-react-sdk/test/test-utils'; | ||
import { Mocked, mocked } from 'jest-mock'; | ||
|
||
import TchapRedListSettings from '~tchap-web/src/tchap/components/views/settings/tabs/user/TchapRedListSettings'; | ||
import { MatrixClient } from 'matrix-js-sdk/src/matrix'; | ||
import TchapUtils from '~tchap-web/src/tchap/util/TchapUtils'; | ||
import userEvent from '@testing-library/user-event'; | ||
|
||
jest.mock("~tchap-web/src/tchap/util/TchapUtils"); | ||
|
||
describe("TchapRedListSettings", () => { | ||
let client: Mocked<MatrixClient>; | ||
|
||
const renderComponent = () => render(<TchapRedListSettings />); | ||
|
||
beforeEach(() => { | ||
client = mocked(stubClient()); | ||
}); | ||
|
||
|
||
it("should red list should be activated when initial value is true", async () => { | ||
mocked(TchapUtils.getUserRedListInfo).mockResolvedValue(true); | ||
mocked(TchapUtils.setUserRedListInfo).mockResolvedValue(); | ||
|
||
renderComponent(); | ||
|
||
await flushPromises(); | ||
|
||
const switchElm = screen.getByRole("switch"); | ||
|
||
expect(switchElm).toHaveAttribute('aria-checked', "true"); | ||
|
||
}); | ||
|
||
it("should red list should be desactivated when initial value is false", async () => { | ||
mocked(TchapUtils.getUserRedListInfo).mockResolvedValue(false); | ||
mocked(TchapUtils.setUserRedListInfo).mockResolvedValue(); | ||
|
||
renderComponent(); | ||
|
||
await flushPromises(); | ||
|
||
const switchElm = screen.getByRole("switch"); | ||
|
||
expect(switchElm).toHaveAttribute('aria-checked', "false"); | ||
}); | ||
|
||
|
||
it("should remove user from red list", async () => { | ||
// initial value | ||
mocked(TchapUtils.getUserRedListInfo).mockResolvedValue(true); | ||
mocked(TchapUtils.setUserRedListInfo).mockResolvedValue(); | ||
|
||
renderComponent(); | ||
|
||
await flushPromises(); | ||
|
||
const switchElm = screen.getByRole("switch"); | ||
|
||
act(() => { | ||
userEvent.click(switchElm); | ||
}) | ||
|
||
waitFor(() => { | ||
expect(switchElm).toHaveAttribute('aria-checked', "false"); | ||
}) | ||
}); | ||
|
||
it("should put user on red list", async () => { | ||
// initial value | ||
mocked(TchapUtils.getUserRedListInfo).mockResolvedValue(false); | ||
mocked(TchapUtils.setUserRedListInfo).mockResolvedValue(); | ||
|
||
renderComponent(); | ||
|
||
await flushPromises(); | ||
|
||
const switchElm = screen.getByRole("switch"); | ||
|
||
act(() => { | ||
userEvent.click(switchElm); | ||
}) | ||
|
||
waitFor(() => { | ||
expect(switchElm).toHaveAttribute('aria-checked', "true"); | ||
}) | ||
}); | ||
|
||
it("should get back to initial value if throws an error", async () => { | ||
// initial value | ||
mocked(TchapUtils.getUserRedListInfo).mockResolvedValue(false); | ||
mocked(TchapUtils.setUserRedListInfo).mockRejectedValue(new Error("error test")); | ||
|
||
renderComponent(); | ||
|
||
await flushPromises(); | ||
|
||
const switchElm = screen.getByRole("switch"); | ||
|
||
act(() => { | ||
userEvent.click(switchElm); | ||
}) | ||
waitFor(() => { | ||
expect(switchElm).toHaveAttribute('aria-checked', "false"); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.