Skip to content

Commit

Permalink
test(sso): add test for email precheck, registration and welcome comp…
Browse files Browse the repository at this point in the history
…onent
  • Loading branch information
marc.sirisak committed Oct 2, 2024
1 parent b574d43 commit 390d1a6
Show file tree
Hide file tree
Showing 8 changed files with 423 additions and 10 deletions.
3 changes: 1 addition & 2 deletions config.preprod.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,7 @@
"feature_space": ["*"],
"feature_audio_call": ["i.tchap.gouv.fr", "e.tchap.gouv.fr"],
"feature_video_call": ["i.tchap.gouv.fr", "e.tchap.gouv.fr"],
"feature_screenshare_call": ["*"],
"feature_sso_flow": []
"feature_screenshare_call": ["*"]
},
"tchap_sso_flow": {
"isActive": false
Expand Down
3 changes: 1 addition & 2 deletions config.prod.json
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,7 @@
"feature_space": ["*"],
"feature_audio_call": ["*"],
"feature_video_call": ["agent.dinum.tchap.gouv.fr"],
"feature_screenshare_call": ["*"],
"feature_sso_flow": []
"feature_screenshare_call": ["*"]
},
"tchap_sso_flow": {
"isActive": false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export default class Welcome extends React.PureComponent<IProps> {
replaceMap["$logoUrl"] = logoUrl;
// :TCHAP: sso-agentconnect-flow - pageUrl = "welcome.html";
pageUrl = TchapUIFeature.isSSOFlowActive() ? "welcome_sso.html" : "welcome.html";
// end :TCHAP:
}

return (
Expand Down
5 changes: 4 additions & 1 deletion patches/subtree-modifications.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@
"sso-agentconnect-flow": {
"issue": "https://github.com/tchapgouv/tchap-web-v4/issues/386",
"files": [
"src/components/structures/MatrixChat.tsx"
"src/components/structures/MatrixChat.tsx",
"src/components/structures/auth/Registration.tsx",
"src/components/structures/auth/Login.tsx",
"src/components/views/auth/Welcome.tsx"
]
}
}
7 changes: 2 additions & 5 deletions src/tchap/components/views/sso/EmailVerificationPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,7 @@ export default function EmailVerificationPage() {
const isFieldCorrect = await emailFieldRef.current?.validate({ allowEmpty: false });

if (!isFieldCorrect) {
emailFieldRef.current?.focus();
emailFieldRef.current?.validate({ allowEmpty: false, focused: true });
setErrorText(_td("auth|sso|error_email"));
setLoading(false);
displayError(_td("auth|sso|error_email"));
return;
}

Expand Down Expand Up @@ -135,7 +132,7 @@ export default function EmailVerificationPage() {
/>
</div>
{errorText && <ErrorMessage message={errorText} />}
<button type="submit" className="tc_ButtonParent tc_ButtonProconnect tc_Button_iconPC">
<button type="submit" data-testid="proconnect-submit" className="tc_ButtonParent tc_ButtonProconnect tc_Button_iconPC">
{submitButtonChild}
</button>
<div className="mx_AuthBody_button-container tc_bottomButton">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
import React from "react";
import { render, cleanup, fireEvent, screen, act } from "@testing-library/react";
import { mocked, MockedObject } from "jest-mock";
import { MatrixClient } from "matrix-js-sdk/src/matrix";

import EmailVerificationPage from "~tchap-web/src/tchap/components/views/sso/EmailVerificationPage";
import TchapUtils from "~tchap-web/src/tchap/util/TchapUtils";
import { ValidatedServerConfig } from "~matrix-react-sdk/src/utils/ValidatedServerConfig";
import { mockPlatformPeg, stubClient } from "~matrix-react-sdk/test/test-utils";
import BasePlatform from "~matrix-react-sdk/src/BasePlatform";
import Login from "~matrix-react-sdk/src/Login";

jest.mock("~matrix-react-sdk/src/PlatformPeg");
jest.mock("~tchap-web/src/tchap/util/TchapUtils");
jest.mock("~matrix-react-sdk/src/Login");

describe("<EmailVerificationPage />", () => {
const userEmail = "[email protected]";
const defaultHsUrl = "https://matrix.agent1.fr";
const secondHsUrl = "https://matrix.agent2.fr";

const PlatformPegMocked: MockedObject<BasePlatform> = mockPlatformPeg();
const mockedClient: MatrixClient = stubClient();
const mockedTchapUtils = mocked(TchapUtils);

const mockLoginObject = (hs: string = defaultHsUrl) => {
const mockLoginObject = mocked(new Login(hs, hs, null, {}));
mockLoginObject.createTemporaryClient.mockImplementation(() => mockedClient);
return mockLoginObject;
};

const mockedFetchHomeserverFromEmail = (hs: string = defaultHsUrl) => {
mockedTchapUtils.fetchHomeserverForEmail.mockImplementation(() =>
Promise.resolve({ base_url: hs, server_name: hs }),
);
};

const mockedValidatedServerConfig = (withError: boolean = false, hsUrl: string = defaultHsUrl) => {
if (withError) {
mockedTchapUtils.makeValidatedServerConfig.mockImplementation(() => {
throw new Error();
});
} else {
mockedTchapUtils.makeValidatedServerConfig.mockImplementation(() =>
Promise.resolve({
hsUrl: defaultHsUrl,
hsName: "hs",
hsNameIsDifferent: false,
isUrl: "",
isDefault: true,
isNameResolvable: true,
warning: "",
} as ValidatedServerConfig),
);
}
};

const mockedPlatformPegStartSSO = (withError: boolean) => {
if (withError) {
jest.spyOn(PlatformPegMocked, "startSingleSignOn").mockImplementation(() => {
throw new Error();
});
} else {
jest.spyOn(PlatformPegMocked, "startSingleSignOn").mockImplementation(() => {});
}
};

const renderEmailVerificationPage = () => render(<EmailVerificationPage />);

beforeEach(() => {
mockLoginObject(defaultHsUrl);
});

afterEach(() => {
cleanup();
jest.restoreAllMocks();
});

it("returns error when empty email", async () => {
const { container } = renderEmailVerificationPage();

// Put text in email field
const emailField = screen.getByRole("textbox");
fireEvent.focus(emailField);
fireEvent.change(emailField, { target: { value: "" } });

// click on proconnect button
const proconnectButton = screen.getByTestId("proconnect-submit");
await act(async () => {
await fireEvent.click(proconnectButton);
});

// Error classes should not appear
expect(container.getElementsByClassName("mx_ErrorMessage").length).toBe(1);
});

it("returns inccorrect email", async () => {
const { container } = renderEmailVerificationPage();

// Put text in email field
const emailField = screen.getByRole("textbox");
fireEvent.focus(emailField);
fireEvent.change(emailField, { target: { value: "falseemail" } });

// click on proconnect button
const proconnectButton = screen.getByTestId("proconnect-submit");
await act(async () => {
await fireEvent.click(proconnectButton);
});

// Error classes should not appear
expect(container.getElementsByClassName("mx_ErrorMessage").length).toBe(1);
});

it("should throw error when homeserver catch an error", async () => {
const { container } = renderEmailVerificationPage();

// mock server returns an errorn, we dont need to mock the other implementation
// since the code should throw an error before accessing them
mockedValidatedServerConfig(true);

// Put text in email field
const emailField = screen.getByRole("textbox");
fireEvent.focus(emailField);
fireEvent.change(emailField, { target: { value: userEmail } });

// click on proconnect button
const proconnectButton = screen.getByTestId("proconnect-submit");
await act(async () => {
await fireEvent.click(proconnectButton);
});

// Error classes should not appear
expect(container.getElementsByClassName("mx_ErrorMessage").length).toBe(1);
});

it("should throw and error when connecting to proconnect error", async () => {
const { container } = renderEmailVerificationPage();

mockedValidatedServerConfig(false);
// mock platform page startsso error
mockedPlatformPegStartSSO(true);

// Put text in email field
const emailField = screen.getByRole("textbox");
fireEvent.focus(emailField);
fireEvent.change(emailField, { target: { value: userEmail } });

// click on proconnect button
const proconnectButton = screen.getByTestId("proconnect-submit");
await act(async () => {
await fireEvent.click(proconnectButton);
});

// Error classes should not appear
expect(container.getElementsByClassName("mx_ErrorMessage").length).toBe(1);
});

it("should start sso with correct homeserver 1", async () => {
renderEmailVerificationPage();

// Mock the implementation without error, what we want is to be sure they are called with the correct parameters
mockedFetchHomeserverFromEmail(defaultHsUrl);
mockedValidatedServerConfig(false, defaultHsUrl);
mockedPlatformPegStartSSO(false);

// Put text in email field
const emailField = screen.getByRole("textbox");
fireEvent.focus(emailField);
fireEvent.change(emailField, { target: { value: userEmail } });

// click on proconnect button
const proconnectButton = screen.getByTestId("proconnect-submit");
await act(async () => {
await fireEvent.click(proconnectButton);
});

expect(mockedTchapUtils.makeValidatedServerConfig).toHaveBeenCalledWith({
base_url: defaultHsUrl,
server_name: defaultHsUrl,
});
expect(PlatformPegMocked.startSingleSignOn).toHaveBeenCalledTimes(1);
});

it("should start sso with correct homeserver 2", async () => {
renderEmailVerificationPage();

// Mock the implementation without error, what we want is to be sure they are called with the correct parameters
mockedFetchHomeserverFromEmail(secondHsUrl);
mockedValidatedServerConfig(false, secondHsUrl);
mockedPlatformPegStartSSO(false);

// Put text in email field
const emailField = screen.getByRole("textbox");
fireEvent.focus(emailField);
fireEvent.change(emailField, { target: { value: userEmail } });

// click on proconnect button
const proconnectButton = screen.getByTestId("proconnect-submit");
await act(async () => {
await fireEvent.click(proconnectButton);
});

expect(mockedTchapUtils.makeValidatedServerConfig).toHaveBeenCalledWith({
base_url: secondHsUrl,
server_name: secondHsUrl,
});
expect(PlatformPegMocked.startSingleSignOn).toHaveBeenCalledTimes(1);
});
});
Loading

0 comments on commit 390d1a6

Please sign in to comment.