Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stable10] Add a notice to the share tooltip when there is no autocomplete #31729

Merged
merged 5 commits into from
Jun 12, 2018
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
2 changes: 1 addition & 1 deletion config/config.sample.php
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@
* the minimum characters have been entered. The search is case insensitive.
* e.g. entering "tom" will always return "Tom" if there is an exact match.
*/
'user.search_min_length' => 4,
'user.search_min_length' => 2,

/**
* Mail Parameters
Expand Down
10 changes: 10 additions & 0 deletions core/js/sharedialogview.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,16 @@
if (!view.configModel.get('allowGroupSharing')) {
title = t('core', 'No users found for {search}', {search: $('.shareWithField').val()});
}
var suggestStarts = OC.getCapabilities().files_sharing.search_min_length;
if (suggestStarts > $('.shareWithField').val().length) {
title = title + '. ' + n(
'core',
'Please enter at least {chars} character for suggestions',
'Please enter at least {chars} characters for suggestions',
suggestStarts,
{chars: suggestStarts}
);
}
$('.shareWithField').addClass('error')
.attr('data-original-title', title)
.tooltip('hide')
Expand Down
85 changes: 83 additions & 2 deletions core/js/tests/specs/sharedialogviewSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* ownCloud
*
* @author Vincent Petry
* @copyright Copyright (c) 2015 Vincent Petry <[email protected]>
* @copyright Copyright (c) 2018 Vincent Petry <[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
Expand Down Expand Up @@ -108,7 +108,7 @@ describe('OC.Share.ShareDialogView', function() {
capsSpec = sinon.stub(OC, 'getCapabilities');
capsSpec.returns({
'files_sharing': {
'search_min_length': 4
'search_min_length': 2
}
});
});
Expand Down Expand Up @@ -774,6 +774,87 @@ describe('OC.Share.ShareDialogView', function() {

addShareStub.restore();
});

it('displays message when not enough characters were typed in and the server returned no matches', function() {
dialog.render();
var $shareWithField = $('.shareWithField');
$shareWithField.val('b');
var response = sinon.stub();
dialog.autocompleteHandler({term: 'b'}, response);

var jsonData = JSON.stringify({
'ocs': {
'data': {
'exact': {
'users': [],
'groups': [],
'remotes': [],
},
'users': [],
'groups': [],
'remotes': []
},
'meta': {
'status': 'success',
'statuscode': 100
}
}
});
expect(fakeServer.requests.length).toEqual(1);
fakeServer.requests[0].respond(
200,
{'Content-Type': 'application/json'},
jsonData
);
expect(response.calledOnce).toEqual(true);
expect(response.getCall(0).args[0]).toBeUndefined();

expect($shareWithField.attr('data-original-title'))
.toEqual('No users found for b. Please enter at least 2 characters for suggestions');
});

it('does not display a message when not enough characters were typed in but the server returned an exact match', function() {
dialog.render();
var $shareWithField = $('.shareWithField');
var response = sinon.stub();
dialog.autocompleteHandler({term: '成'}, response);

var jsonData = JSON.stringify({
'ocs': {
'data': {
'exact' : {
'users' : [{
'label': '成 龙',
'value': {
'shareType': 0,
'shareWith': 'jackie_chan'
}
}],
'groups' : [],
'remotes': []
},
'users': [],
'groups': [],
'remotes': []
},
'meta': {
'status': 'success',
'statuscode': 100
}
}
});
expect(fakeServer.requests.length).toEqual(1);
fakeServer.requests[0].respond(
200,
{'Content-Type': 'application/json'},
jsonData
);
expect(response.calledOnce).toEqual(true);
expect(response.getCall(0).args[0]).toBeDefined();

expect($shareWithField.attr('data-original-title'))
.not.toContain('for suggestions');
});
});
describe('reshare permissions', function() {
it('does not show sharing options when sharing not allowed', function() {
Expand Down
2 changes: 1 addition & 1 deletion lib/public/Util/UserSearch.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,6 @@ public function isSearchable($pattern) {
* @since 10.0.8
*/
public function getSearchMinLength() {
return $this->config->getSystemValue('user.search_min_length', 4);
return $this->config->getSystemValue('user.search_min_length', 2);
}
}
34 changes: 28 additions & 6 deletions tests/acceptance/features/bootstrap/Provisioning.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,19 +82,41 @@ public function getCreatedGroups() {
}

/**
* returns an array of the real displayed names
* returns the display name of the current user
* if no "Display Name" is set the user-name is returned instead
*
* @return array
*/
public function getCurrentUserDisplayName() {
return $this->getUserDisplayName($this->getCurrentUser());
}

