Skip to content
This repository has been archived by the owner on Sep 28, 2020. It is now read-only.

Commit

Permalink
Using an observer to handle menu updates to recalculate the dividers …
Browse files Browse the repository at this point in the history
…when change while is open (mattermost#3527)

* Using an observer to handle menu updates to recalculate the dividers when change while is open

* Fixing tests

* Adding cypress test to verify the redrawing of dividers on permissions changes

* Addressing PR comments
  • Loading branch information
jespino authored and skheria committed Oct 3, 2019
1 parent 2cbd1c4 commit a35fff5
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 0 deletions.
8 changes: 8 additions & 0 deletions components/widgets/menu/menu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,23 @@ export default class Menu extends React.PureComponent {
constructor(props) {
super(props);
this.node = React.createRef();
this.observer = new MutationObserver(this.hideUnneededDividers);
}

hideUnneededDividers = () => {
if (this.node.current === null) {
return;
}

this.observer.disconnect();
const children = Object.values(this.node.current.children).slice(0, this.node.current.children.length);

// Hiding dividers at beginning and duplicated ones
let prevWasDivider = false;
let isAtBeginning = true;
for (const child of children) {
if (child.classList.contains('menu-divider') || child.classList.contains('mobile-menu-divider')) {
child.style.display = 'block';
if (isAtBeginning || prevWasDivider) {
child.style.display = 'none';
}
Expand All @@ -65,6 +68,7 @@ export default class Menu extends React.PureComponent {
break;
}
}
this.observer.observe(this.node.current, {attributes: true, childList: true, subtree: true});
}

componentDidMount() {
Expand All @@ -75,6 +79,10 @@ export default class Menu extends React.PureComponent {
this.hideUnneededDividers();
}

componentWillUnmount() {
this.observer.disconnect();
}

// Used from DotMenu component to know in which direction show the menu
rect() {
if (this.node && this.node.current) {
Expand Down
9 changes: 9 additions & 0 deletions components/widgets/menu/menu.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import {shallow} from 'enzyme';

import Menu from './menu.jsx';

global.MutationObserver = class {
disconnect() {}
observe() {}
};

jest.mock('utils/utils', () => {
const original = require.requireActual('utils/utils');
return {
Expand Down Expand Up @@ -162,6 +167,7 @@ describe('components/Menu', () => {
/>
<div
class="menu-divider"
style="display: block;"
/>
<div
class="menu-divider"
Expand All @@ -172,6 +178,7 @@ describe('components/Menu', () => {
/>
<div
class="menu-divider"
style="display: block;"
/>
<div
class="menu-divider"
Expand Down Expand Up @@ -260,6 +267,7 @@ describe('components/Menu', () => {
/>
<div
class="mobile-menu-divider"
style="display: block;"
/>
<div
class="mobile-menu-divider"
Expand All @@ -270,6 +278,7 @@ describe('components/Menu', () => {
/>
<div
class="mobile-menu-divider"
style="display: block;"
/>
<div
class="mobile-menu-divider"
Expand Down
78 changes: 78 additions & 0 deletions e2e/cypress/integration/channel/channel_menu_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

// ***************************************************************
// - [#] indicates a test step (e.g. # Go to a page)
// - [*] indicates an assertion (e.g. * Check the title)
// - Use element ID when selecting an element. Create one if none.
// ***************************************************************

import users from '../../fixtures/users.json';

function demoteUserToGuest(user) {
// # Issue a Request to demote the user to guest
const baseUrl = Cypress.config('baseUrl');
cy.externalRequest({user: users.sysadmin, method: 'post', baseUrl, path: `users/${user.id}/demote`});
}

function promoteGuestToUser(user) {
// # Issue a Request to promote the guest to user
const baseUrl = Cypress.config('baseUrl');
cy.externalRequest({user: users.sysadmin, method: 'post', baseUrl, path: `users/${user.id}/promote`});
}

describe('Channel header menu', () => {
before(() => {
cy.apiUpdateConfig({
GuestAccountsSettings: {
Enable: true,
},
});
cy.loginAsNewUser().as('newuser');
});

it('MM-14490 show/hide properly menu dividers', () => {
let channel;

// # Go to "/"
cy.visit('/');

cy.getCurrentTeamId().then((teamId) => {
// # Create new test channel
cy.apiCreateChannel(teamId, 'channel-test', 'Channel Test').then((res) => {
channel = res.body;

// # Select channel on the left hand side
cy.get(`#sidebarItem_${channel.name}`).click();

// * Channel's display name should be visible at the top of the center pane
cy.get('#channelHeaderTitle').should('contain', channel.display_name);

// # Then click it to access the drop-down menu
cy.get('#channelHeaderTitle').click();

// * The dropdown menu of the channel header should be visible;
cy.get('#channelHeaderDropdownMenu').should('be.visible');

// * The dropdown menu of the channel header should have 3 dividers;
cy.get('#channelHeaderDropdownMenu').find('.menu-divider:visible').should('have.lengthOf', 3);

// # Demote the user to guest
cy.get('@newuser').then((user) => {
demoteUserToGuest(user);
});

// * The dropdown menu of the channel header should have 2 dividers because some options have disappeared;
cy.get('#channelHeaderDropdownMenu').find('.menu-divider:visible').should('have.lengthOf', 2);

// # Promote the guest to user again
cy.get('@newuser').then((user) => {
promoteGuestToUser(user);
});

// * The dropdown menu of the channel header should have 3 dividers again;
cy.get('#channelHeaderDropdownMenu').find('.menu-divider:visible').should('have.lengthOf', 3);
});
});
});
});

0 comments on commit a35fff5

Please sign in to comment.