Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ describe('Authentication', () => {

cy.get('#input_name').clear().type(`test${getRandomId()}`);

cy.get('#signup-body-card-form-check-terms-and-privacy').check();

cy.findByText('Create account').click();

// * Make sure account was created successfully and we are at the select team page
Expand Down Expand Up @@ -113,6 +115,8 @@ describe('Authentication', () => {

cy.get('#input_name').clear().type(`test${getRandomId()}`);

cy.get('#signup-body-card-form-check-terms-and-privacy').check();

cy.findByText('Create account').click();

// * Make sure account was not created successfully
Expand Down Expand Up @@ -146,6 +150,8 @@ describe('Authentication', () => {

cy.get('#input_name').clear().type(username);

cy.get('#signup-body-card-form-check-terms-and-privacy').check();

cy.findByText('Create account').click();

// * Make sure account was created successfully and we are on the team joining page
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,17 @@ describe('Authentication', () => {

cy.get('#input_password-input').clear().type('less');

cy.get('#signup-body-card-form-check-terms-and-privacy').check();

cy.findByText('Create account').click();

// * Assert the error is what is expected;
cy.findByText('Your password must be 7-72 characters long.').should('be.visible');

cy.get('#input_password-input').clear().type('greaterthan7');

cy.get('#signup-body-card-form-check-terms-and-privacy').check();

cy.findByText('Create account').click();

// * Assert that we are not shown an MFA screen and instead a Teams You Can join page
Expand Down Expand Up @@ -112,6 +116,8 @@ describe('Authentication', () => {

cy.get('#input_name').clear().type(`BestUsernameInTheWorld${getRandomId()}`);

cy.get('#signup-body-card-form-check-terms-and-privacy').check();

['NOLOWERCASE123!', 'noupppercase123!', 'NoNumber!', 'NoSymbol123'].forEach((option) => {
cy.get('#input_password-input').clear().type(option);
cy.findByText('Create account').click();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ describe('Authentication', () => {

cy.get('#input_password-input').type('Test123456!');

cy.get('#signup-body-card-form-check-terms-and-privacy').check();

['1user', 'te', 'user#1', 'user!1'].forEach((option) => {
cy.get('#input_name').clear().type(option);
cy.findByText('Create account').click();
Expand Down Expand Up @@ -183,6 +185,8 @@ describe('Authentication', () => {

cy.get('#input_name').clear().type(`Test${getRandomId()}`);

cy.get('#signup-body-card-form-check-terms-and-privacy').check();

cy.findByText('Create account').click();

// * Make sure account was created successfully and we are on the team joining page
Expand Down Expand Up @@ -245,6 +249,8 @@ describe('Authentication', () => {

cy.get('#input_name').clear().type(`Test${getRandomId()}`);

cy.get('#signup-body-card-form-check-terms-and-privacy').check();

cy.findByText('Create account').click();

// * Make sure account was not created successfully
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ describe('Authentication', () => {

cy.get('#input_name').clear().type(`Test${getRandomId()}`);

cy.get('#signup-body-card-form-check-terms-and-privacy').check();

cy.findByText('Create account').click();

// * Make sure account was not created successfully
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ function signupWithEmail(name, pw) {
// # Type 'unique1pw' for password
cy.get('#input_password-input').type(pw);

// # Check the terms and privacy checkbox
cy.get('#signup-body-card-form-check-terms-and-privacy').check();

// # Click on Create Account button
cy.findByText('Create account').click();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ describe('Onboarding', () => {
cy.get('#input_email').should('be.focused').and('be.visible').type(email);
cy.get('#input_name').should('be.visible').type(username);
cy.get('#input_password-input').should('be.visible').type(password);
cy.get('#signup-body-card-form-check-terms-and-privacy').check();
cy.findByText('Create account').click();

cy.findByText('You’re almost done!').should('be.visible');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ describe('Onboarding', () => {
cy.get('#input_name').should('be.visible').type(username);
cy.get('#input_password-input').should('be.visible').type(password);

// # Check the terms and privacy checkbox
cy.get('#signup-body-card-form-check-terms-and-privacy').check();

// # Attempt to create an account by clicking on the 'Create account' button
cy.findByText('Create account').click();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,22 @@ describe('Signup Email page', () => {
cy.get('#input_password-input').should('be.visible').and('have.attr', 'placeholder', 'Choose a Password');
cy.findByText('Your password must be 5-72 characters long.').should('be.visible');

// * Check terms and privacy checkbox
cy.get('#signup-body-card-form-check-terms-and-privacy').should('be.visible').and('not.be.checked');
cy.findByText(/I agree to the/i).should('be.visible');

// * Check that submit button is disabled without accepting terms
cy.get('#saveSetting').scrollIntoView().should('be.visible');
cy.get('#saveSetting').should('contain', 'Create account');

// * Check newsletter subscription checkbox text and links
cy.findByText('I would like to receive Mattermost security updates via newsletter.').should('be.visible');
cy.findByText(/By subscribing, I consent to receive emails from Mattermost with product updates, promotions, and company news\./).should('be.visible');
cy.findByText(/I have read the/).parent().within(() => {
cy.findByRole('link', {name: 'Privacy Policy'}).should('be.visible').and('have.attr', 'href').and('include', 'mattermost.com/pl/privacy-policy/');
cy.findByRole('link', {name: 'unsubscribe'}).should('be.visible').and('have.attr', 'href').and('include', 'forms.mattermost.com/UnsubscribePage.html');
cy.get('#saveSetting').should('contain', 'Create account').and('be.disabled');

// * Check terms and privacy links (now part of checkbox label)
cy.get('label[for="signup-body-card-form-check-terms-and-privacy"]').within(() => {
cy.findByText('Acceptable Use Policy').should('be.visible').
and('have.attr', 'href').
and('include', config.SupportSettings.TermsOfServiceLink || TERMS_OF_SERVICE_LINK);
cy.findByText('Privacy Policy').should('be.visible').
and('have.attr', 'href').
and('include', config.SupportSettings.PrivacyPolicyLink || PRIVACY_POLICY_LINK);
});
});

Expand Down Expand Up @@ -116,4 +123,23 @@ describe('Signup Email page', () => {
cy.get('.footer-copyright').should('contain', `© ${currentYear} Mattermost Inc.`);
});
});

it('should enable submit button when terms checkbox is checked', () => {
// # Fill in valid form data
cy.get('#input_email').type('test@example.com');
cy.get('#input_name').type('testuser');
cy.get('#input_password-input').type('validPassword123');

// * Verify submit button is disabled
cy.get('#saveSetting').should('be.disabled');

// # Check the terms and privacy checkbox
cy.get('#signup-body-card-form-check-terms-and-privacy').check();

// * Verify checkbox is now checked
cy.get('#signup-body-card-form-check-terms-and-privacy').should('be.checked');

// * Verify submit button is now enabled
cy.get('#saveSetting').should('not.be.disabled');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ describe('Team Settings', () => {
cy.wait(TIMEOUTS.HALF_SEC);
cy.get('#input_password-input').type(password);

// # Check the terms and privacy checkbox
cy.get('#signup-body-card-form-check-terms-and-privacy').check();

// # Attempt to create an account by clicking on the 'Create Account' button
cy.findByText('Create account').click();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ describe('Team Settings', () => {
cy.get('#input_name').type(username);
cy.get('#input_password-input').type(password);

// # Attempt to create an account by clicking on the 'Create account' button
// # Check the terms and privacy checkbox
cy.get('#signup-body-card-form-check-terms-and-privacy').check();

// # Attempt to create an account by clicking on the 'Create Account' button
cy.findByText('Create account').click();

// * Assert that the expected error message from creating an account with an email not from the allowed email domain exists and is visible
Expand Down
23 changes: 10 additions & 13 deletions e2e-tests/playwright/lib/src/ui/pages/signup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@ export default class SignupPage {
readonly usernameInput;
readonly passwordInput;
readonly passwordToggleButton;
readonly newsLetterCheckBox;
readonly newsLetterPrivacyPolicyLink;
readonly newsLetterUnsubscribeLink;
readonly agreementTermsOfUseLink;
readonly agreementPrivacyPolicyLink;
readonly termsAndPrivacyCheckBox;
readonly termsAndPrivacyAcceptableUsePolicyLink;
readonly termsAndPrivacyPrivacyPolicyLink;
readonly createAccountButton;
readonly loginLink;
readonly emailError;
Expand Down Expand Up @@ -48,14 +46,12 @@ export default class SignupPage {
);
this.passwordError = page.locator('text=Must be 5-72 characters long.');

const newsletterBlock = page.locator('.check-input');
this.newsLetterCheckBox = newsletterBlock.getByRole('checkbox', {name: 'newsletter checkbox'});
this.newsLetterPrivacyPolicyLink = newsletterBlock.locator('text=Privacy Policy');
this.newsLetterUnsubscribeLink = newsletterBlock.locator('text=unsubscribe');

const agreementBlock = page.locator('.signup-body-card-agreement');
this.agreementTermsOfUseLink = agreementBlock.locator('text=Terms of Use');
this.agreementPrivacyPolicyLink = agreementBlock.locator('text=Privacy Policy');
const termsAndPrivacyBlock = page.locator('.check-input');
this.termsAndPrivacyCheckBox = termsAndPrivacyBlock.getByRole('checkbox', {
name: 'Terms and privacy policy checkbox',
});
this.termsAndPrivacyAcceptableUsePolicyLink = termsAndPrivacyBlock.locator('text=Acceptable Use Policy');
this.termsAndPrivacyPrivacyPolicyLink = termsAndPrivacyBlock.locator('text=Privacy Policy');

this.header = new components.MainHeader(page.locator('.hfroute-header'));
this.footer = new components.Footer(page.locator('.hfroute-footer'));
Expand All @@ -79,6 +75,7 @@ export default class SignupPage {
await this.emailInput.fill(user.email);
await this.usernameInput.fill(user.username);
await this.passwordInput.fill(user.password);
await this.termsAndPrivacyCheckBox.check();
await this.createAccountButton.click();

if (waitForRedirect) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,25 +43,21 @@ test('/signup_user_complete accessibility tab support', async ({pw}, testInfo) =
await pw.signupPage.passwordInput.press('Tab');
expect(await pw.signupPage.passwordToggleButton).toBeFocused();

// * Should move focus to newsletter checkbox after tab
// * Should move focus to terms and privacy checkbox after tab
await pw.signupPage.passwordToggleButton.press('Tab');
expect(await pw.signupPage.newsLetterCheckBox).toBeFocused();
expect(await pw.signupPage.termsAndPrivacyCheckBox).toBeFocused();

// * Should move focus to newsletter privacy policy link after tab
await pw.signupPage.newsLetterCheckBox.press('Tab');
expect(await pw.signupPage.newsLetterPrivacyPolicyLink).toBeFocused();
// * Should move focus to acceptable use policy link after tab
await pw.signupPage.termsAndPrivacyCheckBox.press('Tab');
expect(await pw.signupPage.termsAndPrivacyAcceptableUsePolicyLink).toBeFocused();

// * Should move focus to newsletter unsubscribe link after tab
await pw.signupPage.newsLetterPrivacyPolicyLink.press('Tab');
expect(await pw.signupPage.newsLetterUnsubscribeLink).toBeFocused();

// * Should move focus to agreement terms of use link after tab
await pw.signupPage.newsLetterUnsubscribeLink.press('Tab');
expect(await pw.signupPage.agreementTermsOfUseLink).toBeFocused();
// * Should move focus to privacy policy link after tab
await pw.signupPage.termsAndPrivacyAcceptableUsePolicyLink.press('Tab');
expect(await pw.signupPage.termsAndPrivacyPrivacyPolicyLink).toBeFocused();

// * Should move focus to agreement privacy policy link after tab
await pw.signupPage.agreementTermsOfUseLink.press('Tab');
expect(await pw.signupPage.agreementPrivacyPolicyLink).toBeFocused();
// * Should move focus to about link after tab (skips disabled create account button)
await pw.signupPage.termsAndPrivacyPrivacyPolicyLink.press('Tab');
expect(await pw.signupPage.footer.aboutLink).toBeFocused();

// * Should move focus to privacy policy link after tab
await pw.signupPage.footer.aboutLink.press('Tab');
Expand Down
2 changes: 1 addition & 1 deletion server/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ TEMPLATES_DIR=templates
PLUGIN_PACKAGES ?= $(PLUGIN_PACKAGES:)
PLUGIN_PACKAGES += mattermost-plugin-calls-v1.11.0
PLUGIN_PACKAGES += mattermost-plugin-github-v2.5.0
PLUGIN_PACKAGES += mattermost-plugin-gitlab-v1.11.0
PLUGIN_PACKAGES += mattermost-plugin-gitlab-v1.12.0
PLUGIN_PACKAGES += mattermost-plugin-jira-v4.5.1
PLUGIN_PACKAGES += mattermost-plugin-playbooks-v2.6.1
PLUGIN_PACKAGES += mattermost-plugin-servicenow-v2.4.0
Expand Down
33 changes: 0 additions & 33 deletions server/channels/api4/hosted_customer.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
package api4

import (
"encoding/json"
"io"
"net/http"

"github.com/mattermost/mattermost/server/public/model"
Expand All @@ -16,40 +14,9 @@ import (
func (api *API) InitHostedCustomer() {
// POST /api/v4/hosted_customer/available
api.BaseRoutes.HostedCustomer.Handle("/signup_available", api.APISessionRequired(handleSignupAvailable)).Methods(http.MethodGet)
api.BaseRoutes.HostedCustomer.Handle("/subscribe-newsletter", api.APIHandler(handleSubscribeToNewsletter)).Methods(http.MethodPost)
}

func handleSignupAvailable(c *Context, w http.ResponseWriter, r *http.Request) {
const where = "Api4.handleSignupAvailable"
c.Err = model.NewAppError(where, "api.server.hosted_signup_unavailable.error", nil, "", http.StatusNotImplemented)
}

func handleSubscribeToNewsletter(c *Context, w http.ResponseWriter, r *http.Request) {
const where = "Api4.handleSubscribeToNewsletter"
ensured := ensureCloudInterface(c, where)
if !ensured {
return
}

bodyBytes, err := io.ReadAll(r.Body)
if err != nil {
c.Err = model.NewAppError(where, "api.cloud.app_error", nil, "", http.StatusBadRequest).Wrap(err)
return
}

req := new(model.SubscribeNewsletterRequest)
err = json.Unmarshal(bodyBytes, req)
if err != nil {
c.Err = model.NewAppError(where, "api.cloud.request_error", nil, "", http.StatusBadRequest).Wrap(err)
return
}

req.ServerID = c.App.Srv().ServerId()

if err := c.App.Cloud().SubscribeToNewsletter("", req); err != nil {
c.Err = model.NewAppError(where, "api.server.cws.subscribe_to_newsletter.app_error", nil, "CWS Server failed to subscribe to newsletter.", http.StatusInternalServerError).Wrap(err)
return
}

ReturnStatusOK(w)
}
2 changes: 0 additions & 2 deletions server/einterfaces/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ type CloudInterface interface {

CheckCWSConnection(userId string) error

SubscribeToNewsletter(userID string, req *model.SubscribeNewsletterRequest) error

ApplyIPFilters(userID string, ranges *model.AllowedIPRanges) (*model.AllowedIPRanges, error)
GetIPFilters(userID string) (*model.AllowedIPRanges, error)
GetInstallation(userID string) (*model.Installation, error)
Expand Down
18 changes: 0 additions & 18 deletions server/einterfaces/mocks/CloudInterface.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions server/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -3158,10 +3158,6 @@
"id": "api.server.cws.needs_enterprise_edition",
"translation": "Service only available in Mattermost Enterprise edition"
},
{
"id": "api.server.cws.subscribe_to_newsletter.app_error",
"translation": "CWS Server failed to subscribe to newsletter."
},
{
"id": "api.server.hosted_signup_unavailable.error",
"translation": "Portal unavailable for self-hosted signup."
Expand Down
10 changes: 0 additions & 10 deletions server/public/model/hosted_customer.go

This file was deleted.

Loading