/**
* returns the display name of a user
* if no "Display Name" is set the user-name is returned instead
*
* @param string $username
*
* @return array
*/
public function getUserDisplayName($username) {
$displayName = $this->createdUsers[$username]['displayname'];
if (($displayName === null) || ($displayName === '')) {
$displayName = $username;
}
return $displayName;
}

/**
* returns an array of the display names, keyed by username
* if no "Display Name" is set the user-name is returned instead
*
* @return array
*/
public function getCreatedUserDisplayNames() {
$result = array();
foreach ($this->getCreatedUsers() as $username => $user) {
if (is_null($user['displayname'])) {
$result[] = $username;
} else {
$result[] = $user['displayname'];
}
$result[$username] = $this->getUserDisplayName($username);
}
return $result;
}
Expand Down
67 changes: 52 additions & 15 deletions tests/acceptance/features/bootstrap/WebUISharingContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,30 @@ public function userReactsToShareOfferedByUsingWebUI(
);
}
}

/**
* @Then only :userOrGroupName should be listed in the autocomplete list on the webUI
*
* @param string $userOrGroupName
*
* @return void
*/
public function onlyUserOrGroupNameShouldBeListedInTheAutocompleteList(
$userOrGroupName
) {
$autocompleteItems = $this->sharingDialog->getAutocompleteItemsList();
PHPUnit_Framework_Assert::assertCount(
1,
$autocompleteItems,
"expected 1 autocomplete item but there are " . \count($autocompleteItems)
);
PHPUnit_Framework_Assert::assertContains(
$userOrGroupName,
$autocompleteItems,
"'" . $userOrGroupName . "' not in autocomplete list"
);
}

/**
* @Then all users and groups that contain the string :requiredString in their name should be listed in the autocomplete list on the webUI
*
Expand Down Expand Up @@ -502,25 +526,38 @@ public function allUsersAndGroupsThatContainTheStringInTheirNameShouldBeListedIn
= $this->sharingDialog->groupStringsToMatchAutoComplete($notToBeListed);
}
$autocompleteItems = $this->sharingDialog->getAutocompleteItemsList();
$createdGroups = $this->sharingDialog->groupStringsToMatchAutoComplete(
// Keep separate arrays of users and groups, because the names can overlap
$createdElements = [];
$createdElements['groups'] = $this->sharingDialog->groupStringsToMatchAutoComplete(
$this->featureContext->getCreatedGroups()
);
$usersAndGroups = array_merge(
$this->featureContext->getCreatedUserDisplayNames(),
$createdGroups
);
foreach ($usersAndGroups as $expectedUserOrGroup) {
if (strpos($expectedUserOrGroup, $requiredString) !== false
&& $expectedUserOrGroup !== $notToBeListed
&& $expectedUserOrGroup !== $this->featureContext->getCurrentUser()
) {
PHPUnit_Framework_Assert::assertContains(
$expectedUserOrGroup,
$autocompleteItems,
"'" . $expectedUserOrGroup . "' not in autocomplete list"
);
$createdElements['users'] = $this->featureContext->getCreatedUserDisplayNames();
$numExpectedItems = 0;
foreach ($createdElements as $elementArray) {
foreach ($elementArray as $internalName => $displayName) {
// Matching should be case-insensitive on the internal or display name
if (((\stripos($internalName, $requiredString) !== false)
|| (\stripos($displayName, $requiredString) !== false))
&& ($displayName !== $notToBeListed)
&& ($displayName !== $this->featureContext->getCurrentUser())
&& ($displayName !== $this->featureContext->getCurrentUserDisplayName())
) {
PHPUnit_Framework_Assert::assertContains(
$displayName,
$autocompleteItems,
"'" . $displayName . "' not in autocomplete list"
);
$numExpectedItems = $numExpectedItems + 1;
}
}
}

PHPUnit_Framework_Assert::assertCount(
$numExpectedItems,
$autocompleteItems,
'expected ' . $numExpectedItems . ' in autocomplete list but there are ' . \count($autocompleteItems)
);

PHPUnit_Framework_Assert::assertNotContains(
$notToBeListed,
$this->sharingDialog->getAutocompleteItemsList()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,13 @@ public function getAutocompleteNodeElement() {
*
* @param string|array $groupNames
*
* @return array
* @return string|array
*/
public function groupStringsToMatchAutoComplete($groupNames) {
if (is_array($groupNames)) {
$autocompleteStrings = array();
foreach ($groupNames as $groupName => $groupData) {
$autocompleteStrings[] = $groupName . $this->suffixToIdentifyGroups;
$autocompleteStrings[$groupName] = $groupName . $this->suffixToIdentifyGroups;
}
} else {
$autocompleteStrings = $groupNames . $this->suffixToIdentifyGroups;
Expand Down
Loading