first commit

This commit is contained in:
2018-04-23 21:08:22 +02:00
commit c68c1dd9b0
12994 changed files with 1500824 additions and 0 deletions
@@ -0,0 +1,22 @@
<?php
/**
* @file
* Contains database additions to drupal-8.bare.standard.php.gz for testing the
* upgrade path of https://www.drupal.org/node/2587275.
*/
use Drupal\Core\Database\Database;
$connection = Database::getConnection();
// Replace the user.mail configuration because the dump contains the right token
// already.
$connection->delete('config')->condition('name', 'user.mail')->execute();
$connection->insert('config')
->fields(['collection', 'name', 'data'])
->values([
'collection' => '',
'name' => 'user.mail',
'data' => "a:10:{s:14:\"cancel_confirm\";a:2:{s:4:\"body\";s:369:\"[user:name],\n\nA request to cancel your account has been made at [site:name].\n\nYou may now cancel your account on [site:url-brief] by clicking this link or copying and pasting it into your browser:\n\n[user:cancel-url]\n\nNOTE: The cancellation of your account is not reversible.\n\nThis link expires in one day and nothing will happen if it is not used.\n\n-- [site:name] team\";s:7:\"subject\";s:59:\"Account cancellation request for [user:name] at [site:name]\";}s:14:\"password_reset\";a:2:{s:4:\"body\";s:397:\"[user:name],\n\nA request to reset the password for your account has been made at [site:name].\n\nYou may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password. It expires after one day and nothing will happen if it's not used.\n\n-- [site:name] team\";s:7:\"subject\";s:60:\"Replacement login information for [user:name] at [site:name]\";}s:22:\"register_admin_created\";a:2:{s:4:\"body\";s:463:\"[user:name],\n\nA site administrator at [site:name] has created an account for you. You may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n-- [site:name] team\";s:7:\"subject\";s:58:\"An administrator created an account for you at [site:name]\";}s:29:\"register_no_approval_required\";a:2:{s:4:\"body\";s:437:\"[user:name],\n\nThank you for registering at [site:name]. You may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n-- [site:name] team\";s:7:\"subject\";s:46:\"Account details for [user:name] at [site:name]\";}s:25:\"register_pending_approval\";a:2:{s:4:\"body\";s:281:\"[user:name],\n\nThank you for registering at [site:name]. Your application for an account is currently pending approval. Once it has been approved, you will receive another email containing information about how to log in, set your password, and other details.\n\n\n-- [site:name] team\";s:7:\"subject\";s:71:\"Account details for [user:name] at [site:name] (pending admin approval)\";}s:31:\"register_pending_approval_admin\";a:2:{s:4:\"body\";s:56:\"[user:name] has applied for an account.\n\n[user:edit-url]\";s:7:\"subject\";s:71:\"Account details for [user:name] at [site:name] (pending admin approval)\";}s:16:\"status_activated\";a:2:{s:4:\"body\";s:446:\"[user:name],\n\nYour account at [site:name] has been activated.\n\nYou may now log in by clicking this link or copying and pasting it into your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n-- [site:name] team\";s:7:\"subject\";s:57:\"Account details for [user:name] at [site:name] (approved)\";}s:14:\"status_blocked\";a:2:{s:4:\"body\";s:89:\"[user:name],\n\nYour account on [site:account-name] has been blocked.\n\n-- [site:name] team\";s:7:\"subject\";s:56:\"Account details for [user:name] at [site:name] (blocked)\";}s:15:\"status_canceled\";a:2:{s:4:\"body\";s:82:\"[user:name],\n\nYour account on [site:name] has been canceled.\n\n-- [site:name] team\";s:7:\"subject\";s:57:\"Account details for [user:name] at [site:name] (canceled)\";}s:8:\"langcode\";s:2:\"en\";}"
])->execute();
@@ -0,0 +1,12 @@
name: 'User access tests'
type: module
description: 'Support module for user access testing.'
package: Testing
# version: VERSION
# core: 8.x
# Information added by Drupal.org packaging script on 2017-04-19
version: '8.3.1'
core: '8.x'
project: 'drupal'
datestamp: 1492622988
@@ -0,0 +1,24 @@
<?php
/**
* @file
* Dummy module implementing hook_user_access() to test if entity access is respected.
*/
use Drupal\Core\Access\AccessResult;
use Drupal\user\Entity\User;
/**
* Implements hook_ENTITY_TYPE_access() for entity type "user".
*/
function user_access_test_user_access(User $entity, $operation, $account) {
if ($entity->getUsername() == "no_edit" && $operation == "update") {
// Deny edit access.
return AccessResult::forbidden();
}
if ($entity->getUsername() == "no_delete" && $operation == "delete") {
// Deny delete access.
return AccessResult::forbidden();
}
return AccessResult::neutral();
}
@@ -0,0 +1,12 @@
name: 'User custom phpass params test'
type: module
description: 'Support module for testing custom phpass password algorithm parameters.'
package: Testing
# version: VERSION
# core: 8.x
# Information added by Drupal.org packaging script on 2017-04-19
version: '8.3.1'
core: '8.x'
project: 'drupal'
datestamp: 1492622988
@@ -0,0 +1,4 @@
services:
password:
class: Drupal\Core\Password\PhpassHashedPassword
arguments: [19]
@@ -0,0 +1,12 @@
name: 'User module form tests'
type: module
description: 'Support module for user form testing.'
package: Testing
# version: VERSION
# core: 8.x
# Information added by Drupal.org packaging script on 2017-04-19
version: '8.3.1'
core: '8.x'
project: 'drupal'
datestamp: 1492622988
@@ -0,0 +1,14 @@
<?php
/**
* @file
* Support module for user form testing.
*/
/**
* Implements hook_form_FORM_ID_alter() for user_cancel_form().
*/
function user_form_test_form_user_cancel_form_alter(&$form, &$form_state) {
$form['user_cancel_confirm']['#default_value'] = FALSE;
$form['access']['#value'] = \Drupal::currentUser()->hasPermission('cancel other accounts');
}
@@ -0,0 +1,2 @@
cancel other accounts:
title: 'Cancel other user accounts'
@@ -0,0 +1,7 @@
user_form_test.cancel:
path: '/user_form_test_cancel/{user}'
defaults:
_entity_form: 'user.cancel'
requirements:
_permission: 'cancel other accounts'
@@ -0,0 +1,12 @@
name: 'User module hooks tests'
type: module
description: 'Support module for user hooks testing.'
package: Testing
# version: VERSION
# core: 8.x
# Information added by Drupal.org packaging script on 2017-04-19
version: '8.3.1'
core: '8.x'
project: 'drupal'
datestamp: 1492622988
@@ -0,0 +1,22 @@
<?php
/**
* @file
* Support module for user hooks testing.
*/
use Drupal\Component\Utility\SafeMarkup;
/**
* Implements hook_user_format_name_alter().
*/
function user_hooks_test_user_format_name_alter(&$name, $account) {
if (\Drupal::state()->get('user_hooks_test_user_format_name_alter', FALSE)) {
if (\Drupal::state()->get('user_hooks_test_user_format_name_alter_safe', FALSE)) {
$name = SafeMarkup::format('<em>@uid</em>', ['@uid' => $account->id()]);
}
else {
$name = '<em>' . $account->id() . '</em>';
}
}
}
@@ -0,0 +1,34 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_access_perm
label: ''
module: views
description: ''
tag: ''
base_table: node_field_data
base_field: nid
core: '8'
display:
default:
display_options:
access:
type: perm
options:
perm: 'views_test_data test permission'
cache:
type: tag
exposed_form:
type: basic
pager:
type: full
style:
type: default
row:
type: fields
display_plugin: default
display_title: Master
id: default
position: 0
@@ -0,0 +1,45 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_access_role
label: ''
module: views
description: ''
tag: ''
base_table: views_test_data
base_field: nid
core: '8'
display:
default:
display_options:
fields:
id:
id: id
field: id
table: views_test_data
plugin_id: numeric
access:
type: role
cache:
type: tag
exposed_form:
type: basic
pager:
type: full
style:
type: default
row:
type: fields
display_plugin: default
display_title: Master
id: default
position: 0
page_1:
display_options:
path: test-role
display_plugin: page
display_title: Page
id: page_1
position: 1
@@ -0,0 +1,139 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_field_permission
label: null
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: uid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: null
display_options:
access:
type: none
cache:
type: tag
query:
type: views_query
exposed_form:
type: basic
pager:
type: full
style:
type: default
row:
type: fields
fields:
uid:
id: uid
table: users_field_data
field: uid
relationship: none
group_type: group
admin_label: ''
label: Uid
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
plugin_id: field
entity_type: user
entity_field: uid
permission:
id: permission
table: user__roles
field: permission
relationship: none
group_type: group
admin_label: ''
label: Permission
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
type: separator
separator: ', '
plugin_id: user_permissions
filters: { }
sorts: { }
@@ -0,0 +1,119 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_filter_current_user
label: Users
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: uid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: 0
display_options:
access:
type: none
cache:
type: tag
query:
type: views_query
options:
disable_sql_rewrite: false
distinct: false
replica: false
query_comment: ''
exposed_form:
type: basic
options:
submit_button: Filter
reset_button: false
reset_button_label: Reset
exposed_sorts_label: 'Sort by'
expose_sort_order: true
sort_asc_label: Asc
sort_desc_label: Desc
pager:
type: none
options:
offset: 0
style:
type: default
options:
row_class: ''
default_row_class: true
uses_fields: false
row:
type: fields
options:
separator: ''
hide_empty: false
default_field_elements: true
fields:
uid:
id: uid
table: users
field: uid
relationship: none
group_type: group
admin_label: ''
label: ''
exclude: false
filters:
uid_current:
id: uid_current
table: users
field: uid_current
relationship: none
group_type: group
admin_label: ''
operator: '='
value: '1'
group: 1
exposed: false
expose:
operator_id: ''
label: ''
description: ''
use_operator: false
operator: ''
identifier: ''
required: false
remember: false
multiple: false
remember_roles:
authenticated: authenticated
is_grouped: false
group_info:
label: ''
description: ''
identifier: ''
optional: true
widget: select
multiple: false
remember: false
default_group: All
default_group_multiple: { }
group_items: { }
entity_type: user
plugin_id: user_current
sorts: { }
header: { }
footer: { }
empty: { }
relationships: { }
arguments: { }
display_extenders: { }
cache_metadata:
max-age: -1
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- user
tags: { }
@@ -0,0 +1,142 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_filter_permission
label: null
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: uid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: null
display_options:
access:
type: none
cache:
type: tag
query:
type: views_query
exposed_form:
type: basic
pager:
type: full
style:
type: default
row:
type: fields
fields:
uid:
id: uid
table: users
field: uid
relationship: none
group_type: group
admin_label: ''
label: ''
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: false
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
link_to_user: false
plugin_id: user
entity_type: user
entity_field: uid
filters:
permission:
id: permission
table: user__roles
field: permission
relationship: none
group_type: group
admin_label: ''
operator: or
value:
'access user profiles': 'access user profiles'
group: 1
exposed: false
expose:
operator_id: '0'
label: ''
description: ''
use_operator: false
operator: ''
identifier: ''
required: false
remember: false
multiple: false
remember_roles:
authenticated: authenticated
reduce: false
is_grouped: false
group_info:
label: ''
description: ''
identifier: ''
optional: true
widget: select
multiple: false
remember: false
default_group: All
default_group_multiple: { }
group_items: { }
reduce_duplicates: true
plugin_id: user_permissions
sorts:
uid:
id: uid
table: users_field_data
field: uid
relationship: none
group_type: group
admin_label: ''
order: ASC
exposed: false
expose:
label: ''
plugin_id: standard
entity_type: user
entity_field: uid
@@ -0,0 +1,93 @@
langcode: en
status: true
dependencies:
module:
- node
- user
id: test_groupwise_user
label: test_groupwise_user
module: views
description: ''
tag: default
base_table: users_field_data
base_field: uid
core: 8.0-dev
display:
default:
display_options:
access:
options:
perm: 'access user profiles'
type: perm
cache:
type: tag
exposed_form:
type: basic
fields:
name:
field: name
id: name
table: users_field_data
plugin_id: field
type: user_name
entity_type: user
entity_field: name
nid:
field: nid
id: nid
relationship: uid_representative
table: node_field_data
plugin_id: node
entity_type: node
entity_field: nid
filters:
status:
expose:
operator: '0'
field: status
group: 1
id: status
table: users_field_data
value: '1'
plugin_id: boolean
entity_type: user
entity_field: status
pager:
options:
items_per_page: 10
type: full
query:
type: views_query
relationships:
uid_representative:
admin_label: 'Representative node'
field: uid_representative
group_type: group
id: uid_representative
relationship: none
required: false
subquery_namespace: ''
subquery_order: DESC
subquery_regenerate: true
subquery_sort: node.nid
subquery_view: ''
table: users_field_data
plugin_id: groupwise_max
row:
type: fields
sorts:
created:
field: uid
id: uid
order: ASC
table: users_field_data
plugin_id: field
entity_type: user
entity_field: uid
style:
type: default
title: test_groupwise_user
display_plugin: default
display_title: Master
id: default
position: 0
@@ -0,0 +1,63 @@
langcode: en
status: true
dependencies:
module:
- node
id: test_plugin_argument_default_current_user
label: ''
module: views
description: ''
tag: ''
base_table: node_field_data
base_field: nid
core: '8'
display:
default:
display_options:
access:
type: none
arguments:
'null':
default_action: default
default_argument_type: current_user
field: 'null'
id: 'null'
must_not_be: false
table: views
plugin_id: 'null'
cache:
type: tag
exposed_form:
type: basic
fields:
title:
alter:
alter_text: false
ellipsis: true
html: false
make_link: false
strip_tags: false
trim: false
word_boundary: true
empty_zero: false
field: title
hide_empty: false
id: title
table: node_field_data
plugin_id: field
entity_type: node
entity_field: title
pager:
options:
id: 0
items_per_page: 10
offset: 0
type: full
style:
type: default
row:
type: fields
display_plugin: default
display_title: Master
id: default
position: 0
@@ -0,0 +1,65 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_user_bulk_form
label: ''
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: uid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: null
display_options:
style:
type: table
row:
type: fields
fields:
user_bulk_form:
id: user_bulk_form
table: users
field: user_bulk_form
plugin_id: user_bulk_form
entity_type: user
name:
id: name
table: users_field_data
field: name
plugin_id: field
type: user_name
entity_type: user
entity_field: name
sorts:
uid:
id: uid
table: users_field_data
field: uid
order: ASC
plugin_id: user
entity_type: user
entity_field: uid
filters:
status:
id: status
table: users_field_data
field: status
operator: '='
value: '1'
plugin_id: boolean
entity_type: user
entity_field: status
page_1:
display_plugin: page
id: page_1
display_title: Page
position: null
display_options:
path: test-user-bulk-form
@@ -0,0 +1,243 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_user_bulk_form_combine_filter
label: test_user_bulk_form_combine_filter
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: uid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: 0
display_options:
access:
type: none
options: { }
cache:
type: tag
options: { }
query:
type: views_query
options:
disable_sql_rewrite: false
distinct: false
replica: false
query_comment: ''
query_tags: { }
exposed_form:
type: basic
options:
submit_button: Apply
reset_button: false
reset_button_label: Reset
exposed_sorts_label: 'Sort by'
expose_sort_order: true
sort_asc_label: Asc
sort_desc_label: Desc
pager:
type: full
options:
items_per_page: 10
offset: 0
id: 0
total_pages: null
expose:
items_per_page: false
items_per_page_label: 'Items per page'
items_per_page_options: '5, 10, 25, 50'
items_per_page_options_all: false
items_per_page_options_all_label: '- All -'
offset: false
offset_label: Offset
tags:
previous: ' Previous'
next: 'Next '
first: '« First'
last: 'Last »'
quantity: 9
style:
type: default
row:
type: fields
fields:
user_bulk_form:
id: user_bulk_form
table: users
field: user_bulk_form
relationship: none
group_type: group
admin_label: ''
label: ''
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: false
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
action_title: 'With selection'
include_exclude: exclude
selected_actions: { }
entity_type: user
plugin_id: user_bulk_form
name:
id: name
table: users_field_data
field: name
entity_type: user
entity_field: name
label: ''
alter:
alter_text: false
make_link: false
absolute: false
trim: false
word_boundary: false
ellipsis: false
strip_tags: false
html: false
hide_empty: false
empty_zero: false
plugin_id: field
relationship: none
group_type: group
admin_label: ''
exclude: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_alter_empty: true
click_sort_column: value
type: user_name
settings: { }
group_column: value
group_columns: { }
group_rows: true
delta_limit: 0
delta_offset: 0
delta_reversed: false
delta_first_last: false
multi_type: separator
separator: ', '
field_api_classes: false
filters:
combine:
id: combine
table: views
field: combine
relationship: none
group_type: group
admin_label: ''
operator: contains
value: dummy
group: 1
exposed: false
expose:
operator_id: ''
label: ''
description: ''
use_operator: false
operator: ''
identifier: ''
required: false
remember: false
multiple: false
remember_roles:
authenticated: authenticated
is_grouped: false
group_info:
label: ''
description: ''
identifier: ''
optional: true
widget: select
multiple: false
remember: false
default_group: All
default_group_multiple: { }
group_items: { }
fields:
user_bulk_form: user_bulk_form
name: name
plugin_id: combine
sorts: { }
title: test_user_bulk_form_combine_filter
header: { }
footer: { }
empty: { }
relationships: { }
arguments: { }
display_extenders: { }
filter_groups:
operator: AND
groups:
1: AND
cache_metadata:
max-age: 0
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- url.query_args
tags: { }
page_1:
display_plugin: page
id: page_1
display_title: Page
position: 1
display_options:
display_extenders: { }
path: test-user-bulk-form-combine-filter
cache_metadata:
max-age: 0
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- url.query_args
tags: { }
@@ -0,0 +1,60 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_user_changed
label: ''
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: nid
core: '8'
display:
default:
display_options:
access:
type: none
cache:
type: tag
exposed_form:
type: basic
pager:
type: full
row:
type: fields
style:
type: default
fields:
name:
id: uid
table: users_field_data
field: uid
entity_type: user
entity_field: uid
changed:
id: changed
table: users_field_data
field: changed
label: 'Updated date'
plugin_id: field
type: timestamp
settings:
date_format: html_date
custom_date_format: ''
timezone: ''
entity_type: user
entity_field: changed
filters: { }
display_plugin: default
display_title: Master
id: default
position: 0
page_1:
display_options:
path: test_user_changed
display_plugin: page
display_title: Page
id: page_1
position: 0
@@ -0,0 +1,131 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_user_data
label: test_user_data
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: uid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: null
display_options:
access:
type: perm
options:
perm: 'access user profiles'
cache:
type: tag
query:
type: views_query
exposed_form:
type: basic
pager:
type: full
style:
type: default
row:
type: fields
fields:
name:
id: name
table: users_field_data
field: name
label: ''
alter:
alter_text: false
make_link: false
absolute: false
trim: false
word_boundary: false
ellipsis: false
strip_tags: false
html: false
hide_empty: false
empty_zero: false
plugin_id: field
type: user_name
entity_type: user
entity_field: name
data:
id: data
table: users
field: data
relationship: none
group_type: group
admin_label: ''
label: Data
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
data_module: views_test_config
data_name: test_value_name
plugin_id: user_data
entity_type: user
filters:
uid:
value:
value: '2'
table: users_field_data
field: uid
id: uid
expose:
operator: '0'
group: 1
plugin_id: numeric
entity_type: user
entity_field: uid
sorts:
created:
id: created
table: users_field_data
field: created
order: DESC
plugin_id: date
entity_type: user
entity_field: created
@@ -0,0 +1,62 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_user_name
label: ''
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: nid
core: '8'
display:
default:
display_options:
access:
type: none
cache:
type: tag
exposed_form:
type: basic
pager:
type: full
row:
type: fields
style:
type: default
fields:
name:
id: uid
table: users_field_data
field: uid
entity_type: user
entity_field: uid
filters:
uid:
id: uid
table: users_field_data
field: uid
exposed: true
expose:
operator_id: uid_op
label: Name
operator: uid_op
identifier: uid
remember_roles:
authenticated: authenticated
anonymous: '0'
entity_type: user
entity_field: uid
display_plugin: default
display_title: Master
id: default
position: 0
page_1:
display_options:
path: test_user_name
display_plugin: page
display_title: Page
id: page_1
position: 0
@@ -0,0 +1,115 @@
langcode: en
status: true
dependencies:
module:
- node
- user
id: test_user_relationship
label: test_user_relationship
module: views
description: ''
tag: default
base_table: node_field_data
base_field: nid
core: '8'
display:
default:
display_options:
access:
type: perm
cache:
type: tag
exposed_form:
type: basic
fields:
name:
alter:
absolute: false
alter_text: false
ellipsis: true
external: false
html: false
make_link: false
nl2br: false
replace_spaces: false
strip_tags: false
trim: false
trim_whitespace: false
word_boundary: true
element_default_classes: true
element_label_colon: true
empty_zero: false
field: name
hide_alter_empty: false
hide_empty: false
id: name
table: users_field_data
plugin_id: field
type: user_name
entity_type: user
entity_field: name
title:
alter:
absolute: false
alter_text: false
ellipsis: false
html: false
make_link: false
strip_tags: false
trim: false
word_boundary: false
empty_zero: false
field: title
hide_empty: false
id: title
label: ''
table: node_field_data
plugin_id: field
entity_type: node
entity_field: title
uid:
alter:
absolute: false
alter_text: false
ellipsis: true
external: false
html: false
make_link: false
nl2br: false
replace_spaces: false
strip_tags: false
trim: false
trim_whitespace: false
word_boundary: true
element_default_classes: true
element_label_colon: true
empty_zero: false
field: uid
hide_alter_empty: false
hide_empty: false
id: uid
table: users_field_data
plugin_id: field
type: user
entity_type: user
entity_field: uid
pager:
options:
items_per_page: 10
type: full
query:
options:
query_comment: ''
type: views_query
title: test_user_relationship
style:
type: default
row:
type: fields
options:
default_field_elements: true
hide_empty: false
display_plugin: default
display_title: Master
id: default
position: 0
@@ -0,0 +1,220 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_user_roles_rid
label: test_user_roles_rid
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: uid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: 0
display_options:
access:
type: none
options: { }
cache:
type: tag
options: { }
query:
type: views_query
options:
disable_sql_rewrite: false
distinct: false
replica: false
query_comment: ''
query_tags: { }
exposed_form:
type: basic
options:
submit_button: Apply
reset_button: false
reset_button_label: Reset
exposed_sorts_label: 'Sort by'
expose_sort_order: true
sort_asc_label: Asc
sort_desc_label: Desc
pager:
type: full
options:
items_per_page: 10
offset: 0
id: 0
total_pages: null
expose:
items_per_page: false
items_per_page_label: 'Items per page'
items_per_page_options: '5, 10, 25, 50'
items_per_page_options_all: false
items_per_page_options_all_label: '- All -'
offset: false
offset_label: Offset
tags:
previous: ' Previous'
next: 'Next '
first: '« First'
last: 'Last »'
quantity: 9
style:
type: default
options:
grouping: { }
row_class: ''
default_row_class: true
uses_fields: false
row:
type: fields
options:
inline: { }
separator: ''
hide_empty: false
default_field_elements: true
fields:
name:
id: name
table: users_field_data
field: name
entity_type: user
entity_field: name
label: ''
alter:
alter_text: false
make_link: false
absolute: false
trim: false
word_boundary: false
ellipsis: false
strip_tags: false
html: false
hide_empty: false
empty_zero: false
plugin_id: field
relationship: none
group_type: group
admin_label: ''
exclude: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_alter_empty: true
click_sort_column: value
type: user_name
settings: { }
group_column: value
group_columns: { }
group_rows: true
delta_limit: 0
delta_offset: 0
delta_reversed: false
delta_first_last: false
multi_type: separator
separator: ', '
field_api_classes: false
filters:
status:
value: '1'
table: users_field_data
field: status
plugin_id: boolean
entity_type: user
entity_field: status
id: status
expose:
operator: ''
group: 1
sorts:
uid:
id: uid
table: users
field: uid
relationship: none
group_type: group
admin_label: ''
order: ASC
exposed: false
expose:
label: ''
entity_type: user
entity_field: uid
plugin_id: standard
header: { }
footer: { }
empty: { }
relationships: { }
arguments:
roles_target_id:
id: roles_target_id
table: user__roles
field: roles_target_id
relationship: none
group_type: group
admin_label: ''
default_action: empty
exception:
value: all
title_enable: false
title: All
title_enable: true
title: '{{ arguments.roles_target_id }}'
default_argument_type: fixed
default_argument_options:
argument: ''
default_argument_skip_url: false
summary_options:
base_path: ''
count: true
items_per_page: 25
override: false
summary:
sort_order: asc
number_of_records: 0
format: default_summary
specify_validation: false
validate:
type: none
fail: 'not found'
validate_options: { }
break_phrase: false
add_table: false
require_value: false
reduce_duplicates: false
plugin_id: user__roles_rid
display_extenders: { }
cache_metadata:
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- url
- url.query_args
- user.permissions
cacheable: false
page_1:
display_plugin: page
id: page_1
display_title: Page
position: 1
display_options:
display_extenders: { }
path: user_roles_rid_test
cache_metadata:
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- url
- url.query_args
- user.permissions
cacheable: false
@@ -0,0 +1,38 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_user_uid_argument
label: null
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: nid
core: '8'
display:
default:
display_options:
fields:
uid:
id: uid
table: users_field_data
field: uid
plugin_id: user
entity_type: user
entity_field: uid
arguments:
uid:
id: uid
table: users_field_data
field: uid
title_enable: true
title: '{{ arguments.uid }}'
plugin_id: user_uid
entity_type: user
entity_field: uid
display_plugin: default
display_title: Master
id: default
position: 0
@@ -0,0 +1,40 @@
langcode: en
status: true
dependencies: { }
id: test_view_argument_validate_user
label: ''
module: views
description: ''
tag: ''
base_table: node_field_data
base_field: nid
core: '8'
display:
default:
display_options:
access:
type: none
arguments:
'null':
default_argument_type: fixed
field: 'null'
id: 'null'
must_not_be: false
table: views
validate:
type: 'entity:user'
plugin_id: 'null'
cache:
type: tag
exposed_form:
type: basic
pager:
type: full
style:
type: default
row:
type: fields
display_plugin: default
display_title: Master
id: default
position: 0
@@ -0,0 +1,40 @@
langcode: en
status: true
dependencies: { }
id: test_view_argument_validate_username
label: ''
module: views
description: ''
tag: ''
base_table: node_field_data
base_field: nid
core: '8'
display:
default:
display_options:
access:
type: none
arguments:
'null':
default_argument_type: fixed
field: 'null'
id: 'null'
must_not_be: false
table: views
validate:
type: user_name
plugin_id: 'null'
cache:
type: tag
exposed_form:
type: basic
pager:
type: full
style:
type: default
row:
type: fields
display_plugin: default
display_title: Master
id: default
position: 0
@@ -0,0 +1,177 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_views_handler_field_role
label: test_views_handler_field_role
module: views
description: ''
tag: ''
base_table: users_field_data
base_field: uid
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: null
display_options:
access:
type: perm
options:
perm: 'access user profiles'
cache:
type: tag
query:
type: views_query
exposed_form:
type: basic
pager:
type: none
options:
items_per_page: null
style:
type: default
row:
type: fields
fields:
name:
id: name
table: users_field_data
field: name
relationship: none
group_type: group
admin_label: ''
label: Name
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
plugin_id: field
type: user_name
entity_type: user
entity_field: name
roles_target_id:
id: roles_target_id
table: user__roles
field: roles_target_id
relationship: none
group_type: group
admin_label: ''
label: Roles
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
type: separator
separator: ''
plugin_id: user_roles
filters:
status:
value: '1'
table: users_field_data
field: status
id: status
expose:
operator: '0'
group: 1
plugin_id: boolean
entity_type: user
entity_field: status
sorts:
uid:
id: uid
table: users_field_data
field: uid
relationship: none
group_type: group
admin_label: ''
order: ASC
exposed: false
expose:
label: ''
entity_type: user
entity_field: uid
plugin_id: standard
title: test_user_role
page_1:
display_plugin: page
id: page_1
display_title: Page
position: null
display_options:
path: test-views-handler-field-role
@@ -0,0 +1,63 @@
langcode: en
status: true
dependencies:
module:
- user
id: test_views_handler_field_user_name
label: test_views_handler_field_user_name
module: views
description: ''
tag: default
base_table: users_field_data
base_field: nid
core: '8'
display:
default:
display_options:
access:
type: none
cache:
type: tag
exposed_form:
type: basic
fields:
name:
alter:
absolute: false
alter_text: false
ellipsis: false
html: false
make_link: false
strip_tags: false
trim: false
word_boundary: false
empty_zero: false
field: name
hide_empty: false
id: name
label: ''
table: users_field_data
plugin_id: field
type: user_name
entity_type: user
entity_field: name
pager:
type: full
query:
options:
query_comment: ''
type: views_query
style:
type: default
row:
type: fields
sorts:
uid:
id: uid
table: users
field: uid
plugin_id: standard
display_plugin: default
display_title: Master
id: default
position: 0
@@ -0,0 +1,15 @@
name: 'User test views'
type: module
description: 'Provides default views for views user tests.'
package: Testing
# version: VERSION
# core: 8.x
dependencies:
- user
- views
# Information added by Drupal.org packaging script on 2017-04-19
version: '8.3.1'
core: '8.x'
project: 'drupal'
datestamp: 1492622988
@@ -0,0 +1,56 @@
<?php
namespace Drupal\Tests\user\Functional;
use Drupal\system\Tests\Entity\EntityWithUriCacheTagsTestBase;
use Drupal\user\Entity\Role;
use Drupal\user\Entity\User;
use Drupal\user\RoleInterface;
/**
* Tests the User entity's cache tags.
*
* @group user
*/
class UserCacheTagsTest extends EntityWithUriCacheTagsTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Give anonymous users permission to view user profiles, so that we can
// verify the cache tags of cached versions of user profile pages.
$user_role = Role::load(RoleInterface::ANONYMOUS_ID);
$user_role->grantPermission('access user profiles');
$user_role->save();
}
/**
* {@inheritdoc}
*/
protected function createEntity() {
// Create a "Llama" user.
$user = User::create([
'name' => 'Llama',
'status' => TRUE,
]);
$user->save();
return $user;
}
/**
* {@inheritdoc}
*/
protected function getAdditionalCacheTagsForEntityListing() {
return ['user:0', 'user:1'];
}
}
@@ -0,0 +1,45 @@
<?php
namespace Drupal\Tests\user\Functional;
use Drupal\Tests\BrowserTestBase;
/**
* Tests the create user administration page.
*
* @group user
*/
class UserCreateFailMailTest extends BrowserTestBase {
/**
* Modules to enable
*
* @var array
*/
public static $modules = ['system_mail_failure_test'];
/**
* Tests the create user administration page.
*/
public function testUserAdd() {
$user = $this->drupalCreateUser(['administer users']);
$this->drupalLogin($user);
// Replace the mail functionality with a fake, malfunctioning service.
$this->config('system.mail')->set('interface.default', 'test_php_mail_failure')->save();
// Create a user, but fail to send an email.
$name = $this->randomMachineName();
$edit = [
'name' => $name,
'mail' => $this->randomMachineName() . '@example.com',
'pass[pass1]' => $pass = $this->randomString(),
'pass[pass2]' => $pass,
'notify' => TRUE,
];
$this->drupalPostForm('admin/people/create', $edit, t('Create new account'));
$this->assertText(t('Unable to send email. Contact the site administrator if the problem persists.'));
$this->assertNoText(t('A welcome message with further instructions has been emailed to the new user @name.', ['@name' => $edit['name']]));
}
}
@@ -0,0 +1,55 @@
<?php
namespace Drupal\Tests\user\Functional;
use Drupal\Tests\BrowserTestBase;
use Drupal\user\Entity\User;
/**
* Tests account deleting of users.
*
* @group user
*/
class UserDeleteTest extends BrowserTestBase {
/**
* Test deleting multiple users.
*/
public function testUserDeleteMultiple() {
// Create a few users with permissions, so roles will be created.
$user_a = $this->drupalCreateUser(['access user profiles']);
$user_b = $this->drupalCreateUser(['access user profiles']);
$user_c = $this->drupalCreateUser(['access user profiles']);
$uids = [$user_a->id(), $user_b->id(), $user_c->id()];
// These users should have a role
$query = db_select('user__roles', 'r');
$roles_created = $query
->fields('r', ['entity_id'])
->condition('entity_id', $uids, 'IN')
->countQuery()
->execute()
->fetchField();
$this->assertTrue($roles_created > 0, 'Role assignments created for new users and deletion of role assignments can be tested');
// We should be able to load one of the users.
$this->assertTrue(User::load($user_a->id()), 'User is created and deletion of user can be tested');
// Delete the users.
user_delete_multiple($uids);
// Test if the roles assignments are deleted.
$query = db_select('user__roles', 'r');
$roles_after_deletion = $query
->fields('r', ['entity_id'])
->condition('entity_id', $uids, 'IN')
->countQuery()
->execute()
->fetchField();
$this->assertTrue($roles_after_deletion == 0, 'Role assignments deleted along with users');
// Test if the users are deleted, User::load() will return NULL.
$this->assertNull(User::load($user_a->id()), format_string('User with id @uid deleted.', ['@uid' => $user_a->id()]));
$this->assertNull(User::load($user_b->id()), format_string('User with id @uid deleted.', ['@uid' => $user_b->id()]));
$this->assertNull(User::load($user_c->id()), format_string('User with id @uid deleted.', ['@uid' => $user_c->id()]));
}
}
@@ -0,0 +1,43 @@
<?php
namespace Drupal\Tests\user\Functional;
use Drupal\Tests\BrowserTestBase;
/**
* Tests user edited own account can still log in.
*
* @group user
*/
class UserEditedOwnAccountTest extends BrowserTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['user_form_test'];
public function testUserEditedOwnAccount() {
// Change account setting 'Who can register accounts?' to Administrators
// only.
$this->config('user.settings')->set('register', USER_REGISTER_ADMINISTRATORS_ONLY)->save();
// Create a new user account and log in.
$account = $this->drupalCreateUser(['change own username']);
$this->drupalLogin($account);
// Change own username.
$edit = [];
$edit['name'] = $this->randomMachineName();
$this->drupalPostForm('user/' . $account->id() . '/edit', $edit, t('Save'));
// Log out.
$this->drupalLogout();
// Set the new name on the user account and attempt to log back in.
$account->name = $edit['name'];
$this->drupalLogin($account);
}
}
@@ -0,0 +1,64 @@
<?php
namespace Drupal\Tests\user\Functional;
use Drupal\Tests\BrowserTestBase;
use Drupal\user\Entity\User;
/**
* Tests specific parts of the user entity like the URI callback and the label
* callback.
*
* @group user
*/
class UserEntityCallbacksTest extends BrowserTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['user', 'user_hooks_test'];
/**
* An authenticated user to use for testing.
*
* @var \Drupal\user\UserInterface
*/
protected $account;
/**
* An anonymous user to use for testing.
*
* @var \Drupal\user\UserInterface
*/
protected $anonymous;
protected function setUp() {
parent::setUp();
$this->account = $this->drupalCreateUser();
$this->anonymous = User::create(['uid' => 0]);
}
/**
* Test label callback.
*/
public function testLabelCallback() {
$this->assertEqual($this->account->label(), $this->account->getUsername(), 'The username should be used as label');
// Setup a random anonymous name to be sure the name is used.
$name = $this->randomMachineName();
$this->config('user.settings')->set('anonymous', $name)->save();
$this->assertEqual($this->anonymous->label(), $name, 'The variable anonymous should be used for name of uid 0');
$this->assertEqual($this->anonymous->getDisplayName(), $name, 'The variable anonymous should be used for display name of uid 0');
$this->assertEqual($this->anonymous->getUserName(), '', 'The raw anonymous user name should be empty string');
// Set to test the altered username.
\Drupal::state()->set('user_hooks_test_user_format_name_alter', TRUE);
$this->assertEqual($this->account->getDisplayName(), '<em>' . $this->account->id() . '</em>', 'The user display name should be altered.');
$this->assertEqual($this->account->getUsername(), $this->account->name->value, 'The user name should not be altered.');
}
}
@@ -0,0 +1,67 @@
<?php
namespace Drupal\Tests\user\Functional;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Tests\BrowserTestBase;
/**
* Functional tests for a user's ability to change their default language.
*
* @group user
*/
class UserLanguageTest extends BrowserTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['user', 'language'];
/**
* Test if user can change their default language.
*/
public function testUserLanguageConfiguration() {
// User to add and remove language.
$admin_user = $this->drupalCreateUser(['administer languages', 'access administration pages']);
// User to change their default language.
$web_user = $this->drupalCreateUser();
// Add custom language.
$this->drupalLogin($admin_user);
// Code for the language.
$langcode = 'xx';
// The English name for the language.
$name = $this->randomMachineName(16);
$edit = [
'predefined_langcode' => 'custom',
'langcode' => $langcode,
'label' => $name,
'direction' => LanguageInterface::DIRECTION_LTR,
];
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language'));
$this->drupalLogout();
// Log in as normal user and edit account settings.
$this->drupalLogin($web_user);
$path = 'user/' . $web_user->id() . '/edit';
$this->drupalGet($path);
// Ensure language settings widget is available.
$this->assertText(t('Language'), 'Language selector available.');
// Ensure custom language is present.
$this->assertText($name, 'Language present on form.');
// Switch to our custom language.
$edit = [
'preferred_langcode' => $langcode,
];
$this->drupalPostForm($path, $edit, t('Save'));
// Ensure form was submitted successfully.
$this->assertText(t('The changes have been saved.'), 'Changes were saved.');
// Check if language was changed.
$this->assertOptionSelected('edit-preferred-langcode', $langcode, 'Default language successfully updated.');
$this->drupalLogout();
}
}
@@ -0,0 +1,429 @@
<?php
namespace Drupal\Tests\user\Functional;
use Drupal\Core\Flood\DatabaseBackend;
use Drupal\Core\Url;
use Drupal\Tests\BrowserTestBase;
use Drupal\user\Controller\UserAuthenticationController;
use GuzzleHttp\Cookie\CookieJar;
use Psr\Http\Message\ResponseInterface;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Drupal\hal\Encoder\JsonEncoder as HALJsonEncoder;
use Symfony\Component\Serializer\Serializer;
/**
* Tests login via direct HTTP.
*
* @group user
*/
class UserLoginHttpTest extends BrowserTestBase {
/**
* Modules to install.
*
* @var array
*/
public static $modules = ['hal'];
/**
* The cookie jar.
*
* @var \GuzzleHttp\Cookie\CookieJar
*/
protected $cookies;
/**
* The serializer.
*
* @var \Symfony\Component\Serializer\Serializer
*/
protected $serializer;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->cookies = new CookieJar();
$encoders = [new JsonEncoder(), new XmlEncoder(), new HALJsonEncoder()];
$this->serializer = new Serializer([], $encoders);
}
/**
* Executes a login HTTP request.
*
* @param string $name
* The username.
* @param string $pass
* The user password.
* @param string $format
* The format to use to make the request.
*
* @return \Psr\Http\Message\ResponseInterface The HTTP response.
* The HTTP response.
*/
protected function loginRequest($name, $pass, $format = 'json') {
$user_login_url = Url::fromRoute('user.login.http')
->setRouteParameter('_format', $format)
->setAbsolute();
$request_body = [];
if (isset($name)) {
$request_body['name'] = $name;
}
if (isset($pass)) {
$request_body['pass'] = $pass;
}
$result = \Drupal::httpClient()->post($user_login_url->toString(), [
'body' => $this->serializer->encode($request_body, $format),
'headers' => [
'Accept' => "application/$format",
],
'http_errors' => FALSE,
'cookies' => $this->cookies,
]);
return $result;
}
/**
* Tests user session life cycle.
*/
public function testLogin() {
$client = \Drupal::httpClient();
foreach ([FALSE, TRUE] as $serialization_enabled_option) {
if ($serialization_enabled_option) {
/** @var \Drupal\Core\Extension\ModuleInstaller $module_installer */
$module_installer = $this->container->get('module_installer');
$module_installer->install(['serialization']);
$formats = ['json', 'xml', 'hal_json'];
}
else {
// Without the serialization module only JSON is supported.
$formats = ['json'];
}
foreach ($formats as $format) {
// Create new user for each iteration to reset flood.
// Grant the user administer users permissions to they can see the
// 'roles' field.
$account = $this->drupalCreateUser(['administer users']);
$name = $account->getUsername();
$pass = $account->passRaw;
$login_status_url = $this->getLoginStatusUrlString($format);
$response = $client->get($login_status_url);
$this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_OUT);
// Flooded.
$this->config('user.flood')
->set('user_limit', 3)
->save();
$response = $this->loginRequest($name, 'wrong-pass', $format);
$this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format);
$response = $this->loginRequest($name, 'wrong-pass', $format);
$this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format);
$response = $this->loginRequest($name, 'wrong-pass', $format);
$this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format);
$response = $this->loginRequest($name, 'wrong-pass', $format);
$this->assertHttpResponseWithMessage($response, 403, 'Too many failed login attempts from your IP address. This IP address is temporarily blocked.', $format);
// After testing the flood control we can increase the limit.
$this->config('user.flood')
->set('user_limit', 100)
->save();
$response = $this->loginRequest(NULL, NULL, $format);
$this->assertHttpResponseWithMessage($response, 400, 'Missing credentials.', $format);
$response = $this->loginRequest(NULL, $pass, $format);
$this->assertHttpResponseWithMessage($response, 400, 'Missing credentials.name.', $format);
$response = $this->loginRequest($name, NULL, $format);
$this->assertHttpResponseWithMessage($response, 400, 'Missing credentials.pass.', $format);
// Blocked.
$account
->block()
->save();
$response = $this->loginRequest($name, $pass, $format);
$this->assertHttpResponseWithMessage($response, 400, 'The user has not been activated or is blocked.', $format);
$account
->activate()
->save();
$response = $this->loginRequest($name, 'garbage', $format);
$this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format);
$response = $this->loginRequest('garbage', $pass, $format);
$this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.', $format);
$response = $this->loginRequest($name, $pass, $format);
$this->assertEquals(200, $response->getStatusCode());
$result_data = $this->serializer->decode($response->getBody(), $format);
$this->assertEquals($name, $result_data['current_user']['name']);
$this->assertEquals($account->id(), $result_data['current_user']['uid']);
$this->assertEquals($account->getRoles(), $result_data['current_user']['roles']);
$logout_token = $result_data['logout_token'];
$response = $client->get($login_status_url, ['cookies' => $this->cookies]);
$this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_IN);
$response = $this->logoutRequest($format, $logout_token);
$this->assertEquals(204, $response->getStatusCode());
$response = $client->get($login_status_url, ['cookies' => $this->cookies]);
$this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_OUT);
$this->resetFlood();
}
}
}
/**
* Gets a value for a given key from the response.
*
* @param \Psr\Http\Message\ResponseInterface $response
* The response object.
* @param string $key
* The key for the value.
* @param string $format
* The encoded format.
*
* @return mixed
* The value for the key.
*/
protected function getResultValue(ResponseInterface $response, $key, $format) {
$decoded = $this->serializer->decode((string) $response->getBody(), $format);
if (is_array($decoded)) {
return $decoded[$key];
}
else {
return $decoded->{$key};
}
}
/**
* Resets all flood entries.
*/
protected function resetFlood() {
$this->container->get('database')->delete(DatabaseBackend::TABLE_NAME)->execute();
}
/**
* Tests the global login flood control.
*
* @see \Drupal\basic_auth\Tests\Authentication\BasicAuthTest::testGlobalLoginFloodControl
* @see \Drupal\user\Tests\UserLoginTest::testGlobalLoginFloodControl
*/
public function testGlobalLoginFloodControl() {
$this->config('user.flood')
->set('ip_limit', 2)
// Set a high per-user limit out so that it is not relevant in the test.
->set('user_limit', 4000)
->save();
$user = $this->drupalCreateUser([]);
$incorrect_user = clone $user;
$incorrect_user->passRaw .= 'incorrect';
// Try 2 failed logins.
for ($i = 0; $i < 2; $i++) {
$response = $this->loginRequest($incorrect_user->getUsername(), $incorrect_user->passRaw);
$this->assertEquals('400', $response->getStatusCode());
}
// IP limit has reached to its limit. Even valid user credentials will fail.
$response = $this->loginRequest($user->getUsername(), $user->passRaw);
$this->assertHttpResponseWithMessage($response, '403', 'Access is blocked because of IP based flood prevention.');
}
/**
* Checks a response for status code and body.
*
* @param \Psr\Http\Message\ResponseInterface $response
* The response object.
* @param int $expected_code
* The expected status code.
* @param mixed $expected_body
* The expected response body.
*/
protected function assertHttpResponse(ResponseInterface $response, $expected_code, $expected_body) {
$this->assertEquals($expected_code, $response->getStatusCode());
$this->assertEquals($expected_body, (string) $response->getBody());
}
/**
* Checks a response for status code and message.
*
* @param \Psr\Http\Message\ResponseInterface $response
* The response object.
* @param int $expected_code
* The expected status code.
* @param string $expected_message
* The expected message encoded in response.
* @param string $format
* The format that the response is encoded in.
*/
protected function assertHttpResponseWithMessage(ResponseInterface $response, $expected_code, $expected_message, $format = 'json') {
$this->assertEquals($expected_code, $response->getStatusCode());
$this->assertEquals($expected_message, $this->getResultValue($response, 'message', $format));
}
/**
* Test the per-user login flood control.
*
* @see \Drupal\user\Tests\UserLoginTest::testPerUserLoginFloodControl
* @see \Drupal\basic_auth\Tests\Authentication\BasicAuthTest::testPerUserLoginFloodControl
*/
public function testPerUserLoginFloodControl() {
foreach ([TRUE, FALSE] as $uid_only_setting) {
$this->config('user.flood')
// Set a high global limit out so that it is not relevant in the test.
->set('ip_limit', 4000)
->set('user_limit', 3)
->set('uid_only', $uid_only_setting)
->save();
$user1 = $this->drupalCreateUser([]);
$incorrect_user1 = clone $user1;
$incorrect_user1->passRaw .= 'incorrect';
$user2 = $this->drupalCreateUser([]);
// Try 2 failed logins.
for ($i = 0; $i < 2; $i++) {
$response = $this->loginRequest($incorrect_user1->getUsername(), $incorrect_user1->passRaw);
$this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.');
}
// A successful login will reset the per-user flood control count.
$response = $this->loginRequest($user1->getUsername(), $user1->passRaw);
$result_data = $this->serializer->decode($response->getBody(), 'json');
$this->logoutRequest('json', $result_data['logout_token']);
// Try 3 failed logins for user 1, they will not trigger flood control.
for ($i = 0; $i < 3; $i++) {
$response = $this->loginRequest($incorrect_user1->getUsername(), $incorrect_user1->passRaw);
$this->assertHttpResponseWithMessage($response, 400, 'Sorry, unrecognized username or password.');
}
// Try one successful attempt for user 2, it should not trigger any
// flood control.
$this->drupalLogin($user2);
$this->drupalLogout();
// Try one more attempt for user 1, it should be rejected, even if the
// correct password has been used.
$response = $this->loginRequest($user1->getUsername(), $user1->passRaw);
// Depending on the uid_only setting the error message will be different.
if ($uid_only_setting) {
$excepted_message = 'There have been more than 3 failed login attempts for this account. It is temporarily blocked. Try again later or request a new password.';
}
else {
$excepted_message = 'Too many failed login attempts from your IP address. This IP address is temporarily blocked.';
}
$this->assertHttpResponseWithMessage($response, 403, $excepted_message);
}
}
/**
* Executes a logout HTTP request.
*
* @param string $format
* The format to use to make the request.
* @param string $logout_token
* The csrf token for user logout.
*
* @return \Psr\Http\Message\ResponseInterface The HTTP response.
* The HTTP response.
*/
protected function logoutRequest($format = 'json', $logout_token = '') {
/** @var \GuzzleHttp\Client $client */
$client = $this->container->get('http_client');
$user_logout_url = Url::fromRoute('user.logout.http')
->setRouteParameter('_format', $format)
->setAbsolute();
if ($logout_token) {
$user_logout_url->setOption('query', ['token' => $logout_token]);
}
$post_options = [
'headers' => [
'Accept' => "application/$format",
],
'http_errors' => FALSE,
'cookies' => $this->cookies,
];
$response = $client->post($user_logout_url->toString(), $post_options);
return $response;
}
/**
* Test csrf protection of User Logout route.
*/
public function testLogoutCsrfProtection() {
$client = \Drupal::httpClient();
$login_status_url = $this->getLoginStatusUrlString();
$account = $this->drupalCreateUser();
$name = $account->getUsername();
$pass = $account->passRaw;
$response = $this->loginRequest($name, $pass);
$this->assertEquals(200, $response->getStatusCode());
$result_data = $this->serializer->decode($response->getBody(), 'json');
$logout_token = $result_data['logout_token'];
// Test third party site posting to current site with logout request.
// This should not logout the current user because it lacks the CSRF
// token.
$response = $this->logoutRequest('json');
$this->assertEquals(403, $response->getStatusCode());
// Ensure still logged in.
$response = $client->get($login_status_url, ['cookies' => $this->cookies]);
$this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_IN);
// Try with an incorrect token.
$response = $this->logoutRequest('json', 'not-the-correct-token');
$this->assertEquals(403, $response->getStatusCode());
// Ensure still logged in.
$response = $client->get($login_status_url, ['cookies' => $this->cookies]);
$this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_IN);
// Try a logout request with correct token.
$response = $this->logoutRequest('json', $logout_token);
$this->assertEquals(204, $response->getStatusCode());
// Ensure actually logged out.
$response = $client->get($login_status_url, ['cookies' => $this->cookies]);
$this->assertHttpResponse($response, 200, UserAuthenticationController::LOGGED_OUT);
}
/**
* Gets the URL string for checking login.
*
* @param string $format
* The format to use to make the request.
*
* @return string
* The URL string.
*/
protected function getLoginStatusUrlString($format = 'json') {
$user_login_status_url = Url::fromRoute('user.login_status.http');
$user_login_status_url->setRouteParameter('_format', $format);
$user_login_status_url->setAbsolute();
return $user_login_status_url->toString();
}
}
@@ -0,0 +1,76 @@
<?php
namespace Drupal\Tests\user\Functional;
use Drupal\Core\Test\AssertMailTrait;
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
/**
* Tests _user_mail_notify() use of user.settings.notify.*.
*
* @group user
*/
class UserMailNotifyTest extends EntityKernelTestBase {
use AssertMailTrait {
getMails as drupalGetMails;
}
/**
* Data provider for user mail testing.
*
* @return array
*/
public function userMailsProvider() {
return [
['cancel_confirm', ['cancel_confirm']],
['password_reset', ['password_reset']],
['status_activated', ['status_activated']],
['status_blocked', ['status_blocked']],
['status_canceled', ['status_canceled']],
['register_admin_created', ['register_admin_created']],
['register_no_approval_required', ['register_no_approval_required']],
['register_pending_approval', ['register_pending_approval', 'register_pending_approval_admin']]
];
}
/**
* Tests mails are sent when notify.$op is TRUE.
*
* @param string $op
* The operation being performed on the account.
* @param array $mail_keys
* The mail keys to test for.
*
* @dataProvider userMailsProvider
*/
public function testUserMailsSent($op, array $mail_keys) {
$this->config('user.settings')->set('notify.' . $op, TRUE)->save();
$return = _user_mail_notify($op, $this->createUser());
$this->assertTrue($return, '_user_mail_notify() returns TRUE.');
foreach ($mail_keys as $key) {
$filter = ['key' => $key];
$this->assertNotEmpty($this->getMails($filter), "Mails with $key exists.");
}
$this->assertCount(count($mail_keys), $this->getMails(), 'The expected number of emails sent.');
}
/**
* Tests mails are not sent when notify.$op is FALSE.
*
* @param string $op
* The operation being performed on the account.
* @param array $mail_keys
* The mail keys to test for. Ignored by this test because we assert that no
* mails at all are sent.
*
* @dataProvider userMailsProvider
*/
public function testUserMailsNotSent($op, array $mail_keys) {
$this->config('user.settings')->set('notify.' . $op, FALSE)->save();
$return = _user_mail_notify($op, $this->createUser());
$this->assertFalse($return, '_user_mail_notify() returns FALSE.');
$this->assertEmpty($this->getMails(), 'No emails sent by _user_mail_notify().');
}
}
@@ -0,0 +1,94 @@
<?php
namespace Drupal\Tests\user\Functional;
use Drupal\Tests\BrowserTestBase;
/**
* Tests that users can be assigned and unassigned roles.
*
* @group user
*/
class UserRolesAssignmentTest extends BrowserTestBase {
protected function setUp() {
parent::setUp();
$admin_user = $this->drupalCreateUser(['administer permissions', 'administer users']);
$this->drupalLogin($admin_user);
}
/**
* Tests that a user can be assigned a role and that the role can be removed
* again.
*/
public function testAssignAndRemoveRole() {
$rid = $this->drupalCreateRole(['administer users']);
$account = $this->drupalCreateUser();
// Assign the role to the user.
$this->drupalPostForm('user/' . $account->id() . '/edit', ["roles[$rid]" => $rid], t('Save'));
$this->assertText(t('The changes have been saved.'));
$this->assertFieldChecked('edit-roles-' . $rid, 'Role is assigned.');
$this->userLoadAndCheckRoleAssigned($account, $rid);
// Remove the role from the user.
$this->drupalPostForm('user/' . $account->id() . '/edit', ["roles[$rid]" => FALSE], t('Save'));
$this->assertText(t('The changes have been saved.'));
$this->assertNoFieldChecked('edit-roles-' . $rid, 'Role is removed from user.');
$this->userLoadAndCheckRoleAssigned($account, $rid, FALSE);
}
/**
* Tests that when creating a user the role can be assigned. And that it can
* be removed again.
*/
public function testCreateUserWithRole() {
$rid = $this->drupalCreateRole(['administer users']);
// Create a new user and add the role at the same time.
$edit = [
'name' => $this->randomMachineName(),
'mail' => $this->randomMachineName() . '@example.com',
'pass[pass1]' => $pass = $this->randomString(),
'pass[pass2]' => $pass,
"roles[$rid]" => $rid,
];
$this->drupalPostForm('admin/people/create', $edit, t('Create new account'));
$this->assertText(t('Created a new user account for @name.', ['@name' => $edit['name']]));
// Get the newly added user.
$account = user_load_by_name($edit['name']);
$this->drupalGet('user/' . $account->id() . '/edit');
$this->assertFieldChecked('edit-roles-' . $rid, 'Role is assigned.');
$this->userLoadAndCheckRoleAssigned($account, $rid);
// Remove the role again.
$this->drupalPostForm('user/' . $account->id() . '/edit', ["roles[$rid]" => FALSE], t('Save'));
$this->assertText(t('The changes have been saved.'));
$this->assertNoFieldChecked('edit-roles-' . $rid, 'Role is removed from user.');
$this->userLoadAndCheckRoleAssigned($account, $rid, FALSE);
}
/**
* Check role on user object.
*
* @param object $account
* The user account to check.
* @param string $rid
* The role ID to search for.
* @param bool $is_assigned
* (optional) Whether to assert that $rid exists (TRUE) or not (FALSE).
* Defaults to TRUE.
*/
private function userLoadAndCheckRoleAssigned($account, $rid, $is_assigned = TRUE) {
$user_storage = $this->container->get('entity.manager')->getStorage('user');
$user_storage->resetCache([$account->id()]);
$account = $user_storage->load($account->id());
if ($is_assigned) {
$this->assertFalse(array_search($rid, $account->getRoles()) === FALSE, 'The role is present in the user object.');
}
else {
$this->assertTrue(array_search($rid, $account->getRoles()) === FALSE, 'The role is not present in the user object.');
}
}
}
@@ -0,0 +1,61 @@
<?php
namespace Drupal\Tests\user\Functional;
use Drupal\Tests\BrowserTestBase;
use Drupal\user\Entity\User;
/**
* Tests account saving for arbitrary new uid.
*
* @group user
*/
class UserSaveTest extends BrowserTestBase {
/**
* Test creating a user with arbitrary uid.
*/
public function testUserImport() {
// User ID must be a number that is not in the database.
$uids = \Drupal::entityManager()->getStorage('user')->getQuery()
->sort('uid', 'DESC')
->range(0, 1)
->execute();
$max_uid = reset($uids);
$test_uid = $max_uid + mt_rand(1000, 1000000);
$test_name = $this->randomMachineName();
// Create the base user, based on drupalCreateUser().
$user = User::create([
'name' => $test_name,
'uid' => $test_uid,
'mail' => $test_name . '@example.com',
'pass' => user_password(),
'status' => 1,
]);
$user->enforceIsNew();
$user->save();
// Test if created user exists.
$user_by_uid = User::load($test_uid);
$this->assertTrue($user_by_uid, 'Loading user by uid.');
$user_by_name = user_load_by_name($test_name);
$this->assertTrue($user_by_name, 'Loading user by name.');
}
/**
* Ensures that an existing password is unset after the user was saved.
*/
public function testExistingPasswordRemoval() {
/** @var \Drupal\user\Entity\User $user */
$user = User::create(['name' => $this->randomMachineName()]);
$user->save();
$user->setExistingPassword('existing password');
$this->assertNotNull($user->pass->existing);
$user->save();
$this->assertNull($user->pass->existing);
}
}
@@ -0,0 +1,120 @@
<?php
namespace Drupal\Tests\user\Functional;
use Drupal\Tests\BrowserTestBase;
/**
* Tests the user search page and verifies that sensitive information is hidden
* from unauthorized users.
*
* @group user
*/
class UserSearchTest extends BrowserTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['search'];
public function testUserSearch() {
// Verify that a user without 'administer users' permission cannot search
// for users by email address. Additionally, ensure that the username has a
// plus sign to ensure searching works with that.
$user1 = $this->drupalCreateUser(['access user profiles', 'search content'], "foo+bar");
$this->drupalLogin($user1);
$keys = $user1->getEmail();
$edit = ['keys' => $keys];
$this->drupalPostForm('search/user', $edit, t('Search'));
$this->assertText(t('Your search yielded no results.'), 'Search by email did not work for non-admin user');
$this->assertText('no results', 'Search by email gave no-match message');
// Verify that a non-matching query gives an appropriate message.
$keys = 'nomatch';
$edit = ['keys' => $keys];
$this->drupalPostForm('search/user', $edit, t('Search'));
$this->assertText('no results', 'Non-matching search gave appropriate message');
// Verify that a user with search permission can search for users by name.
$keys = $user1->getUsername();
$edit = ['keys' => $keys];
$this->drupalPostForm('search/user', $edit, t('Search'));
$this->assertLink($keys, 0, 'Search by username worked for non-admin user');
// Verify that searching by sub-string works too.
$subkey = substr($keys, 1, 5);
$edit = ['keys' => $subkey];
$this->drupalPostForm('search/user', $edit, t('Search'));
$this->assertLink($keys, 0, 'Search by username substring worked for non-admin user');
// Verify that wildcard search works.
$subkey = substr($keys, 0, 2) . '*' . substr($keys, 4, 2);
$edit = ['keys' => $subkey];
$this->drupalPostForm('search/user', $edit, t('Search'));
$this->assertLink($keys, 0, 'Search with wildcard worked for non-admin user');
// Verify that a user with 'administer users' permission can search by
// email.
$user2 = $this->drupalCreateUser(['administer users', 'access user profiles', 'search content']);
$this->drupalLogin($user2);
$keys = $user2->getEmail();
$edit = ['keys' => $keys];
$this->drupalPostForm('search/user', $edit, t('Search'));
$this->assertText($keys, 'Search by email works for administrative user');
$this->assertText($user2->getUsername(), 'Search by email resulted in username on page for administrative user');
// Verify that a substring works too for email.
$subkey = substr($keys, 1, 5);
$edit = ['keys' => $subkey];
$this->drupalPostForm('search/user', $edit, t('Search'));
$this->assertText($keys, 'Search by email substring works for administrative user');
$this->assertText($user2->getUsername(), 'Search by email substring resulted in username on page for administrative user');
// Verify that wildcard search works for email
$subkey = substr($keys, 0, 2) . '*' . substr($keys, 4, 2);
$edit = ['keys' => $subkey];
$this->drupalPostForm('search/user', $edit, t('Search'));
$this->assertText($user2->getUsername(), 'Search for email wildcard resulted in username on page for administrative user');
// Verify that if they search by user name, they see email address too.
$keys = $user1->getUsername();
$edit = ['keys' => $keys];
$this->drupalPostForm('search/user', $edit, t('Search'));
$this->assertText($keys, 'Search by username works for admin user');
$this->assertText($user1->getEmail(), 'Search by username for admin shows email address too');
// Create a blocked user.
$blocked_user = $this->drupalCreateUser();
$blocked_user->block();
$blocked_user->save();
// Verify that users with "administer users" permissions can see blocked
// accounts in search results.
$edit = ['keys' => $blocked_user->getUsername()];
$this->drupalPostForm('search/user', $edit, t('Search'));
$this->assertText($blocked_user->getUsername(), 'Blocked users are listed on the user search results for users with the "administer users" permission.');
// Verify that users without "administer users" permissions do not see
// blocked accounts in search results.
$this->drupalLogin($user1);
$edit = ['keys' => $blocked_user->getUsername()];
$this->drupalPostForm('search/user', $edit, t('Search'));
$this->assertText(t('Your search yielded no results.'), 'Blocked users are hidden from the user search results.');
// Create a user without search permission, and one without user page view
// permission. Verify that neither one can access the user search page.
$user3 = $this->drupalCreateUser(['search content']);
$this->drupalLogin($user3);
$this->drupalGet('search/user');
$this->assertResponse('403', 'User without user profile access cannot search');
$user4 = $this->drupalCreateUser(['access user profiles']);
$this->drupalLogin($user4);
$this->drupalGet('search/user');
$this->assertResponse('403', 'User without search permission cannot search');
$this->drupalLogout();
}
}
@@ -0,0 +1,168 @@
<?php
namespace Drupal\Tests\user\Functional;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\Tests\BrowserTestBase;
use Drupal\user\Entity\User;
/**
* Generates text using placeholders for dummy content to check user token
* replacement.
*
* @group user
*/
class UserTokenReplaceTest extends BrowserTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['language', 'user_hooks_test'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
ConfigurableLanguage::createFromLangcode('de')->save();
}
/**
* Creates a user, then tests the tokens generated from it.
*/
public function testUserTokenReplacement() {
$token_service = \Drupal::token();
$language_interface = \Drupal::languageManager()->getCurrentLanguage();
$url_options = [
'absolute' => TRUE,
'language' => $language_interface,
];
\Drupal::state()->set('user_hooks_test_user_format_name_alter', TRUE);
\Drupal::state()->set('user_hooks_test_user_format_name_alter_safe', TRUE);
// Create two users and log them in one after another.
$user1 = $this->drupalCreateUser([]);
$user2 = $this->drupalCreateUser([]);
$this->drupalLogin($user1);
$this->drupalLogout();
$this->drupalLogin($user2);
$account = User::load($user1->id());
$global_account = User::load(\Drupal::currentUser()->id());
// Generate and test tokens.
$tests = [];
$tests['[user:uid]'] = $account->id();
$tests['[user:name]'] = $account->getAccountName();
$tests['[user:account-name]'] = $account->getAccountName();
$tests['[user:display-name]'] = $account->getDisplayName();
$tests['[user:mail]'] = $account->getEmail();
$tests['[user:url]'] = $account->url('canonical', $url_options);
$tests['[user:edit-url]'] = $account->url('edit-form', $url_options);
$tests['[user:last-login]'] = format_date($account->getLastLoginTime(), 'medium', '', NULL, $language_interface->getId());
$tests['[user:last-login:short]'] = format_date($account->getLastLoginTime(), 'short', '', NULL, $language_interface->getId());
$tests['[user:created]'] = format_date($account->getCreatedTime(), 'medium', '', NULL, $language_interface->getId());
$tests['[user:created:short]'] = format_date($account->getCreatedTime(), 'short', '', NULL, $language_interface->getId());
$tests['[current-user:name]'] = $global_account->getAccountName();
$tests['[current-user:account-name]'] = $global_account->getAccountName();
$tests['[current-user:display-name]'] = $global_account->getDisplayName();
$base_bubbleable_metadata = BubbleableMetadata::createFromObject($account);
$metadata_tests = [];
$metadata_tests['[user:uid]'] = $base_bubbleable_metadata;
$metadata_tests['[user:name]'] = $base_bubbleable_metadata;
$metadata_tests['[user:account-name]'] = $base_bubbleable_metadata;
$metadata_tests['[user:display-name]'] = $base_bubbleable_metadata;
$metadata_tests['[user:mail]'] = $base_bubbleable_metadata;
$metadata_tests['[user:url]'] = $base_bubbleable_metadata;
$metadata_tests['[user:edit-url]'] = $base_bubbleable_metadata;
$bubbleable_metadata = clone $base_bubbleable_metadata;
// This test runs with the Language module enabled, which means config is
// overridden by LanguageConfigFactoryOverride (to provide translations of
// config). This causes the interface language cache context to be added for
// config entities. The four next tokens use DateFormat Config entities, and
// therefore have the interface language cache context.
$bubbleable_metadata->addCacheContexts(['languages:language_interface']);
$metadata_tests['[user:last-login]'] = $bubbleable_metadata->addCacheTags(['rendered']);
$metadata_tests['[user:last-login:short]'] = $bubbleable_metadata;
$metadata_tests['[user:created]'] = $bubbleable_metadata;
$metadata_tests['[user:created:short]'] = $bubbleable_metadata;
$metadata_tests['[current-user:name]'] = $base_bubbleable_metadata->merge(BubbleableMetadata::createFromObject($global_account)->addCacheContexts(['user']));
$metadata_tests['[current-user:account-name]'] = $base_bubbleable_metadata->merge(BubbleableMetadata::createFromObject($global_account)->addCacheContexts(['user']));
$metadata_tests['[current-user:display-name]'] = $base_bubbleable_metadata->merge(BubbleableMetadata::createFromObject($global_account)->addCacheContexts(['user']));
// Test to make sure that we generated something for each token.
$this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.');
foreach ($tests as $input => $expected) {
$bubbleable_metadata = new BubbleableMetadata();
$output = $token_service->replace($input, ['user' => $account], ['langcode' => $language_interface->getId()], $bubbleable_metadata);
$this->assertEqual($output, $expected, new FormattableMarkup('User token %token replaced.', ['%token' => $input]));
$this->assertEqual($bubbleable_metadata, $metadata_tests[$input]);
}
// Generate tokens for the anonymous user.
$anonymous_user = User::load(0);
$tests = [];
$tests['[user:uid]'] = t('not yet assigned');
$tests['[user:display-name]'] = $anonymous_user->getDisplayName();
$base_bubbleable_metadata = BubbleableMetadata::createFromObject($anonymous_user);
$metadata_tests = [];
$metadata_tests['[user:uid]'] = $base_bubbleable_metadata;
$bubbleable_metadata = clone $base_bubbleable_metadata;
$bubbleable_metadata->addCacheableDependency(\Drupal::config('user.settings'));
$metadata_tests['[user:display-name]'] = $bubbleable_metadata;
foreach ($tests as $input => $expected) {
$bubbleable_metadata = new BubbleableMetadata();
$output = $token_service->replace($input, ['user' => $anonymous_user], ['langcode' => $language_interface->getId()], $bubbleable_metadata);
$this->assertEqual($output, $expected, format_string('Sanitized user token %token replaced.', ['%token' => $input]));
$this->assertEqual($bubbleable_metadata, $metadata_tests[$input]);
}
// Generate login and cancel link.
$tests = [];
$tests['[user:one-time-login-url]'] = user_pass_reset_url($account);
$tests['[user:cancel-url]'] = user_cancel_url($account);
// Generate tokens with interface language.
$link = \Drupal::url('user.page', [], ['absolute' => TRUE]);
foreach ($tests as $input => $expected) {
$output = $token_service->replace($input, ['user' => $account], ['langcode' => $language_interface->getId(), 'callback' => 'user_mail_tokens', 'clear' => TRUE]);
$this->assertTrue(strpos($output, $link) === 0, 'Generated URL is in interface language.');
}
// Generate tokens with the user's preferred language.
$account->preferred_langcode = 'de';
$account->save();
$link = \Drupal::url('user.page', [], ['language' => \Drupal::languageManager()->getLanguage($account->getPreferredLangcode()), 'absolute' => TRUE]);
foreach ($tests as $input => $expected) {
$output = $token_service->replace($input, ['user' => $account], ['callback' => 'user_mail_tokens', 'clear' => TRUE]);
$this->assertTrue(strpos($output, $link) === 0, "Generated URL is in the user's preferred language.");
}
// Generate tokens with one specific language.
$link = \Drupal::url('user.page', [], ['language' => \Drupal::languageManager()->getLanguage('de'), 'absolute' => TRUE]);
foreach ($tests as $input => $expected) {
foreach ([$user1, $user2] as $account) {
$output = $token_service->replace($input, ['user' => $account], ['langcode' => 'de', 'callback' => 'user_mail_tokens', 'clear' => TRUE]);
$this->assertTrue(strpos($output, $link) === 0, "Generated URL in the requested language.");
}
}
// Generate user display name tokens when safe markup is returned.
// @see user_hooks_test_user_format_name_alter()
\Drupal::state()->set('user_hooks_test_user_format_name_alter_safe', TRUE);
$input = '[user:display-name] [current-user:display-name]';
$expected = "<em>{$user1->id()}</em> <em>{$user2->id()}</em>";
$output = $token_service->replace($input, ['user' => $user1]);
$this->assertEqual($output, $expected, new FormattableMarkup('User token %token does not escape safe markup.', ['%token' => 'display-name']));
}
}
@@ -0,0 +1,157 @@
<?php
namespace Drupal\Tests\user\Kernel\Condition;
use Drupal\Component\Utility\SafeMarkup;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\Entity\Role;
use Drupal\user\Entity\User;
use Drupal\user\RoleInterface;
/**
* Tests the user role condition.
*
* @group user
*/
class UserRoleConditionTest extends KernelTestBase {
/**
* The condition plugin manager.
*
* @var \Drupal\Core\Condition\ConditionManager
*/
protected $manager;
/**
* An anonymous user for testing purposes.
*
* @var \Drupal\user\UserInterface
*/
protected $anonymous;
/**
* An authenticated user for testing purposes.
*
* @var \Drupal\user\UserInterface
*/
protected $authenticated;
/**
* A custom role for testing purposes.
*
* @var \Drupal\user\Entity\RoleInterface
*/
protected $role;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['system', 'user', 'field'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installSchema('system', 'sequences');
$this->installEntitySchema('user');
$this->manager = $this->container->get('plugin.manager.condition');
// Set up the authenticated and anonymous roles.
Role::create([
'id' => RoleInterface::ANONYMOUS_ID,
'label' => 'Anonymous user',
])->save();
Role::create([
'id' => RoleInterface::AUTHENTICATED_ID,
'label' => 'Authenticated user',
])->save();
// Create new role.
$rid = strtolower($this->randomMachineName(8));
$label = $this->randomString(8);
$role = Role::create([
'id' => $rid,
'label' => $label,
]);
$role->save();
$this->role = $role;
// Setup an anonymous user for our tests.
$this->anonymous = User::create([
'name' => '',
'uid' => 0,
]);
$this->anonymous->save();
// Loading the anonymous user adds the correct role.
$this->anonymous = User::load($this->anonymous->id());
// Setup an authenticated user for our tests.
$this->authenticated = User::create([
'name' => $this->randomMachineName(),
]);
$this->authenticated->save();
// Add the custom role.
$this->authenticated->addRole($this->role->id());
}
/**
* Test the user_role condition.
*/
public function testConditions() {
// Grab the user role condition and configure it to check against
// authenticated user roles.
/** @var $condition \Drupal\Core\Condition\ConditionInterface */
$condition = $this->manager->createInstance('user_role')
->setConfig('roles', [RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID])
->setContextValue('user', $this->anonymous);
$this->assertFalse($condition->execute(), 'Anonymous users fail role checks for authenticated.');
// Check for the proper summary.
// Summaries require an extra space due to negate handling in summary().
$this->assertEqual($condition->summary(), 'The user is a member of Authenticated user');
// Set the user role to anonymous.
$condition->setConfig('roles', [RoleInterface::ANONYMOUS_ID => RoleInterface::ANONYMOUS_ID]);
$this->assertTrue($condition->execute(), 'Anonymous users pass role checks for anonymous.');
// Check for the proper summary.
$this->assertEqual($condition->summary(), 'The user is a member of Anonymous user');
// Set the user role to check anonymous or authenticated.
$condition->setConfig('roles', [RoleInterface::ANONYMOUS_ID => RoleInterface::ANONYMOUS_ID, RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID]);
$this->assertTrue($condition->execute(), 'Anonymous users pass role checks for anonymous or authenticated.');
// Check for the proper summary.
$this->assertEqual($condition->summary(), 'The user is a member of Anonymous user, Authenticated user');
// Set the context to the authenticated user and check that they also pass
// against anonymous or authenticated roles.
$condition->setContextValue('user', $this->authenticated);
$this->assertTrue($condition->execute(), 'Authenticated users pass role checks for anonymous or authenticated.');
// Set the role to just authenticated and recheck.
$condition->setConfig('roles', [RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID]);
$this->assertTrue($condition->execute(), 'Authenticated users pass role checks for authenticated.');
// Test Constructor injection.
$condition = $this->manager->createInstance('user_role', ['roles' => [RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID], 'context' => ['user' => $this->authenticated]]);
$this->assertTrue($condition->execute(), 'Constructor injection of context and configuration working as anticipated.');
// Check the negated summary.
$condition->setConfig('negate', TRUE);
$this->assertEqual($condition->summary(), 'The user is not a member of Authenticated user');
// Check the complex negated summary.
$condition->setConfig('roles', [RoleInterface::ANONYMOUS_ID => RoleInterface::ANONYMOUS_ID, RoleInterface::AUTHENTICATED_ID => RoleInterface::AUTHENTICATED_ID]);
$this->assertEqual($condition->summary(), 'The user is not a member of Anonymous user, Authenticated user');
// Check a custom role.
$condition->setConfig('roles', [$this->role->id() => $this->role->id()]);
$condition->setConfig('negate', FALSE);
$this->assertTrue($condition->execute(), 'Authenticated user is a member of the custom role.');
$this->assertEqual($condition->summary(), SafeMarkup::format('The user is a member of @roles', ['@roles' => $this->role->label()]));
}
}
@@ -0,0 +1,98 @@
<?php
namespace Drupal\Tests\user\Kernel\Field;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\Entity\User;
/**
* Tests the user_name formatter.
*
* @group field
*/
class UserNameFormatterTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['field', 'user', 'system'];
/**
* @var string
*/
protected $entityType;
/**
* @var string
*/
protected $bundle;
/**
* @var string
*/
protected $fieldName;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(['field']);
$this->installEntitySchema('user');
$this->installSchema('system', ['sequences']);
$this->entityType = 'user';
$this->bundle = $this->entityType;
$this->fieldName = 'name';
}
/**
* Renders fields of a given entity with a given display.
*
* @param \Drupal\Core\Entity\FieldableEntityInterface $entity
* The entity object with attached fields to render.
* @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display
* The display to render the fields in.
*
* @return string
* The rendered entity fields.
*/
protected function renderEntityFields(FieldableEntityInterface $entity, EntityViewDisplayInterface $display) {
$content = $display->build($entity);
$content = $this->render($content);
return $content;
}
/**
* Tests the formatter output.
*/
public function testFormatter() {
$user = User::create([
'name' => 'test name',
]);
$user->save();
$result = $user->{$this->fieldName}->view(['type' => 'user_name']);
$this->assertEqual('username', $result[0]['#theme']);
$this->assertEqual(spl_object_hash($user), spl_object_hash($result[0]['#account']));
$result = $user->{$this->fieldName}->view(['type' => 'user_name', 'settings' => ['link_to_entity' => FALSE]]);
$this->assertEqual($user->getDisplayName(), $result[0]['#markup']);
$user = User::getAnonymousUser();
$result = $user->{$this->fieldName}->view(['type' => 'user_name']);
$this->assertEqual('username', $result[0]['#theme']);
$this->assertEqual(spl_object_hash($user), spl_object_hash($result[0]['#account']));
$result = $user->{$this->fieldName}->view(['type' => 'user_name', 'settings' => ['link_to_entity' => FALSE]]);
$this->assertEqual($user->getDisplayName(), $result[0]['#markup']);
$this->assertEqual($this->config('user.settings')->get('anonymous'), $result[0]['#markup']);
}
}
@@ -0,0 +1,109 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate;
use Drupal\Tests\migrate\Kernel\MigrateTestBase;
use Drupal\user\Entity\User;
/**
* Tests preservation of root account password.
*
* @group user
*/
class MigrateUserAdminPassTest extends MigrateTestBase {
/**
* The passwords as retrieved from the account entities before migration.
*
* @var array
*/
protected $originalPasswords = [];
/**
* Modules to enable.
*
* @var string[]
*/
public static $modules = ['user'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Make sure the admin user and a regular user are created.
$this->container->get('module_handler')->loadInclude('user', 'install');
$this->installEntitySchema('user');
user_install();
/** @var \Drupal\user\Entity\User $admin_account */
$admin_account = User::load(1);
$admin_account->setPassword('original');
$admin_account->save();
$this->originalPasswords[1] = $admin_account->getPassword();
/** @var \Drupal\user\Entity\User $user_account */
$user_account = User::create([
'uid' => 2,
'name' => 'original_username',
'mail' => 'original_email@example.com',
'pass' => 'original_password',
]);
$user_account->save();
$this->originalPasswords[2] = $user_account->getPassword();
}
/**
* Tests preserving the admin user's password.
*/
public function testAdminPasswordPreserved() {
$user_data_rows = [
[
'id' => '1',
'username' => 'site_admin',
'password' => 'new_password',
'email' => 'site_admin@example.com',
],
[
'id' => '2',
'username' => 'random_user',
'password' => 'random_password',
'email' => 'random_user@example.com',
],
];
$ids = ['id' => ['type' => 'integer']];
$definition = [
'id' => 'users',
'migration_tags' => ['Admin password test'],
'source' => [
'plugin' => 'embedded_data',
'data_rows' => $user_data_rows,
'ids' => $ids,
],
'process' => [
'uid' => 'id',
'name' => 'username',
'mail' => 'email',
'pass' => 'password',
],
'destination' => ['plugin' => 'entity:user'],
];
$migration = \Drupal::service('plugin.manager.migration')->createStubMigration($definition);
$this->executeMigration($migration);
// Verify that admin username and email were changed, but password was not.
/** @var \Drupal\user\Entity\User $admin_account */
$admin_account = User::load(1);
$this->assertIdentical($admin_account->getUsername(), 'site_admin');
$this->assertIdentical($admin_account->getEmail(), 'site_admin@example.com');
$this->assertIdentical($admin_account->getPassword(), $this->originalPasswords[1]);
// Verify that everything changed for the regular user.
/** @var \Drupal\user\Entity\User $user_account */
$user_account = User::load(2);
$this->assertIdentical($user_account->getUsername(), 'random_user');
$this->assertIdentical($user_account->getEmail(), 'random_user@example.com');
$this->assertNotIdentical($user_account->getPassword(), $this->originalPasswords[2]);
}
}
@@ -0,0 +1,43 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate;
use Drupal\Core\Entity\Entity\EntityViewDisplay;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
/**
* User picture entity display.
*
* @group user
*/
class MigrateUserPictureEntityDisplayTest extends MigrateDrupal7TestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['file', 'image'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('file');
$this->executeMigrations([
'user_picture_field',
'user_picture_field_instance',
'user_picture_entity_display',
]);
}
/**
* Tests the Drupal 7 user picture to Drupal 8 entity display migration.
*/
public function testUserPictureEntityDisplay() {
$component = EntityViewDisplay::load('user.user.default')->getComponent('user_picture');
$this->assertIdentical('image', $component['type']);
$this->assertIdentical('', $component['settings']['image_style']);
$this->assertIdentical('content', $component['settings']['image_link']);
}
}
@@ -0,0 +1,39 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
/**
* Tests migration of the user_picture field's entity form display settings.
*
* @group user
*/
class MigrateUserPictureEntityFormDisplayTest extends MigrateDrupal7TestBase {
public static $modules = ['image', 'file'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigrations([
'user_picture_field',
'user_picture_field_instance',
'user_picture_entity_form_display',
]);
}
/**
* Tests the field's entity form display settings.
*/
public function testEntityFormDisplaySettings() {
$component = EntityFormDisplay::load('user.user.default')->getComponent('user_picture');
$this->assertIdentical('image_image', $component['type']);
$this->assertIdentical('throbber', $component['settings']['progress_indicator']);
$this->assertIdentical('thumbnail', $component['settings']['preview_image_style']);
}
}
@@ -0,0 +1,41 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate;
use Drupal\Core\Field\FieldConfigInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
/**
* User picture field instance migration.
*
* @group user
*/
class MigrateUserPictureFieldInstanceTest extends MigrateDrupal7TestBase {
public static $modules = ['image', 'file'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigrations([
'user_picture_field',
'user_picture_field_instance',
]);
}
/**
* Test the user picture field migration.
*/
public function testUserPictureField() {
/** @var \Drupal\field\FieldConfigInterface $field */
$field = FieldConfig::load('user.user.user_picture');
$this->assertTrue($field instanceof FieldConfigInterface);
$this->assertIdentical('user', $field->getTargetEntityTypeId());
$this->assertIdentical('user', $field->getTargetBundle());
$this->assertIdentical('user_picture', $field->getName());
}
}
@@ -0,0 +1,38 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\FieldStorageConfigInterface;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
/**
* User picture field migration.
*
* @group user
*/
class MigrateUserPictureFieldTest extends MigrateDrupal7TestBase {
public static $modules = ['image', 'file'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigration('user_picture_field');
}
/**
* Test the user picture field migration.
*/
public function testUserPictureField() {
/** @var \Drupal\field\FieldStorageConfigInterface $field_storage */
$field_storage = FieldStorageConfig::load('user.user_picture');
$this->assertTrue($field_storage instanceof FieldStorageConfigInterface);
$this->assertIdentical('user.user_picture', $field_storage->id());
$this->assertIdentical('image', $field_storage->getType());
$this->assertIdentical('user', $field_storage->getTargetEntityTypeId());
}
}
@@ -0,0 +1,52 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate;
use Drupal\Core\Entity\Entity\EntityViewDisplay;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
/**
* Tests the user profile entity display migration.
*
* @group migrate_drupal_6
*/
class MigrateUserProfileEntityDisplayTest extends MigrateDrupal6TestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigrations([
'user_profile_field',
'user_profile_field_instance',
'user_profile_entity_display',
]);
}
/**
* Tests migration of user profile fields.
*/
public function testUserProfileFields() {
$display = EntityViewDisplay::load('user.user.default');
// Test a text field.
$component = $display->getComponent('profile_color');
$this->assertIdentical('text_default', $component['type']);
// Test a list field.
$component = $display->getComponent('profile_bands');
$this->assertIdentical('text_default', $component['type']);
// Test a date field.
$component = $display->getComponent('profile_birthdate');
$this->assertIdentical('datetime_default', $component['type']);
// Test PROFILE_PRIVATE field is hidden.
$this->assertNull($display->getComponent('profile_sell_address'));
// Test PROFILE_HIDDEN field is hidden.
$this->assertNull($display->getComponent('profile_sold_to'));
}
}
@@ -0,0 +1,57 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
/**
* Tests the user profile entity form display migration.
*
* @group migrate_drupal_6
*/
class MigrateUserProfileEntityFormDisplayTest extends MigrateDrupal6TestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigrations([
'user_profile_field',
'user_profile_field_instance',
'user_profile_entity_form_display',
]);
}
/**
* Tests migration of user profile fields.
*/
public function testUserProfileEntityFormDisplay() {
$display = EntityFormDisplay::load('user.user.default');
// Test a text field.
$component = $display->getComponent('profile_color');
$this->assertIdentical('text_textfield', $component['type']);
// Test a list field.
$component = $display->getComponent('profile_bands');
$this->assertIdentical('text_textfield', $component['type']);
// Test a date field.
$component = $display->getComponent('profile_birthdate');
$this->assertIdentical('datetime_default', $component['type']);
// Test PROFILE_PRIVATE field is hidden.
$this->assertNull($display->getComponent('profile_sell_address'));
// Test PROFILE_HIDDEN field is hidden.
$this->assertNull($display->getComponent('profile_sold_to'));
// Test that a checkbox field has the proper display label setting.
$component = $display->getComponent('profile_love_migrations');
$this->assertIdentical('boolean_checkbox', $component['type']);
$this->assertIdentical(TRUE, $component['settings']['display_label']);
}
}
@@ -0,0 +1,76 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate;
use Drupal\field\Entity\FieldConfig;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
/**
* Tests the user profile field instance migration.
*
* @group migrate_drupal_6
*/
class MigrateUserProfileFieldInstanceTest extends MigrateDrupal6TestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['field'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigrations([
'user_profile_field',
'user_profile_field_instance',
]);
}
/**
* Tests migration of user profile fields.
*/
public function testUserProfileFields() {
// Migrated a text field.
$field = FieldConfig::load('user.user.profile_color');
$this->assertIdentical('Favorite color', $field->label());
$this->assertIdentical('List your favorite color', $field->getDescription());
// Migrated a textarea.
$field = FieldConfig::load('user.user.profile_biography');
$this->assertIdentical('Biography', $field->label());
$this->assertIdentical('Tell people a little bit about yourself', $field->getDescription());
// Migrated checkbox field.
$field = FieldConfig::load('user.user.profile_sell_address');
$this->assertIdentical('Sell your email address?', $field->label());
$this->assertIdentical("If you check this box, we'll sell your address to spammers to help line the pockets of our shareholders. Thanks!", $field->getDescription());
// Migrated selection field.
$field = FieldConfig::load('user.user.profile_sold_to');
$this->assertIdentical('Sales Category', $field->label());
$this->assertIdentical("Select the sales categories to which this user's address was sold.", $field->getDescription());
// Migrated list field.
$field = FieldConfig::load('user.user.profile_bands');
$this->assertIdentical('Favorite bands', $field->label());
$this->assertIdentical("Enter your favorite bands. When you've saved your profile, you'll be able to find other people with the same favorites.", $field->getDescription());
// Migrated URL field.
$field = FieldConfig::load('user.user.profile_blog');
$this->assertIdentical('Blog', $field->label());
$this->assertIdentical("Paste the full URL, including http://, of your personal blog.", $field->getDescription());
// Migrated date field.
$field = FieldConfig::load('user.user.profile_birthdate');
$this->assertIdentical('Birthdate', $field->label());
$this->assertIdentical("Enter your birth date and we'll send you a coupon.", $field->getDescription());
// Another migrated checkbox field, with a different source visibility setting.
$field = FieldConfig::load('user.user.profile_love_migrations');
$this->assertIdentical('I love migrations', $field->label());
$this->assertIdentical("If you check this box, you love migrations.", $field->getDescription());
}
}
@@ -0,0 +1,70 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
/**
* Tests the user profile field migration.
*
* @group migrate_drupal_6
*/
class MigrateUserProfileFieldTest extends MigrateDrupal6TestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigration('user_profile_field');
}
/**
* Tests migration of user profile fields.
*/
public function testUserProfileFields() {
// Migrated a text field.
$field_storage = FieldStorageConfig::load('user.profile_color');
$this->assertIdentical('text', $field_storage->getType(), 'Field type is text.');
$this->assertIdentical(1, $field_storage->getCardinality(), 'Text field has correct cardinality');
// Migrated a textarea.
$field_storage = FieldStorageConfig::load('user.profile_biography');
$this->assertIdentical('text_long', $field_storage->getType(), 'Field type is text_long.');
// Migrated checkbox field.
$field_storage = FieldStorageConfig::load('user.profile_sell_address');
$this->assertIdentical('boolean', $field_storage->getType(), 'Field type is boolean.');
// Migrated selection field.
$field_storage = FieldStorageConfig::load('user.profile_sold_to');
$this->assertIdentical('list_string', $field_storage->getType(), 'Field type is list_string.');
$settings = $field_storage->getSettings();
$this->assertEqual($settings['allowed_values'], [
'Pill spammers' => 'Pill spammers',
'Fitness spammers' => 'Fitness spammers',
'Back\slash' => 'Back\slash',
'Forward/slash' => 'Forward/slash',
'Dot.in.the.middle' => 'Dot.in.the.middle',
'Faithful servant' => 'Faithful servant',
'Anonymous donor' => 'Anonymous donor',
]);
$this->assertIdentical('list_string', $field_storage->getType(), 'Field type is list_string.');
// Migrated list field.
$field_storage = FieldStorageConfig::load('user.profile_bands');
$this->assertIdentical('text', $field_storage->getType(), 'Field type is text.');
$this->assertIdentical(-1, $field_storage->getCardinality(), 'List field has correct cardinality');
// Migrated URL field.
$field_storage = FieldStorageConfig::load('user.profile_blog');
$this->assertIdentical('link', $field_storage->getType(), 'Field type is link.');
// Migrated date field.
$field_storage = FieldStorageConfig::load('user.profile_birthdate');
$this->assertIdentical('datetime', $field_storage->getType(), 'Field type is datetime.');
$this->assertIdentical('date', $field_storage->getSettings()['datetime_type']);
}
}
@@ -0,0 +1,38 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate;
use Drupal\Tests\migrate_drupal\Kernel\MigrateDrupalTestBase;
use Drupal\migrate_drupal\Tests\StubTestTrait;
/**
* Test stub creation for user entities.
*
* @group user
*/
class MigrateUserStubTest extends MigrateDrupalTestBase {
use StubTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['user'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('user');
$this->installSchema('system', ['sequences']);
}
/**
* Tests creation of user stubs.
*/
public function testStub() {
$this->performStubTest('user');
}
}
@@ -0,0 +1,89 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d6;
use Drupal\Tests\SchemaCheckTestTrait;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
use Drupal\user\AccountSettingsForm;
use Drupal\Core\Database\Database;
/**
* Upgrade variables to user.*.yml.
*
* @group migrate_drupal_6
*/
class MigrateUserConfigsTest extends MigrateDrupal6TestBase {
use SchemaCheckTestTrait;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->container->get('router.builder')->rebuild();
$this->executeMigrations(['d6_user_mail', 'd6_user_settings']);
}
/**
* Tests migration of user variables to user.mail.yml.
*/
public function testUserMail() {
$config = $this->config('user.mail');
$this->assertIdentical('Account details for [user:name] at [site:name] (approved)', $config->get('status_activated.subject'));
$this->assertIdentical("[user:name],\n\nYour account at [site:name] has been activated.\n\nYou may now log in by clicking on this link or copying and pasting it in your browser:\n\n[user:one-time-login-url]\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to [user:edit-url] so you can change your password.\n\nOnce you have set your own password, you will be able to log in to [site:login-url] in the future using:\n\nusername: [user:name]\n", $config->get('status_activated.body'));
$this->assertIdentical('Replacement login information for [user:name] at [site:name]', $config->get('password_reset.subject'));
$this->assertIdentical("[user:name],\n\nA request to reset the password for your account has been made at [site:name].\n\nYou may now log in to [site:url-brief] by clicking on this link or copying and pasting it in your browser:\n\n[user:one-time-login-url]\n\nThis is a one-time login, so it can be used only once. It expires after one day and nothing will happen if it's not used.\n\nAfter logging in, you will be redirected to [user:edit-url] so you can change your password.", $config->get('password_reset.body'));
$this->assertIdentical('Account details for [user:name] at [site:name] (deleted)', $config->get('cancel_confirm.subject'));
$this->assertIdentical("[user:name],\n\nYour account on [site:name] has been deleted.", $config->get('cancel_confirm.body'));
$this->assertIdentical('An administrator created an account for you at [site:name]', $config->get('register_admin_created.subject'));
$this->assertIdentical("[user:name],\n\nA site administrator at [site:name] has created an account for you. You may now log in to [site:login-url] using the following username and password:\n\nusername: [user:name]\npassword: \n\nYou may also log in by clicking on this link or copying and pasting it in your browser:\n\n[user:one-time-login-url]\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to [user:edit-url] so you can change your password.\n\n\n-- [site:name] team", $config->get('register_admin_created.body'));
$this->assertIdentical('Account details for [user:name] at [site:name]', $config->get('register_no_approval_required.subject'));
$this->assertIdentical("[user:name],\n\nThank you for registering at [site:name]. You may now log in to [site:login-url] using the following username and password:\n\nusername: [user:name]\npassword: \n\nYou may also log in by clicking on this link or copying and pasting it in your browser:\n\n[user:one-time-login-url]\n\nThis is a one-time login, so it can be used only once.\n\nAfter logging in, you will be redirected to [user:edit-url] so you can change your password.\n\n\n-- [site:name] team", $config->get('register_no_approval_required.body'));
$this->assertIdentical('Account details for [user:name] at [site:name] (pending admin approval)', $config->get('register_pending_approval.subject'));
$this->assertIdentical("[user:name],\n\nThank you for registering at [site:name]. Your application for an account is currently pending approval. Once it has been approved, you will receive another email containing information about how to log in, set your password, and other details.\n\n\n-- [site:name] team", $config->get('register_pending_approval.body'));
$this->assertIdentical('Account details for [user:name] at [site:name] (blocked)', $config->get('status_blocked.subject'));
$this->assertIdentical("[user:name],\n\nYour account on [site:name] has been blocked.", $config->get('status_blocked.body'));
$this->assertConfigSchema(\Drupal::service('config.typed'), 'user.mail', $config->get());
}
/**
* Tests migration of user variables to user.settings.yml.
*/
public function testUserSettings() {
$config = $this->config('user.settings');
$this->assertIdentical(TRUE, $config->get('notify.status_blocked'));
$this->assertIdentical(FALSE, $config->get('notify.status_activated'));
$this->assertIdentical(FALSE, $config->get('verify_mail'));
$this->assertIdentical('admin_only', $config->get('register'));
$this->assertIdentical('Guest', $config->get('anonymous'));
// Tests migration of user_register using the AccountSettingsForm.
// Map D6 value to D8 value
$user_register_map = [
[0, USER_REGISTER_ADMINISTRATORS_ONLY],
[1, USER_REGISTER_VISITORS],
[2, USER_REGISTER_VISITORS_ADMINISTRATIVE_APPROVAL],
];
foreach ($user_register_map as $map) {
// Tests migration of user_register = 1
Database::getConnection('default', 'migrate')
->update('variable')
->fields(['value' => serialize($map[0])])
->condition('name', 'user_register')
->execute();
/** @var \Drupal\migrate\Plugin\MigrationInterface $migration */
$migration = $this->getMigration('d6_user_settings');
// Indicate we're rerunning a migration that's already run.
$migration->getIdMap()->prepareUpdate();
$this->executeMigration($migration);
$form = $this->container->get('form_builder')->getForm(AccountSettingsForm::create($this->container));
$this->assertIdentical($map[1], $form['registration_cancellation']['user_register']['#value']);
}
}
}
@@ -0,0 +1,48 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d6;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
/**
* Users contact settings migration.
*
* @group migrate_drupal_6
*/
class MigrateUserContactSettingsTest extends MigrateDrupal6TestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['contact'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->migrateUsers(FALSE);
$this->installSchema('user', ['users_data']);
$this->executeMigration('d6_user_contact_settings');
}
/**
* Tests the Drupal6 user contact settings migration.
*/
public function testUserContactSettings() {
$user_data = \Drupal::service('user.data');
$module = $key = 'contact';
$uid = 2;
$setting = $user_data->get($module, $uid, $key);
$this->assertIdentical('1', $setting);
$uid = 8;
$setting = $user_data->get($module, $uid, $key);
$this->assertIdentical('0', $setting);
$uid = 15;
$setting = $user_data->get($module, $uid, $key);
$this->assertIdentical(NULL, $setting);
}
}
@@ -0,0 +1,69 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d6;
use Drupal\file\Entity\File;
use Drupal\file\FileInterface;
use Drupal\Tests\file\Kernel\Migrate\d6\FileMigrationTestTrait;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
/**
* User pictures migration.
*
* @group migrate_drupal_6
*/
class MigrateUserPictureD6FileTest extends MigrateDrupal6TestBase {
use FileMigrationTestTrait;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('file');
$this->executeMigration('d6_user_picture_file');
$this->setUpMigratedFiles();
}
/**
* Asserts a file entity.
*
* @param int $fid
* The file ID.
* @param string $name
* The expected file name.
* @param int $size
* The expected file size.
* @param string $uri
* The expected file URI.
* @param string $type
* The expected MIME type.
* @param int $uid
* The expected file owner ID.
*/
protected function assertEntity($fid, $name, $size, $uri, $type, $uid) {
/** @var \Drupal\file\FileInterface $file */
$file = File::load($fid);
$this->assertInstanceOf(FileInterface::class, $file);
$this->assertSame($name, $file->getFilename());
$this->assertSame($size, $file->getSize());
$this->assertSame($uri, $file->getFileUri());
$this->assertSame($type, $file->getMimeType());
$this->assertSame($uid, $file->getOwnerId());
}
/**
* Tests the D6 user pictures migration in combination with D6 file.
*/
public function testUserPicturesWithD6File() {
$this->assertEntity(1, 'image-test.jpg', '1901', 'public://image-test.jpg', 'image/jpeg', '2');
$this->assertEntity(2, 'image-test.png', '125', 'public://image-test.png', 'image/png', '8');
$this->assertEntity(3, 'Image1.png', '39325', 'public://image-1.png', 'image/png', '1');
$this->assertEntity(4, 'Image2.jpg', '1831', 'public://image-2.jpg', 'image/jpeg', '1');
$this->assertEntity(5, 'Image-test.gif', '183', 'public://image-test.gif', 'image/jpeg', '1');
$this->assertEntity(6, 'html-1.txt', '24', 'public://html-1.txt', 'text/plain', '1');
}
}
@@ -0,0 +1,52 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d6;
use Drupal\file\Entity\File;
use Drupal\Tests\file\Kernel\Migrate\d6\FileMigrationTestTrait;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
/**
* User pictures migration.
*
* @group migrate_drupal_6
*/
class MigrateUserPictureFileTest extends MigrateDrupal6TestBase {
use FileMigrationTestTrait;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('file');
$this->executeMigration('d6_user_picture_file');
}
/**
* Tests the Drupal 6 user pictures to Drupal 8 migration.
*/
public function testUserPictures() {
$file_ids = [];
foreach ($this->migration->getIdMap() as $destination_ids) {
$file_ids[] = reset($destination_ids);
}
$files = File::loadMultiple($file_ids);
/** @var \Drupal\file\FileInterface $file */
$file = array_shift($files);
$this->assertIdentical('image-test.jpg', $file->getFilename());
$this->assertIdentical('public://image-test.jpg', $file->getFileUri());
$this->assertIdentical('2', $file->getOwnerId());
$this->assertIdentical('1901', $file->getSize());
$this->assertIdentical('image/jpeg', $file->getMimeType());
$file = array_shift($files);
$this->assertIdentical('image-test.png', $file->getFilename());
$this->assertIdentical('public://image-test.png', $file->getFileUri());
$this->assertIdentical('8', $file->getOwnerId());
$this->assertFalse($files);
}
}
@@ -0,0 +1,71 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d6;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
use Drupal\user\Entity\User;
/**
* User profile values migration.
*
* @group migrate_drupal_6
*/
class MigrateUserProfileValuesTest extends MigrateDrupal6TestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['language'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigrations([
'language',
'user_profile_field',
'user_profile_field_instance',
'user_profile_entity_display',
'user_profile_entity_form_display',
]);
$this->migrateUsers(FALSE);
$this->executeMigration('d6_profile_values');
}
/**
* Tests Drupal 6 profile values to Drupal 8 migration.
*/
public function testUserProfileValues() {
$user = User::load(2);
$this->assertFalse(is_null($user));
$this->assertIdentical('red', $user->profile_color->value);
$expected = <<<EOT
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam nulla sapien, congue nec risus ut, adipiscing aliquet felis. Maecenas quis justo vel nulla varius euismod. Quisque metus metus, cursus sit amet sem non, bibendum vehicula elit. Cras dui nisl, eleifend at iaculis vitae, lacinia ut felis. Nullam aliquam ligula volutpat nulla consectetur accumsan. Maecenas tincidunt molestie diam, a accumsan enim fringilla sit amet. Morbi a tincidunt tellus. Donec imperdiet scelerisque porta. Sed quis sem bibendum eros congue sodales. Vivamus vel fermentum est, at rutrum orci. Nunc consectetur purus ut dolor pulvinar, ut volutpat felis congue. Cras tincidunt odio sed neque sollicitudin, vehicula tempor metus scelerisque.
EOT;
$this->assertIdentical($expected, $user->profile_biography->value);
$this->assertIdentical('1', $user->profile_sell_address->value);
$this->assertIdentical('Back\slash', $user->profile_sold_to->value);
$this->assertIdentical('AC/DC', $user->profile_bands[0]->value);
$this->assertIdentical('Eagles', $user->profile_bands[1]->value);
$this->assertIdentical('Elton John', $user->profile_bands[2]->value);
$this->assertIdentical('Lemonheads', $user->profile_bands[3]->value);
$this->assertIdentical('Rolling Stones', $user->profile_bands[4]->value);
$this->assertIdentical('Queen', $user->profile_bands[5]->value);
$this->assertIdentical('The White Stripes', $user->profile_bands[6]->value);
$this->assertIdentical('1974-06-02', $user->profile_birthdate->value);
$this->assertIdentical('http://example.com/blog', $user->profile_blog->uri);
$this->assertNull($user->profile_blog->title);
$this->assertIdentical([], $user->profile_blog->options);
$this->assertIdentical('http://example.com/blog', $user->profile_blog->uri);
$this->assertNull($user->profile_love_migrations->value);
$user = User::load(8);
$this->assertIdentical('Forward/slash', $user->profile_sold_to->value);
$user = User::load(15);
$this->assertIdentical('Dot.in.the.middle', $user->profile_sold_to->value);
}
}
@@ -0,0 +1,167 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d6;
use Drupal\user\Entity\Role;
use Drupal\user\RoleInterface;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
use Drupal\migrate\Plugin\MigrateIdMapInterface;
/**
* Upgrade user roles to user.role.*.yml.
*
* @group migrate_drupal_6
*/
class MigrateUserRoleTest extends MigrateDrupal6TestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigrations(['d6_filter_format', 'd6_user_role']);
}
/**
* Helper function to perform assertions on a user role.
*
* @param string $id
* The role ID.
* @param string[] $permissions
* An array of user permissions.
* @param int $lookupId
* The original numeric ID of the role in the source database.
* @param \Drupal\migrate\Plugin\MigrateIdMapInterface $id_map
* The map table plugin.
*/
protected function assertRole($id, array $permissions, $lookupId, MigrateIdMapInterface $id_map) {
/** @var \Drupal\user\RoleInterface $role */
$role = Role::load($id);
$this->assertInstanceOf(RoleInterface::class, $role);
sort($permissions);
$this->assertSame($permissions, $role->getPermissions());
$this->assertSame([[$id]], $id_map->lookupDestinationIds(['rid' => $lookupId]));
}
/**
* Helper function to test the migration of the user roles. The user roles
* will be re-imported and the tests here will be repeated.
*
* @param \Drupal\migrate\Plugin\MigrateIdMapInterface $id_map
* The map table plugin.
*/
protected function assertRoles(MigrateIdMapInterface $id_map) {
// The permissions for each role are found in the two tables in the Drupal 6
// source database. One is the permission table and the other is the
// filter_format table.
$permissions = [
// From permission table.
'access content',
'migrate test anonymous permission',
// From filter_format tables.
'use text format filtered_html'
];
$this->assertRole('anonymous', $permissions, 1, $id_map);
$permissions = [
// From permission table.
'access comments',
'access content',
'migrate test authenticated permission',
'post comments',
'skip comment approval',
// From filter_format.
'use text format filtered_html',
];
$this->assertRole('authenticated', $permissions, 2, $id_map);
$permissions = [
// From permission table.
'migrate test role 1 test permission',
// From filter format.
'use text format full_html',
'use text format php_code'
];
$this->assertRole('migrate_test_role_1', $permissions, 3, $id_map);
$permissions = [
// From permission table.
'migrate test role 2 test permission',
'use PHP for settings',
'administer contact forms',
'skip comment approval',
'edit own blog content',
'edit any blog content',
'delete own blog content',
'delete any blog content',
'create forum content',
'delete any forum content',
'delete own forum content',
'edit any forum content',
'edit own forum content',
'administer nodes',
'access content overview',
// From filter format.
'use text format php_code',
];
$this->assertRole('migrate_test_role_2', $permissions, 4, $id_map);
// The only permission for this role is a filter format.
$permissions = ['use text format php_code'];
$this->assertRole('migrate_test_role_3_that_is_longer_than_thirty_two_characters', $permissions, 5, $id_map);
}
/**
* Tests user role migration.
*/
public function testUserRole() {
$id_map = $this->getMigration('d6_user_role')->getIdMap();
$this->assertRoles($id_map);
// Test there are no duplicated roles.
$roles = [
'anonymous1',
'authenticated1',
'administrator1',
'migrate_test_role_11',
'migrate_test_role_21',
'migrate_test_role_3_that_is_longer_than_thirty_two_characters1'
];
$this->assertEmpty(Role::loadMultiple($roles));
// Remove the map row for the migrate_test_role_1 role and rerun the
// migration. This will re-import the migrate_test_role_1 role migration
// again.
$this->sourceDatabase->insert('role')
->fields([
'rid' => 6,
'name' => 'migrate test role 4',
])
->execute();
$this->sourceDatabase->insert('permission')
->fields([
'pid' => 7,
'rid' => 6,
'perm' => 'access content',
'tid' => 0,
])
->execute();
$id_map->delete(['rid' => 3]);
$this->executeMigration('d6_user_role');
// Test there are no duplicated roles.
$roles[] = 'migrate_test_role_41';
$this->assertEmpty(Role::loadMultiple($roles));
// Test that the existing roles have not changed.
$this->assertRoles($id_map);
// Test the migration of the new role, migrate_test_role_4.
$permissions = ['access content'];
$this->assertRole('migrate_test_role_4', $permissions, 6, $id_map);
}
}
@@ -0,0 +1,173 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d6;
use Drupal\migrate\MigrateExecutable;
use Drupal\Tests\file\Kernel\Migrate\d6\FileMigrationTestTrait;
use Drupal\user\Entity\User;
use Drupal\file\Entity\File;
use Drupal\Core\Database\Database;
use Drupal\user\RoleInterface;
use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase;
/**
* Users migration.
*
* @group migrate_drupal_6
*/
class MigrateUserTest extends MigrateDrupal6TestBase {
use FileMigrationTestTrait;
/**
* {@inheritdoc}
*/
public static $modules = ['language'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('file');
$this->installSchema('file', ['file_usage']);
$this->installEntitySchema('node');
$this->installSchema('user', ['users_data']);
// Make sure uid 1 is created.
user_install();
$file = File::create([
'fid' => 2,
'uid' => 2,
'filename' => 'image-test.jpg',
'uri' => "public://image-test.jpg",
'filemime' => 'image/jpeg',
'created' => 1,
'changed' => 1,
'status' => FILE_STATUS_PERMANENT,
]);
$file->enforceIsNew();
file_put_contents($file->getFileUri(), file_get_contents('core/modules/simpletest/files/image-1.png'));
$file->save();
$file = File::create([
'fid' => 8,
'uid' => 8,
'filename' => 'image-test.png',
'uri' => "public://image-test.png",
'filemime' => 'image/png',
'created' => 1,
'changed' => 1,
'status' => FILE_STATUS_PERMANENT,
]);
$file->enforceIsNew();
file_put_contents($file->getFileUri(), file_get_contents('core/modules/simpletest/files/image-2.jpg'));
$file->save();
$this->executeMigration('language');
$this->migrateUsers();
}
/**
* Tests the Drupal6 user to Drupal 8 migration.
*/
public function testUser() {
$users = Database::getConnection('default', 'migrate')
->select('users', 'u')
->fields('u')
->condition('uid', 0, '>')
->execute()
->fetchAll();
foreach ($users as $source) {
// Get roles directly from the source.
$rids = Database::getConnection('default', 'migrate')
->select('users_roles', 'ur')
->fields('ur', ['rid'])
->condition('ur.uid', $source->uid)
->execute()
->fetchCol();
$roles = [RoleInterface::AUTHENTICATED_ID];
$id_map = $this->getMigration('d6_user_role')->getIdMap();
foreach ($rids as $rid) {
$role = $id_map->lookupDestinationId([$rid]);
$roles[] = reset($role);
}
/** @var \Drupal\user\UserInterface $user */
$user = User::load($source->uid);
$this->assertSame($source->uid, $user->id());
$this->assertSame($source->name, $user->label());
$this->assertSame($source->mail, $user->getEmail());
$this->assertSame($source->created, $user->getCreatedTime());
$this->assertSame($source->access, $user->getLastAccessedTime());
$this->assertSame($source->login, $user->getLastLoginTime());
$is_blocked = $source->status == 0;
$this->assertSame($is_blocked, $user->isBlocked());
$expected_timezone_name = $source->timezone_name ?: $this->config('system.date')->get('timezone.default');
$this->assertSame($expected_timezone_name, $user->getTimeZone());
$this->assertSame($source->init, $user->getInitialEmail());
$this->assertSame($roles, $user->getRoles());
// Ensure the user's langcode, preferred_langcode and
// preferred_admin_langcode are valid.
// $user->getPreferredLangcode() might fallback to default language if the
// user preferred language is not configured on the site. We just want to
// test if the value was imported correctly.
$language_manager = $this->container->get('language_manager');
$default_langcode = $language_manager->getDefaultLanguage()->getId();
if (empty($source->language)) {
$this->assertSame('en', $user->langcode->value);
$this->assertSame($default_langcode, $user->preferred_langcode->value);
$this->assertSame($default_langcode, $user->preferred_admin_langcode->value);
}
elseif ($language_manager->getLanguage($source->language) === NULL) {
$this->assertSame($default_langcode, $user->langcode->value);
$this->assertSame($default_langcode, $user->preferred_langcode->value);
$this->assertSame($default_langcode, $user->preferred_admin_langcode->value);
}
else {
$this->assertSame($source->language, $user->langcode->value);
$this->assertSame($source->language, $user->preferred_langcode->value);
$this->assertSame($source->language, $user->preferred_admin_langcode->value);
}
// We have one empty picture in the data so don't try load that.
if (!empty($source->picture)) {
// Test the user picture.
$file = File::load($user->user_picture->target_id);
$this->assertSame(basename($source->picture), $file->getFilename());
}
else {
// Ensure the user does not have a picture.
$this->assertFalse($user->user_picture->target_id, sprintf('User %s does not have a picture', $user->id()));
}
// Use the API to check if the password has been salted and re-hashed to
// conform to Drupal >= 7 for non-admin users.
if ($user->id() != 1) {
$this->assertTrue(\Drupal::service('password')
->check($source->pass_plain, $user->getPassword()));
}
}
// Rollback the migration and make sure everything is deleted but uid 1.
(new MigrateExecutable($this->migration, $this))->rollback();
$users = Database::getConnection('default', 'migrate')
->select('users', 'u')
->fields('u', ['uid'])
->condition('uid', 0, '>')
->execute()
->fetchCol();
foreach ($users as $uid) {
$account = User::load($uid);
if ($uid == 1) {
$this->assertNotNull($account, 'User 1 was preserved after rollback');
}
else {
$this->assertNull($account);
}
}
}
}
@@ -0,0 +1,40 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d7;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
/**
* Migrates user flood control configuration.
*
* @group user
*/
class MigrateUserFloodTest extends MigrateDrupal7TestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(['user']);
$this->executeMigration('d7_user_flood');
}
/**
* Tests the migration.
*/
public function testMigration() {
$expected = [
'uid_only' => TRUE,
'ip_limit' => 30,
'ip_window' => 7200,
'user_limit' => 22,
'user_window' => 86400,
'_core' => [
'default_config_hash' => 'UYfMzeP1S8jKm9PSvxf7nQNe8DsNS-3bc2WSNNXBQWs',
],
];
$this->assertIdentical($expected, $this->config('user.flood')->get());
}
}
@@ -0,0 +1,44 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d7;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
/**
* Migrates user mail configuration.
*
* @group user
*/
class MigrateUserMailTest extends MigrateDrupal7TestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installConfig(['user']);
$this->executeMigration('d7_user_mail');
}
/**
* Tests the migration.
*/
public function testMigration() {
$config = $this->config('user.mail');
$this->assertIdentical('Your account is approved!', $config->get('status_activated.subject'));
$this->assertIdentical('Your account was activated, and there was much rejoicing.', $config->get('status_activated.body'));
$this->assertIdentical('Fix your password', $config->get('password_reset.subject'));
$this->assertIdentical("Nope! You're locked out forever.", $config->get('password_reset.body'));
$this->assertIdentical('So long, bub', $config->get('cancel_confirm.subject'));
$this->assertIdentical('The gates of Drupal are closed to you. Now you will work in the salt mines.', $config->get('cancel_confirm.body'));
$this->assertIdentical('Gawd made you an account', $config->get('register_admin_created.subject'));
$this->assertIdentical('...and she could take it away.', $config->get('register_admin_created.body'));
$this->assertIdentical('Welcome!', $config->get('register_no_approval_required.subject'));
$this->assertIdentical('You can now log in if you can figure out how to use Drupal!', $config->get('register_no_approval_required.body'));
$this->assertIdentical('Soon...', $config->get('register_pending_approval.subject'));
$this->assertIdentical('...you will join our Circle. Let the Drupal flow through you.', $config->get('register_pending_approval.body'));
$this->assertIdentical('BEGONE!', $config->get('status_blocked.subject'));
$this->assertIdentical('You no longer please the robot overlords. Go to your room and chill out.', $config->get('status_blocked.body'));
}
}
@@ -0,0 +1,106 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d7;
use Drupal\Core\Database\Database;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
use Drupal\user\Entity\Role;
use Drupal\user\RoleInterface;
/**
* Upgrade user roles to user.role.*.yml.
*
* @group user
*/
class MigrateUserRoleTest extends MigrateDrupal7TestBase {
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->executeMigration('d7_user_role');
}
/**
* Asserts aspects of a user role config entity.
*
* @param string $id
* The role ID.
* @param string $label
* The role's expected label.
* @param int|null $original_rid
* The original (integer) ID of the role, to check permissions.
*/
protected function assertEntity($id, $label, $original_rid) {
/** @var \Drupal\user\RoleInterface $entity */
$entity = Role::load($id);
$this->assertTrue($entity instanceof RoleInterface);
$this->assertIdentical($label, $entity->label());
if (isset($original_rid)) {
$permissions = Database::getConnection('default', 'migrate')
->select('role_permission', 'rp')
->fields('rp', ['permission'])
->condition('rid', $original_rid)
->execute()
->fetchCol();
sort($permissions);
$this->assertIdentical($permissions, $entity->getPermissions());
}
}
/**
* Tests user role migration.
*/
public function testUserRole() {
$this->assertEntity('anonymous', 'anonymous user', 1);
$this->assertEntity('authenticated', 'authenticated user', 2);
$this->assertEntity('administrator', 'administrator', 3);
// Test there are no duplicated roles.
$roles = [
'anonymous1',
'authenticated1',
'administrator1',
];
$this->assertEmpty(Role::loadMultiple($roles));
// Remove the map row for the administrator role and rerun the migration.
// This will re-import the administrator role again.
$id_map = $this->getMigration('d7_user_role')->getIdMap();
$id_map->delete(['rid' => 3]);
$this->sourceDatabase->insert('role')
->fields([
'rid' => 4,
'name' => 'test role',
'weight' => 10,
])
->execute();
$this->sourceDatabase->insert('role_permission')
->fields([
'rid' => 4,
'permission' => 'access content',
'module' => 'node',
])
->execute();
$this->executeMigration('d7_user_role');
// Test there are no duplicated roles.
$roles = [
'anonymous1',
'authenticated1',
'administrator1',
];
$this->assertEmpty(Role::loadMultiple($roles));
// Test that the existing roles have not changed.
$this->assertEntity('administrator', 'administrator', 3);
$this->assertEntity('anonymous', 'anonymous user', 1);
$this->assertEntity('authenticated', 'authenticated user', 2);
// Test the migration of the new role, test role.
$this->assertEntity('test_role', 'test role', 4);
}
}
@@ -0,0 +1,239 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d7;
use Drupal\comment\Entity\CommentType;
use Drupal\Core\Database\Database;
use Drupal\node\Entity\NodeType;
use Drupal\taxonomy\Entity\Vocabulary;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
use Drupal\user\Entity\User;
use Drupal\user\RoleInterface;
use Drupal\user\UserInterface;
/**
* Users migration.
*
* @group user
*/
class MigrateUserTest extends MigrateDrupal7TestBase {
/**
* {@inheritdoc}
*/
public static $modules = [
'comment',
'datetime',
'file',
'image',
'language',
'link',
'node',
'system',
'taxonomy',
'telephone',
'text',
];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
// Prepare to migrate user pictures as well.
$this->installEntitySchema('file');
$this->createType('page');
$this->createType('article');
$this->createType('blog');
$this->createType('book');
$this->createType('forum');
$this->createType('test_content_type');
Vocabulary::create(['vid' => 'test_vocabulary'])->save();
$this->executeMigrations([
'language',
'user_picture_field',
'user_picture_field_instance',
'd7_user_role',
'd7_field',
'd7_field_instance',
'd7_user',
]);
}
/**
* Creates a node type with a corresponding comment type.
*
* @param string $id
* The node type ID.
*/
protected function createType($id) {
NodeType::create([
'type' => $id,
'label' => $this->randomString(),
])->save();
CommentType::create([
'id' => 'comment_node_' . $id,
'label' => $this->randomString(),
'target_entity_type_id' => 'node',
])->save();
}
/**
* Asserts various aspects of a user account.
*
* @param string $id
* The user ID.
* @param string $label
* The username.
* @param string $mail
* The user's email address.
* @param string $password
* The password for this user.
* @param int $created
* The user's creation time.
* @param int $access
* The last access time.
* @param int $login
* The last login time.
* @param bool $blocked
* Whether or not the account is blocked.
* @param string $langcode
* The user account's language code.
* @param string $timezone
* The user account's timezone name.
* @param string $init
* The user's initial email address.
* @param string[] $roles
* Role IDs the user account is expected to have.
* @param int $field_integer
* The value of the integer field.
* @param int|false $field_file_target_id
* (optional) The target ID of the file field.
* @param bool $has_picture
* (optional) Whether the user is expected to have a picture attached.
*/
protected function assertEntity($id, $label, $mail, $password, $created, $access, $login, $blocked, $langcode, $timezone, $init, $roles, $field_integer, $field_file_target_id = FALSE, $has_picture = FALSE) {
/** @var \Drupal\user\UserInterface $user */
$user = User::load($id);
$this->assertTrue($user instanceof UserInterface);
$this->assertSame($label, $user->label());
$this->assertSame($mail, $user->getEmail());
$this->assertSame($password, $user->getPassword());
$this->assertSame($created, $user->getCreatedTime());
$this->assertSame($access, $user->getLastAccessedTime());
$this->assertSame($login, $user->getLastLoginTime());
$this->assertNotSame($blocked, $user->isBlocked());
// Ensure the user's langcode, preferred_langcode and
// preferred_admin_langcode are valid.
// $user->getPreferredLangcode() might fallback to default language if the
// user preferred language is not configured on the site. We just want to
// test if the value was imported correctly.
$language_manager = $this->container->get('language_manager');
$default_langcode = $language_manager->getDefaultLanguage()->getId();
if ($langcode == '') {
$this->assertSame('en', $user->langcode->value);
$this->assertSame($default_langcode, $user->preferred_langcode->value);
$this->assertSame($default_langcode, $user->preferred_admin_langcode->value);
}
elseif ($language_manager->getLanguage($langcode) === NULL) {
$this->assertSame($default_langcode, $user->langcode->value);
$this->assertSame($default_langcode, $user->preferred_langcode->value);
$this->assertSame($default_langcode, $user->preferred_admin_langcode->value);
}
else {
$this->assertSame($langcode, $user->langcode->value);
$this->assertSame($langcode, $user->preferred_langcode->value);
$this->assertSame($langcode, $user->preferred_admin_langcode->value);
}
$this->assertSame($timezone, $user->getTimeZone());
$this->assertSame($init, $user->getInitialEmail());
$this->assertSame($roles, $user->getRoles());
$this->assertSame($has_picture, !$user->user_picture->isEmpty());
if (!is_null($field_integer)) {
$this->assertTrue($user->hasField('field_integer'));
$this->assertEquals($field_integer[0], $user->field_integer->value);
}
if (!empty($field_file_target_id)) {
$this->assertTrue($user->hasField('field_file'));
$this->assertSame($field_file_target_id, $user->field_file->target_id);
}
}
/**
* Tests the Drupal 7 user to Drupal 8 migration.
*/
public function testUser() {
$users = Database::getConnection('default', 'migrate')
->select('users', 'u')
->fields('u')
->condition('uid', 1, '>')
->execute()
->fetchAll();
foreach ($users as $source) {
$rids = Database::getConnection('default', 'migrate')
->select('users_roles', 'ur')
->fields('ur', ['rid'])
->condition('ur.uid', $source->uid)
->execute()
->fetchCol();
$roles = [RoleInterface::AUTHENTICATED_ID];
$id_map = $this->getMigration('d7_user_role')->getIdMap();
foreach ($rids as $rid) {
$role = $id_map->lookupDestinationId([$rid]);
$roles[] = reset($role);
}
$field_integer = Database::getConnection('default', 'migrate')
->select('field_data_field_integer', 'fi')
->fields('fi', ['field_integer_value'])
->condition('fi.entity_id', $source->uid)
->execute()
->fetchCol();
$field_integer = !empty($field_integer) ? $field_integer : NULL;
$field_file = Database::getConnection('default', 'migrate')
->select('field_data_field_file', 'ff')
->fields('ff', ['field_file_fid'])
->condition('ff.entity_id', $source->uid)
->execute()
->fetchField();
$this->assertEntity(
$source->uid,
$source->name,
$source->mail,
$source->pass,
$source->created,
$source->access,
$source->login,
$source->status,
$source->language,
$source->timezone,
$source->init,
$roles,
$field_integer,
$field_file
);
// Ensure that the user can authenticate.
$this->assertEquals($source->uid, $this->container->get('user.auth')->authenticate($source->name, 'a password'));
// After authenticating the password will be rehashed because the password
// stretching iteration count has changed from 15 in Drupal 7 to 16 in
// Drupal 8.
$user = User::load($source->uid);
$rehash = $user->getPassword();
$this->assertNotEquals($source->pass, $rehash);
// Authenticate again and there should be no re-hash.
$this->assertEquals($source->uid, $this->container->get('user.auth')->authenticate($source->name, 'a password'));
$user = User::load($source->uid);
$this->assertEquals($rehash, $user->getPassword());
}
}
}
@@ -0,0 +1,28 @@
<?php
namespace Drupal\Tests\user\Kernel\Migrate\d7;
use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase;
/**
* Tests the user migration plugin class.
*
* @group user
*/
class UserMigrationClassTest extends MigrateDrupal7TestBase {
/**
* Tests d6_profile_values builder.
*
* Ensures profile fields are merged into the d6_profile_values migration's
* process pipeline.
*/
public function testClass() {
$migration = $this->getMigration('d7_user');
/** @var \Drupal\migrate\Plugin\MigrationInterface[] $migrations */
$this->assertIdentical('d7_user', $migration->id());
$process = $migration->getProcess();
$this->assertIdentical('field_file', $process['field_file'][0]['source']);
}
}
@@ -0,0 +1,129 @@
<?php
namespace Drupal\Tests\user\Kernel\Plugin\migrate\source;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests the profile_field source plugin.
*
* @covers \Drupal\user\Plugin\migrate\source\ProfileField
* @group user
*/
class ProfileFieldTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [
[
'source_data' => [],
'expected_data' => [],
],
];
$profile_fields = [
[
'fid' => 1,
'title' => 'First name',
'name' => 'profile_first_name',
'explanation' => 'First name user',
'category' => 'profile',
'page' => '',
'type' => 'textfield',
'weight' => 0,
'required' => 1,
'register' => 0,
'visibility' => 2,
'autocomplete' => 0,
'options' => '',
],
[
'fid' => 2,
'title' => 'Last name',
'name' => 'profile_last_name',
'explanation' => 'Last name user',
'category' => 'profile',
'page' => '',
'type' => 'textfield',
'weight' => 0,
'required' => 0,
'register' => 0,
'visibility' => 2,
'autocomplete' => 0,
'options' => '',
],
[
'fid' => 3,
'title' => 'Policy',
'name' => 'profile_policy',
'explanation' => 'A checkbox that say if you accept policy of website',
'category' => 'profile',
'page' => '',
'type' => 'checkbox',
'weight' => 0,
'required' => 1,
'register' => 1,
'visibility' => 2,
'autocomplete' => 0,
'options' => '',
],
[
'fid' => 4,
'title' => 'Color',
'name' => 'profile_color',
'explanation' => 'A selection that allows user to select a color',
'category' => 'profile',
'page' => '',
'type' => 'selection',
'weight' => 0,
'required' => 0,
'register' => 0,
'visibility' => 2,
'autocomplete' => 0,
'options' => "red\nblue\ngreen",
],
];
$tests[0]['source_data']['profile_fields'] = $profile_fields;
// Profile values are merged with pre-set options of a "selection" field.
$tests[0]['source_data']['profile_values'] = [
[
'fid' => 4,
'uid' => 1,
'value' => 'yellow',
]
];
// Expected options are:
// for "checkbox" fields - array with NULL options
// for "selection" fields - options in both keys and values
$expected_field_options = [
'',
'',
[NULL, NULL],
[
'red' => 'red',
'blue' => 'blue',
'green' => 'green',
'yellow' => 'yellow',
]
];
$tests[0]['expected_data'] = $profile_fields;
foreach ($tests[0]['expected_data'] as $delta => $row) {
$tests[0]['expected_data'][$delta]['options'] = $expected_field_options[$delta];
}
return $tests;
}
}
@@ -0,0 +1,55 @@
<?php
namespace Drupal\Tests\user\Kernel\Plugin\migrate\source;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests the user_picture_instance source plugin.
*
* @covers \Drupal\user\Plugin\migrate\source\UserPictureInstance
* @group user
*/
class UserPictureInstanceTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [];
// The source data.
$tests[0]['source_data']['variable'] = [
[
'name' => 'file_directory',
'value' => serialize(NULL),
],
[
'name' => 'user_picture_file_size',
'value' => serialize(128),
],
[
'name' => 'user_picture_dimensions',
'value' => serialize('128x128'),
],
];
// The expected results.
$tests[0]['expected_data'] = [
[
'id' => '',
'file_directory' => 'pictures',
'max_filesize' => '128KB',
'max_resolution' => '128x128',
],
];
return $tests;
}
}
@@ -0,0 +1,85 @@
<?php
namespace Drupal\Tests\user\Kernel\Plugin\migrate\source\d6;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests the d6_profile_field_values source plugin.
*
* @covers \Drupal\user\Plugin\migrate\source\d6\ProfileFieldValues
* @group user
*/
class ProfileFieldValuesTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [];
// The source data.
$tests[0]['source_data']['profile_values'] = [
[
'fid' => '8',
'uid' => '2',
'value' => 'red',
],
[
'fid' => '9',
'uid' => '2',
'value' => 'Lorem ipsum dolor sit amet...',
],
];
$tests[0]['source_data']['profile_fields'] = [
[
'fid' => '8',
'title' => 'Favorite color',
'name' => 'profile_color',
'explanation' => 'List your favorite color',
'category' => 'Personal information',
'page' => 'Peole whose favorite color is %value',
'type' => 'textfield',
'weight' => '-10',
'required' => '0',
'register' => '1',
'visibility' => '2',
'autocomplete' => '1',
'options' => '',
],
[
'fid' => '9',
'title' => 'Biography',
'name' => 'profile_biography',
'explanation' => 'Tell people a little bit about yourself',
'category' => 'Personal information',
'page' => '',
'type' => 'textarea',
'weight' => '-8',
'required' => '0',
'register' => '0',
'visibility' => '2',
'autocomplete' => '0',
'options' => '',
],
];
// The expected results.
$tests[0]['expected_data'] = [
[
'profile_color' => ['red'],
'profile_biography' => ['Lorem ipsum dolor sit amet...'],
'uid' => '2',
],
];
return $tests;
}
}
@@ -0,0 +1,87 @@
<?php
namespace Drupal\Tests\user\Kernel\Plugin\migrate\source\d6;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests the d6_user_role source plugin.
*
* @covers \Drupal\user\Plugin\migrate\source\d6\Role
* @group user
*/
class RoleTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [
[
'source_data' => [],
'expected_data' => [],
],
];
$roles = [
[
'rid' => 1,
'name' => 'anonymous user',
'permissions' => [
'access content',
],
],
[
'rid' => 2,
'name' => 'authenticated user',
'permissions' => [
'access comments',
'access content',
'post comments',
'post comments without approval',
],
],
[
'rid' => 3,
'name' => 'administrator',
'permissions' => [
'access comments',
'administer comments',
'post comments',
'post comments without approval',
'access content',
'administer content types',
'administer nodes',
],
],
];
// The source data.
foreach ($roles as $role) {
$tests[0]['source_data']['permission'][] = [
'rid' => $role['rid'],
'perm' => implode(', ', $role['permissions']),
];
unset($role['permissions']);
$tests[0]['source_data']['role'][] = $role;
}
$tests[0]['source_data']['filter_formats'] = [
[
'format' => 1,
'roles' => '',
],
];
// The expected results.
$tests[0]['expected_data'] = $roles;
return $tests;
}
}
@@ -0,0 +1,49 @@
<?php
namespace Drupal\Tests\user\Kernel\Plugin\migrate\source\d6;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests the d6_user_picture_file source plugin.
*
* @covers \Drupal\user\Plugin\migrate\source\d6\UserPictureFile
* @group user
*/
class UserPictureFileTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [];
// The source data.
$tests[0]['source_data']['users'] = [
[
'uid' => '2',
'picture' => 'core/modules/simpletest/files/image-test.jpg',
],
[
'uid' => '15',
'picture' => '',
],
];
// The expected results.
$tests[0]['expected_data'] = [
[
'uid' => '2',
'picture' => 'core/modules/simpletest/files/image-test.jpg',
],
];
return $tests;
}
}
@@ -0,0 +1,46 @@
<?php
namespace Drupal\Tests\user\Kernel\Plugin\migrate\source\d6;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests the d6_user_picture source plugin.
*
* @covers \Drupal\user\Plugin\migrate\source\d6\UserPicture
* @group user
*/
class UserPictureTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [];
// The source data.
$tests[0]['source_data']['users'] = [
[
'uid' => 1,
'access' => 1382835435,
'picture' => 'sites/default/files/pictures/picture-1.jpg',
],
[
'uid' => 2,
'access' => 1382835436,
'picture' => 'sites/default/files/pictures/picture-2.jpg',
],
];
// User picture data model is identical in source input and output.
$tests[0]['expected_data'] = $tests[0]['source_data']['users'];
return $tests;
}
}
@@ -0,0 +1,83 @@
<?php
namespace Drupal\Tests\user\Kernel\Plugin\migrate\source\d6;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests the d6_user source plugin.
*
* @covers \Drupal\user\Plugin\migrate\source\d6\User
* @group user
*/
class UserTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [];
// The source data.
$tests[0]['source_data']['users'] = [
[
'uid' => 2,
'name' => 'admin',
'pass' => '1234',
'mail' => 'admin@example.com',
'theme' => '',
'signature' => '',
'signature_format' => 0,
'created' => 1279402616,
'access' => 1322981278,
'login' => 1322699994,
'status' => 0,
'timezone' => 'America/Lima',
'language' => 'en',
// @todo Add the file when needed.
'picture' => 'sites/default/files/pictures/picture-1.jpg',
'init' => 'admin@example.com',
'data' => NULL,
],
[
'uid' => 4,
'name' => 'alice',
// @todo d6 hash?
'pass' => '1234',
'mail' => 'alice@example.com',
'theme' => '',
'signature' => '',
'signature_format' => 0,
'created' => 1322981368,
'access' => 1322982419,
'login' => 132298140,
'status' => 0,
'timezone' => 'America/Lima',
'language' => 'en',
'picture' => '',
'init' => 'alice@example.com',
'data' => NULL,
],
];
// getDatabase() will not create empty tables, so we need to insert data
// even if it's irrelevant to the test.
$tests[0]['source_data']['users_roles'] = [
[
'uid' => 99,
'rid' => 99,
],
];
// The expected results.
$tests[0]['expected_data'] = $tests[0]['source_data']['users'];
return $tests;
}
}
@@ -0,0 +1,72 @@
<?php
namespace Drupal\Tests\user\Kernel\Plugin\migrate\source\d7;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests the d7_user_role source plugin.
*
* @covers \Drupal\user\Plugin\migrate\source\d7\Role
* @group user
*/
class RoleTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['migrate_drupal', 'user'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$expected = [
[
'rid' => 1,
'name' => 'anonymous user',
'permissions' => [
'access content',
],
],
[
'rid' => 2,
'name' => 'authenticated user',
'permissions' => [
'access comments',
'access content',
'post comments',
'post comments without approval',
],
],
[
'rid' => 3,
'name' => 'administrator',
'permissions' => [
'access comments',
'administer comments',
'post comments',
'post comments without approval',
'access content',
'administer content types',
'administer nodes',
],
],
];
$data = [
[[], $expected],
];
foreach ($expected as $row) {
foreach ($row['permissions'] as $permission) {
$data[0][0]['role_permission'][] = [
'permission' => $permission,
'rid' => $row['rid'],
];
}
unset($row['permissions']);
$data[0][0]['role'][] = $row;
}
return $data;
}
}
@@ -0,0 +1,120 @@
<?php
namespace Drupal\Tests\user\Kernel\Plugin\migrate\source\d7;
use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase;
/**
* Tests the d7_user source plugin.
*
* @covers \Drupal\user\Plugin\migrate\source\d7\User
* @group user
*/
class UserTest extends MigrateSqlSourceTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'migrate_drupal'];
/**
* {@inheritdoc}
*/
public function providerSource() {
$tests = [];
// The source data.
$tests[0]['source_data']['field_config_instance'] = [
[
'id' => '33',
'field_id' => '11',
'field_name' => 'field_file',
'entity_type' => 'user',
'bundle' => 'user',
'data' => 'a:0:{}',
'deleted' => '0',
],
];
$tests[0]['source_data']['field_data_field_file'] = [
[
'entity_type' => 'user',
'bundle' => 'user',
'deleted' => 0,
'entity_id' => 2,
'revision_id' => NULL,
'language' => 'und',
'delta' => 0,
'field_file_fid' => 99,
'field_file_display' => 1,
'field_file_description' => 'None',
],
];
$tests[0]['source_data']['role'] = [
[
'rid' => 2,
'name' => 'authenticated user',
'weight' => 0,
],
];
$tests[0]['source_data']['users'] = [
[
'uid' => '2',
'name' => 'Odo',
'pass' => '$S$DVpvPItXvnsmF3giVEe7Jy2lG.SCoEs8uKwpHsyPvdeNAaNZYxZ8',
'mail' => 'odo@local.host',
'theme' => '',
'signature' => '',
'signature_format' => 'filtered_html',
'created' => '1432750741',
'access' => '0',
'login' => '0',
'status' => '1',
'timezone' => 'America/Chicago',
'language' => '',
'picture' => '0',
'init' => 'odo@local.host',
'data' => 'a:1:{s:7:"contact";i:1;}',
],
];
$tests[0]['source_data']['users_roles'] = [
[
'uid' => 2,
'rid' => 2,
],
];
// The expected results.
$tests[0]['expected_data'] = [
[
'uid' => '2',
'name' => 'Odo',
'pass' => '$S$DVpvPItXvnsmF3giVEe7Jy2lG.SCoEs8uKwpHsyPvdeNAaNZYxZ8',
'mail' => 'odo@local.host',
'signature' => '',
'signature_format' => 'filtered_html',
'created' => '1432750741',
'access' => '0',
'login' => '0',
'status' => '1',
'timezone' => 'America/Chicago',
'language' => '',
'picture' => '0',
'init' => 'odo@local.host',
'roles' => [2],
'data' => [
'contact' => 1,
],
'field_file' => [
[
'fid' => 99,
'display' => 1,
'description' => 'None',
],
],
],
];
return $tests;
}
}
@@ -0,0 +1,146 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\Core\KeyValueStore\KeyValueExpirableFactory;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\SharedTempStoreFactory;
use Drupal\Core\Lock\DatabaseLockBackend;
use Drupal\Core\Database\Database;
/**
* Tests the temporary object storage system.
*
* @group user
* @see \Drupal\Core\TempStore\TempStore.
*/
class TempStoreDatabaseTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['system', 'user'];
/**
* A key/value store factory.
*
* @var \Drupal\user\SharedTempStoreFactory
*/
protected $storeFactory;
/**
* The name of the key/value collection to set and retrieve.
*
* @var string
*/
protected $collection;
/**
* An array of (fake) user IDs.
*
* @var array
*/
protected $users = [];
/**
* An array of random stdClass objects.
*
* @var array
*/
protected $objects = [];
protected function setUp() {
parent::setUp();
// Install system tables to test the key/value storage without installing a
// full Drupal environment.
$this->installSchema('system', ['key_value_expire']);
// Create several objects for testing.
for ($i = 0; $i <= 3; $i++) {
$this->objects[$i] = $this->randomObject();
}
}
/**
* Tests the UserTempStore API.
*/
public function testUserTempStore() {
// Create a key/value collection.
$factory = new SharedTempStoreFactory(new KeyValueExpirableFactory(\Drupal::getContainer()), new DatabaseLockBackend(Database::getConnection()), $this->container->get('request_stack'));
$collection = $this->randomMachineName();
// Create two mock users.
for ($i = 0; $i <= 1; $i++) {
$users[$i] = mt_rand(500, 5000000);
// Storing the SharedTempStore objects in a class member variable causes a
// fatal exception, because in that situation garbage collection is not
// triggered until the test class itself is destructed, after tearDown()
// has deleted the database tables. Store the objects locally instead.
$stores[$i] = $factory->get($collection, $users[$i]);
}
$key = $this->randomMachineName();
// Test that setIfNotExists() succeeds only the first time.
for ($i = 0; $i <= 1; $i++) {
// setIfNotExists() should be TRUE the first time (when $i is 0) and
// FALSE the second time (when $i is 1).
$this->assertEqual(!$i, $stores[0]->setIfNotExists($key, $this->objects[$i]));
$metadata = $stores[0]->getMetadata($key);
$this->assertEqual($users[0], $metadata->owner);
$this->assertIdenticalObject($this->objects[0], $stores[0]->get($key));
// Another user should get the same result.
$metadata = $stores[1]->getMetadata($key);
$this->assertEqual($users[0], $metadata->owner);
$this->assertIdenticalObject($this->objects[0], $stores[1]->get($key));
}
// Remove the item and try to set it again.
$stores[0]->delete($key);
$stores[0]->setIfNotExists($key, $this->objects[1]);
// This time it should succeed.
$this->assertIdenticalObject($this->objects[1], $stores[0]->get($key));
// This user can update the object.
$stores[0]->set($key, $this->objects[2]);
$this->assertIdenticalObject($this->objects[2], $stores[0]->get($key));
// The object is the same when another user loads it.
$this->assertIdenticalObject($this->objects[2], $stores[1]->get($key));
// This user should be allowed to get, update, delete.
$this->assertTrue($stores[0]->getIfOwner($key) instanceof \stdClass);
$this->assertTrue($stores[0]->setIfOwner($key, $this->objects[1]));
$this->assertTrue($stores[0]->deleteIfOwner($key));
// Another user can update the object and become the owner.
$stores[1]->set($key, $this->objects[3]);
$this->assertIdenticalObject($this->objects[3], $stores[0]->get($key));
$this->assertIdenticalObject($this->objects[3], $stores[1]->get($key));
$metadata = $stores[1]->getMetadata($key);
$this->assertEqual($users[1], $metadata->owner);
// The first user should be informed that the second now owns the data.
$metadata = $stores[0]->getMetadata($key);
$this->assertEqual($users[1], $metadata->owner);
// The first user should no longer be allowed to get, update, delete.
$this->assertNull($stores[0]->getIfOwner($key));
$this->assertFalse($stores[0]->setIfOwner($key, $this->objects[1]));
$this->assertFalse($stores[0]->deleteIfOwner($key));
// Now manually expire the item (this is not exposed by the API) and then
// assert it is no longer accessible.
db_update('key_value_expire')
->fields(['expire' => REQUEST_TIME - 1])
->condition('collection', "user.shared_tempstore.$collection")
->condition('name', $key)
->execute();
$this->assertFalse($stores[0]->get($key));
$this->assertFalse($stores[1]->get($key));
}
}
@@ -0,0 +1,146 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\Core\Form\FormState;
use Drupal\KernelTests\KernelTestBase;
/**
* Verifies that the field order in user account forms is compatible with
* password managers of web browsers.
*
* @group user
*/
class UserAccountFormFieldsTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['system', 'user', 'field'];
/**
* Tests the root user account form section in the "Configure site" form.
*/
public function testInstallConfigureForm() {
require_once \Drupal::root() . '/core/includes/install.core.inc';
require_once \Drupal::root() . '/core/includes/install.inc';
$install_state = install_state_defaults();
$form_state = new FormState();
$form_state->addBuildInfo('args', [&$install_state]);
$form = $this->container->get('form_builder')
->buildForm('Drupal\Core\Installer\Form\SiteConfigureForm', $form_state);
// Verify name and pass field order.
$this->assertFieldOrder($form['admin_account']['account']);
// Verify that web browsers may autocomplete the email value and
// autofill/prefill the name and pass values.
foreach (['mail', 'name', 'pass'] as $key) {
$this->assertFalse(isset($form['account'][$key]['#attributes']['autocomplete']), "'$key' field: 'autocomplete' attribute not found.");
}
}
/**
* Tests the user registration form.
*/
public function testUserRegistrationForm() {
// Install default configuration; required for AccountFormController.
$this->installConfig(['user']);
// Disable email confirmation to unlock the password field.
$this->config('user.settings')
->set('verify_mail', FALSE)
->save();
$form = $this->buildAccountForm('register');
// Verify name and pass field order.
$this->assertFieldOrder($form['account']);
// Verify that web browsers may autocomplete the email value and
// autofill/prefill the name and pass values.
foreach (['mail', 'name', 'pass'] as $key) {
$this->assertFalse(isset($form['account'][$key]['#attributes']['autocomplete']), "'$key' field: 'autocomplete' attribute not found.");
}
}
/**
* Tests the user edit form.
*/
public function testUserEditForm() {
// Install default configuration; required for AccountFormController.
$this->installConfig(['user']);
// Install the router table and then rebuild.
\Drupal::service('router.builder')->rebuild();
$form = $this->buildAccountForm('default');
// Verify name and pass field order.
$this->assertFieldOrder($form['account']);
// Verify that autocomplete is off on all account fields.
foreach (['mail', 'name', 'pass'] as $key) {
$this->assertIdentical($form['account'][$key]['#attributes']['autocomplete'], 'off', "'$key' field: 'autocomplete' attribute is 'off'.");
}
}
/**
* Asserts that the 'name' form element is directly before the 'pass' element.
*
* @param array $elements
* A form array section that contains the user account form elements.
*/
protected function assertFieldOrder(array $elements) {
$name_index = 0;
$name_weight = 0;
$pass_index = 0;
$pass_weight = 0;
$index = 0;
foreach ($elements as $key => $element) {
if ($key === 'name') {
$name_index = $index;
$name_weight = $element['#weight'];
$this->assertTrue($element['#sorted'], "'name' field is #sorted.");
}
elseif ($key === 'pass') {
$pass_index = $index;
$pass_weight = $element['#weight'];
$this->assertTrue($element['#sorted'], "'pass' field is #sorted.");
}
$index++;
}
$this->assertEqual($name_index, $pass_index - 1, "'name' field ($name_index) appears before 'pass' field ($pass_index).");
$this->assertTrue($name_weight < $pass_weight, "'name' field weight ($name_weight) is smaller than 'pass' field weight ($pass_weight).");
}
/**
* Builds the user account form for a given operation.
*
* @param string $operation
* The entity operation; one of 'register' or 'default'.
*
* @return array
* The form array.
*/
protected function buildAccountForm($operation) {
// @see HtmlEntityFormController::getFormObject()
$entity_type = 'user';
$fields = [];
if ($operation != 'register') {
$fields['uid'] = 2;
}
$entity = $this->container->get('entity.manager')
->getStorage($entity_type)
->create($fields);
$this->container->get('entity.manager')
->getFormObject($entity_type, $operation)
->setEntity($entity);
// @see EntityFormBuilder::getForm()
return $this->container->get('entity.form_builder')->getForm($entity, $operation);
}
}
@@ -0,0 +1,44 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\Tests\SchemaCheckTestTrait;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\Entity\Role;
/**
* Ensures the user action for adding and removing roles have valid config
* schema.
*
* @group user
*/
class UserActionConfigSchemaTest extends KernelTestBase {
use SchemaCheckTestTrait;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['system', 'user'];
/**
* Tests whether the user action config schema are valid.
*/
public function testValidUserActionConfigSchema() {
$rid = strtolower($this->randomMachineName(8));
Role::create(['id' => $rid])->save();
// Test user_add_role_action configuration.
$config = $this->config('system.action.user_add_role_action.' . $rid);
$this->assertEqual($config->get('id'), 'user_add_role_action.' . $rid);
$this->assertConfigSchema(\Drupal::service('config.typed'), $config->getName(), $config->get());
// Test user_remove_role_action configuration.
$config = $this->config('system.action.user_remove_role_action.' . $rid);
$this->assertEqual($config->get('id'), 'user_remove_role_action.' . $rid);
$this->assertConfigSchema(\Drupal::service('config.typed'), $config->getName(), $config->get());
}
}
@@ -0,0 +1,98 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
use Drupal\field\Entity\FieldConfig;
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
use Drupal\user\Entity\Role;
/**
* Tests the user reference field functionality.
*
* @group user
*/
class UserEntityReferenceTest extends EntityKernelTestBase {
use EntityReferenceTestTrait;
/**
* A randomly-generated role for testing purposes.
*
* @var \Drupal\user\RoleInterface
*/
protected $role1;
/**
* A randomly-generated role for testing purposes.
*
* @var \Drupal\user\RoleInterface
*/
protected $role2;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->role1 = Role::create([
'id' => strtolower($this->randomMachineName(8)),
'label' => $this->randomMachineName(8),
]);
$this->role1->save();
$this->role2 = Role::create([
'id' => strtolower($this->randomMachineName(8)),
'label' => $this->randomMachineName(8),
]);
$this->role2->save();
$this->createEntityReferenceField('user', 'user', 'user_reference', 'User reference', 'user');
}
/**
* Tests user selection by roles.
*/
public function testUserSelectionByRole() {
$field_definition = FieldConfig::loadByName('user', 'user', 'user_reference');
$handler_settings = $field_definition->getSetting('handler_settings');
$handler_settings['filter']['role'] = [
$this->role1->id() => $this->role1->id(),
$this->role2->id() => 0,
];
$handler_settings['filter']['type'] = 'role';
$field_definition->setSetting('handler_settings', $handler_settings);
$field_definition->save();
$user1 = $this->createUser(['name' => 'aabb']);
$user1->addRole($this->role1->id());
$user1->save();
$user2 = $this->createUser(['name' => 'aabbb']);
$user2->addRole($this->role1->id());
$user2->save();
$user3 = $this->createUser(['name' => 'aabbbb']);
$user3->addRole($this->role2->id());
$user3->save();
/** @var \Drupal\Core\Entity\EntityAutocompleteMatcher $autocomplete */
$autocomplete = \Drupal::service('entity.autocomplete_matcher');
$matches = $autocomplete->getMatches('user', 'default', $field_definition->getSetting('handler_settings'), 'aabb');
$this->assertEqual(count($matches), 2);
$users = [];
foreach ($matches as $match) {
$users[] = $match['label'];
}
$this->assertTrue(in_array($user1->label(), $users));
$this->assertTrue(in_array($user2->label(), $users));
$this->assertFalse(in_array($user3->label(), $users));
$matches = $autocomplete->getMatches('user', 'default', $field_definition->getSetting('handler_settings'), 'aabbbb');
$this->assertEqual(count($matches), 0, '');
}
}
@@ -0,0 +1,68 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\Entity\User;
use Drupal\user\RoleInterface;
/**
* Tests the user entity class.
*
* @group user
* @see \Drupal\user\Entity\User
*/
class UserEntityTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['system', 'user', 'field'];
/**
* Tests some of the methods.
*
* @see \Drupal\user\Entity\User::getRoles()
* @see \Drupal\user\Entity\User::addRole()
* @see \Drupal\user\Entity\User::removeRole()
*/
public function testUserMethods() {
$role_storage = $this->container->get('entity.manager')->getStorage('user_role');
$role_storage->create(['id' => 'test_role_one'])->save();
$role_storage->create(['id' => 'test_role_two'])->save();
$role_storage->create(['id' => 'test_role_three'])->save();
$values = [
'uid' => 1,
'roles' => ['test_role_one'],
];
$user = User::create($values);
$this->assertTrue($user->hasRole('test_role_one'));
$this->assertFalse($user->hasRole('test_role_two'));
$this->assertEqual([RoleInterface::AUTHENTICATED_ID, 'test_role_one'], $user->getRoles());
$user->addRole('test_role_one');
$this->assertTrue($user->hasRole('test_role_one'));
$this->assertFalse($user->hasRole('test_role_two'));
$this->assertEqual([RoleInterface::AUTHENTICATED_ID, 'test_role_one'], $user->getRoles());
$user->addRole('test_role_two');
$this->assertTrue($user->hasRole('test_role_one'));
$this->assertTrue($user->hasRole('test_role_two'));
$this->assertEqual([RoleInterface::AUTHENTICATED_ID, 'test_role_one', 'test_role_two'], $user->getRoles());
$user->removeRole('test_role_three');
$this->assertTrue($user->hasRole('test_role_one'));
$this->assertTrue($user->hasRole('test_role_two'));
$this->assertEqual([RoleInterface::AUTHENTICATED_ID, 'test_role_one', 'test_role_two'], $user->getRoles());
$user->removeRole('test_role_one');
$this->assertFalse($user->hasRole('test_role_one'));
$this->assertTrue($user->hasRole('test_role_two'));
$this->assertEqual([RoleInterface::AUTHENTICATED_ID, 'test_role_two'], $user->getRoles());
}
}
@@ -0,0 +1,52 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\user\Entity\User;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests available user fields in twig.
*
* @group user
*/
class UserFieldsTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['user', 'system'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('user');
// Set up a test theme that prints the user's mail field.
\Drupal::service('theme_handler')->install(['user_test_theme']);
\Drupal::theme()->setActiveTheme(\Drupal::service('theme.initialization')->initTheme('user_test_theme'));
// Clear the theme registry.
$this->container->set('theme.registry', NULL);
}
/**
* Tests account's available fields.
*/
public function testUserFields() {
// Create the user to test the user fields.
$user = User::create([
'name' => 'foobar',
'mail' => 'foobar@example.com',
]);
$build = user_view($user);
$output = \Drupal::service('renderer')->renderRoot($build);
$this->setRawContent($output);
$userEmail = $user->getEmail();
$this->assertText($userEmail, "User's mail field is found in the twig template");
}
}
@@ -0,0 +1,54 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\KernelTests\KernelTestBase;
/**
* Tests user_install().
*
* @group user
*/
class UserInstallTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['user'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->container->get('module_handler')->loadInclude('user', 'install');
$this->installEntitySchema('user');
user_install();
}
/**
* Test that the initial users have correct values.
*/
public function testUserInstall() {
$result = db_query('SELECT u.uid, u.uuid, u.langcode, uf.status FROM {users} u INNER JOIN {users_field_data} uf ON u.uid=uf.uid ORDER BY u.uid')
->fetchAllAssoc('uid');
$anon = $result[0];
$admin = $result[1];
$this->assertFalse(empty($anon->uuid), 'Anon user has a UUID');
$this->assertFalse(empty($admin->uuid), 'Admin user has a UUID');
// Test that the anonymous and administrators languages are equal to the
// site's default language.
$this->assertEqual($anon->langcode, \Drupal::languageManager()->getDefaultLanguage()->getId());
$this->assertEqual($admin->langcode, \Drupal::languageManager()->getDefaultLanguage()->getId());
// Test that the administrator is active.
$this->assertEqual($admin->status, 1);
// Test that the anonymous user is blocked.
$this->assertEqual($anon->status, 0);
}
}
@@ -0,0 +1,74 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\Entity\User;
/**
* Tests the handling of user_role entity from the user module
*
* @group user
*/
class UserRoleDeleteTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['system', 'user', 'field'];
protected function setUp() {
parent::setUp();
$this->installEntitySchema('user');
}
/**
* Tests removal of role references on role entity delete.
*
* @see user_user_role_delete()
*/
public function testRoleDeleteUserRoleReferenceDelete() {
// Create two test roles.
$role_storage = $this->container->get('entity.manager')->getStorage('user_role');
$role_storage->create(['id' => 'test_role_one'])->save();
$role_storage->create(['id' => 'test_role_two'])->save();
// Create user and assign both test roles.
$values = [
'uid' => 1,
'name' => $this->randomString(),
'roles' => ['test_role_one', 'test_role_two'],
];
$user = User::create($values);
$user->save();
// Check that user has both roles.
$this->assertTrue($user->hasRole('test_role_one'));
$this->assertTrue($user->hasRole('test_role_two'));
// Delete test role one.
$test_role_one = $role_storage->load('test_role_one');
$test_role_one->delete();
// Load user again from the database.
$user = User::load($user->id());
// Check that user does not have role one anymore, still has role two.
$this->assertFalse($user->hasRole('test_role_one'));
$this->assertTrue($user->hasRole('test_role_two'));
// Create new role with same name.
$role_storage->create(['id' => 'test_role_one'])->save();
// Load user again from the database.
$user = User::load($user->id());
// Check that user does not have role one.
$this->assertFalse($user->hasRole('test_role_one'));
$this->assertTrue($user->hasRole('test_role_two'));
}
}
@@ -0,0 +1,30 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\Entity\Role;
/**
* @group user
*/
class UserRoleEntityTest extends KernelTestBase {
public static $modules = ['system', 'user'];
public function testOrderOfPermissions() {
$role = Role::create(['id' => 'test_role']);
$role->grantPermission('b')
->grantPermission('a')
->grantPermission('c')
->save();
$this->assertEquals($role->getPermissions(), ['a', 'b', 'c']);
$role->revokePermission('b')->save();
$this->assertEquals($role->getPermissions(), ['a', 'c']);
$role->grantPermission('b')->save();
$this->assertEquals($role->getPermissions(), ['a', 'b', 'c']);
}
}
@@ -0,0 +1,48 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\Entity\User;
/**
* Tests user saving status.
*
* @group user
*/
class UserSaveStatusTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['system', 'user', 'field'];
protected function setUp() {
parent::setUp();
$this->installEntitySchema('user');
}
/**
* Test SAVED_NEW and SAVED_UPDATED statuses for user entity type.
*/
public function testUserSaveStatus() {
// Create a new user.
$values = [
'uid' => 1,
'name' => $this->randomMachineName(),
];
$user = User::create($values);
// Test SAVED_NEW.
$return = $user->save();
$this->assertEqual($return, SAVED_NEW, "User was saved with SAVED_NEW status.");
// Test SAVED_UPDATED.
$user->name = $this->randomMachineName();
$return = $user->save();
$this->assertEqual($return, SAVED_UPDATED, "User was saved with SAVED_UPDATED status.");
}
}
@@ -0,0 +1,216 @@
<?php
namespace Drupal\Tests\user\Kernel;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Language\Language;
use Drupal\Core\Render\Element\Email;
use Drupal\KernelTests\KernelTestBase;
use Drupal\user\Entity\Role;
use Drupal\user\Entity\User;
/**
* Verify that user validity checks behave as designed.
*
* @group user
*/
class UserValidationTest extends KernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['field', 'user', 'system'];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('user');
$this->installSchema('system', ['sequences']);
// Make sure that the default roles exist.
$this->installConfig(['user']);
}
/**
* Tests user name validation.
*/
public function testUsernames() {
$test_cases = [ // '<username>' => array('<description>', 'assert<testName>'),
'foo' => ['Valid username', 'assertNull'],
'FOO' => ['Valid username', 'assertNull'],
'Foo O\'Bar' => ['Valid username', 'assertNull'],
'foo@bar' => ['Valid username', 'assertNull'],
'foo@example.com' => ['Valid username', 'assertNull'],
'foo@-example.com' => ['Valid username', 'assertNull'], // invalid domains are allowed in usernames
'þòøÇߪř€' => ['Valid username', 'assertNull'],
'foo+bar' => ['Valid username', 'assertNull'], // '+' symbol is allowed
'ᚠᛇᚻ᛫ᛒᛦᚦ' => ['Valid UTF8 username', 'assertNull'], // runes
' foo' => ['Invalid username that starts with a space', 'assertNotNull'],
'foo ' => ['Invalid username that ends with a space', 'assertNotNull'],
'foo bar' => ['Invalid username that contains 2 spaces \'&nbsp;&nbsp;\'', 'assertNotNull'],
'' => ['Invalid empty username', 'assertNotNull'],
'foo/' => ['Invalid username containing invalid chars', 'assertNotNull'],
'foo' . chr(0) . 'bar' => ['Invalid username containing chr(0)', 'assertNotNull'], // NULL
'foo' . chr(13) . 'bar' => ['Invalid username containing chr(13)', 'assertNotNull'], // CR
str_repeat('x', USERNAME_MAX_LENGTH + 1) => ['Invalid excessively long username', 'assertNotNull'],
];
foreach ($test_cases as $name => $test_case) {
list($description, $test) = $test_case;
$result = user_validate_name($name);
$this->$test($result, $description . ' (' . $name . ')');
}
}
/**
* Runs entity validation checks.
*/
public function testValidation() {
$user = User::create([
'name' => 'test',
'mail' => 'test@example.com',
]);
$violations = $user->validate();
$this->assertEqual(count($violations), 0, 'No violations when validating a default user.');
// Only test one example invalid name here, the rest is already covered in
// the testUsernames() method in this class.
$name = $this->randomMachineName(61);
$user->set('name', $name);
$violations = $user->validate();
$this->assertEqual(count($violations), 1, 'Violation found when name is too long.');
$this->assertEqual($violations[0]->getPropertyPath(), 'name');
$this->assertEqual($violations[0]->getMessage(), t('The username %name is too long: it must be %max characters or less.', ['%name' => $name, '%max' => 60]));
// Create a second test user to provoke a name collision.
$user2 = User::create([
'name' => 'existing',
'mail' => 'existing@example.com',
]);
$user2->save();
$user->set('name', 'existing');
$violations = $user->validate();
$this->assertEqual(count($violations), 1, 'Violation found on name collision.');
$this->assertEqual($violations[0]->getPropertyPath(), 'name');
$this->assertEqual($violations[0]->getMessage(), t('The username %name is already taken.', ['%name' => 'existing']));
// Make the name valid.
$user->set('name', $this->randomMachineName());
$user->set('mail', 'invalid');
$violations = $user->validate();
$this->assertEqual(count($violations), 1, 'Violation found when email is invalid');
$this->assertEqual($violations[0]->getPropertyPath(), 'mail.0.value');
$this->assertEqual($violations[0]->getMessage(), t('This value is not a valid email address.'));
$mail = $this->randomMachineName(Email::EMAIL_MAX_LENGTH - 11) . '@example.com';
$user->set('mail', $mail);
$violations = $user->validate();
// @todo There are two violations because EmailItem::getConstraints()
// overlaps with the implicit constraint of the 'email' property type used
// in EmailItem::propertyDefinitions(). Resolve this in
// https://www.drupal.org/node/2023465.
$this->assertEqual(count($violations), 2, 'Violations found when email is too long');
$this->assertEqual($violations[0]->getPropertyPath(), 'mail.0.value');
$this->assertEqual($violations[0]->getMessage(), t('%name: the email address can not be longer than @max characters.', ['%name' => $user->get('mail')->getFieldDefinition()->getLabel(), '@max' => Email::EMAIL_MAX_LENGTH]));
$this->assertEqual($violations[1]->getPropertyPath(), 'mail.0.value');
$this->assertEqual($violations[1]->getMessage(), t('This value is not a valid email address.'));
// Provoke an email collision with an existing user.
$user->set('mail', 'existing@example.com');
$violations = $user->validate();
$this->assertEqual(count($violations), 1, 'Violation found when email already exists.');
$this->assertEqual($violations[0]->getPropertyPath(), 'mail');
$this->assertEqual($violations[0]->getMessage(), t('The email address %mail is already taken.', ['%mail' => 'existing@example.com']));
$user->set('mail', NULL);
$violations = $user->validate();
$this->assertEqual(count($violations), 1, 'Email addresses may not be removed');
$this->assertEqual($violations[0]->getPropertyPath(), 'mail');
$this->assertEqual($violations[0]->getMessage(), t('@name field is required.', ['@name' => $user->getFieldDefinition('mail')->getLabel()]));
$user->set('mail', 'someone@example.com');
$user->set('timezone', $this->randomString(33));
$this->assertLengthViolation($user, 'timezone', 32, 2, 1);
$user->set('timezone', 'invalid zone');
$this->assertAllowedValuesViolation($user, 'timezone');
$user->set('timezone', NULL);
$user->set('init', 'invalid');
$violations = $user->validate();
$this->assertEqual(count($violations), 1, 'Violation found when init email is invalid');
$user->set('init', NULL);
$user->set('langcode', 'invalid');
$this->assertAllowedValuesViolation($user, 'langcode');
$user->set('langcode', NULL);
// Only configurable langcodes are allowed for preferred languages.
$user->set('preferred_langcode', Language::LANGCODE_NOT_SPECIFIED);
$this->assertAllowedValuesViolation($user, 'preferred_langcode');
$user->set('preferred_langcode', NULL);
$user->set('preferred_admin_langcode', Language::LANGCODE_NOT_SPECIFIED);
$this->assertAllowedValuesViolation($user, 'preferred_admin_langcode');
$user->set('preferred_admin_langcode', NULL);
Role::create(['id' => 'role1'])->save();
Role::create(['id' => 'role2'])->save();
// Test cardinality of user roles.
$user = User::create([
'name' => 'role_test',
'mail' => 'test@example.com',
'roles' => ['role1', 'role2'],
]);
$violations = $user->validate();
$this->assertEqual(count($violations), 0);
$user->roles[1]->target_id = 'unknown_role';
$violations = $user->validate();
$this->assertEqual(count($violations), 1);
$this->assertEqual($violations[0]->getPropertyPath(), 'roles.1.target_id');
$this->assertEqual($violations[0]->getMessage(), t('The referenced entity (%entity_type: %name) does not exist.', ['%entity_type' => 'user_role', '%name' => 'unknown_role']));
}
/**
* Verifies that a length violation exists for the given field.
*
* @param \Drupal\core\Entity\EntityInterface $entity
* The entity object to validate.
* @param string $field_name
* The field that violates the maximum length.
* @param int $length
* Number of characters that was exceeded.
* @param int $count
* (optional) The number of expected violations. Defaults to 1.
* @param int $expected_index
* (optional) The index at which to expect the violation. Defaults to 0.
*/
protected function assertLengthViolation(EntityInterface $entity, $field_name, $length, $count = 1, $expected_index = 0) {
$violations = $entity->validate();
$this->assertEqual(count($violations), $count, "Violation found when $field_name is too long.");
$this->assertEqual($violations[$expected_index]->getPropertyPath(), "$field_name.0.value");
$field_label = $entity->get($field_name)->getFieldDefinition()->getLabel();
$this->assertEqual($violations[$expected_index]->getMessage(), t('%name: may not be longer than @max characters.', ['%name' => $field_label, '@max' => $length]));
}
/**
* Verifies that a AllowedValues violation exists for the given field.
*
* @param \Drupal\core\Entity\EntityInterface $entity
* The entity object to validate.
* @param string $field_name
* The name of the field to verify.
*/
protected function assertAllowedValuesViolation(EntityInterface $entity, $field_name) {
$violations = $entity->validate();
$this->assertEqual(count($violations), 1, "Allowed values violation for $field_name found.");
$this->assertEqual($violations[0]->getPropertyPath(), "$field_name.0.value");
$this->assertEqual($violations[0]->getMessage(), t('The value you selected is not a valid choice.'));
}
}
@@ -0,0 +1,53 @@
<?php
namespace Drupal\Tests\user\Kernel\Views;
use Drupal\views\Views;
/**
* Tests the permission field handler.
*
* @group user
* @see \Drupal\user\Plugin\views\field\Permissions
*/
class HandlerFieldPermissionTest extends UserKernelTestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_field_permission'];
/**
* Tests the permission field handler output.
*/
public function testFieldPermission() {
$this->setupPermissionTestData();
$view = Views::getView('test_field_permission');
$this->executeView($view);
$view->initStyle();
$view->render();
$style_plugin = $view->style_plugin;
$expected_permissions = [];
$expected_permissions[$this->users[0]->id()] = [];
$expected_permissions[$this->users[1]->id()] = [];
$expected_permissions[$this->users[2]->id()][] = t('Administer permissions');
// View user profiles comes first, because we sort by the permission
// machine name.
$expected_permissions[$this->users[3]->id()][] = t('View user information');
$expected_permissions[$this->users[3]->id()][] = t('Administer permissions');
$expected_permissions[$this->users[3]->id()][] = t('Administer users');
foreach ($view->result as $index => $row) {
$uid = $view->field['uid']->getValue($row);
$rendered_permission = $style_plugin->getField($index, 'permission');
$expected_output = implode(', ', $expected_permissions[$uid]);
$this->assertEqual($rendered_permission, $expected_output, 'The right permissions are rendered.');
}
}
}
@@ -0,0 +1,95 @@
<?php
namespace Drupal\Tests\user\Kernel\Views;
use Drupal\views\Views;
use Drupal\Core\Session\AnonymousUserSession;
/**
* Tests the current user filter handler.
*
* @group user
* @see \Drupal\user\Plugin\views\filter\Current
*/
class HandlerFilterCurrentUserTest extends UserKernelTestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_filter_current_user'];
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountProxy
*/
protected $currentUser;
/**
* {@inheritdoc}
*/
protected function setUp($import_test_views = TRUE) {
parent::setUp();
$this->currentUser = $this->container->get('current_user');
$this->setupPermissionTestData();
}
/**
* Tests the current user filter handler with anonymous user.
*/
public function testFilterCurrentUserAsAnonymous() {
$column_map = ['uid' => 'uid'];
$this->currentUser->setAccount(new AnonymousUserSession());
$view = Views::getView('test_filter_current_user');
$view->initHandlers();
$view->filter['uid_current']->value = 0;
$this->executeView($view);
$expected[] = ['uid' => 1];
$expected[] = ['uid' => 2];
$expected[] = ['uid' => 3];
$expected[] = ['uid' => 4];
$this->assertIdenticalResultset($view, $expected, $column_map, 'Anonymous account can view all accounts when current filter is FALSE.');
$view->destroy();
$view = Views::getView('test_filter_current_user');
$view->initHandlers();
$view->filter['uid_current']->value = 1;
$this->executeView($view);
$expected = [];
$this->assertIdenticalResultset($view, $expected, $column_map, 'Anonymous account can view zero accounts when current filter is TRUE.');
$view->destroy();
}
/**
* Tests the current user filter handler with logged-in user.
*/
public function testFilterCurrentUserAsUser() {
$column_map = ['uid' => 'uid'];
$user = reset($this->users);
$this->currentUser->setAccount($user);
$view = Views::getView('test_filter_current_user');
$view->initHandlers();
$view->filter['uid_current']->value = 0;
$this->executeView($view);
$expected = [];
$expected[] = ['uid' => 2];
$expected[] = ['uid' => 3];
$expected[] = ['uid' => 4];
$this->assertIdenticalResultset($view, $expected, $column_map, 'User can view all users except itself when current filter is FALSE.');
$view->destroy();
$view = Views::getView('test_filter_current_user');
$view->initHandlers();
$view->filter['uid_current']->value = 1;
$this->executeView($view);
$expected = [];
$expected[] = ['uid' => 1];
$this->assertIdenticalResultset($view, $expected, $column_map, 'User can only view itself when current filter is TRUE.');
$view->destroy();
}
}
@@ -0,0 +1,115 @@
<?php
namespace Drupal\Tests\user\Kernel\Views;
use Drupal\Component\Utility\Html;
use Drupal\views\Views;
/**
* Tests the permissions filter handler.
*
* @group user
* @see \Drupal\user\Plugin\views\filter\Permissions
*/
class HandlerFilterPermissionTest extends UserKernelTestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_filter_permission'];
protected $columnMap;
/**
* Tests the permission filter handler.
*
* @todo Fix the different commented out tests by fixing the many to one
* handler handling with the NOT operator.
*/
public function testFilterPermission() {
$this->setupPermissionTestData();
$column_map = ['uid' => 'uid'];
$view = Views::getView('test_filter_permission');
// Filter by a non existing permission.
$view->initHandlers();
$view->filter['permission']->value = ['non_existent_permission'];
$this->executeView($view);
$this->assertEqual(count($view->result), 4, 'A non existent permission is not filtered so everything is the result.');
$expected[] = ['uid' => 1];
$expected[] = ['uid' => 2];
$expected[] = ['uid' => 3];
$expected[] = ['uid' => 4];
$this->assertIdenticalResultset($view, $expected, $column_map);
$view->destroy();
// Filter by a permission.
$view->initHandlers();
$view->filter['permission']->value = ['administer permissions'];
$this->executeView($view);
$this->assertEqual(count($view->result), 2);
$expected = [];
$expected[] = ['uid' => 3];
$expected[] = ['uid' => 4];
$this->assertIdenticalResultset($view, $expected, $column_map);
$view->destroy();
// Filter by not a permission.
$view->initHandlers();
$view->filter['permission']->operator = 'not';
$view->filter['permission']->value = ['administer users'];
$this->executeView($view);
$this->assertEqual(count($view->result), 3);
$expected = [];
$expected[] = ['uid' => 1];
$expected[] = ['uid' => 2];
$expected[] = ['uid' => 3];
$this->assertIdenticalResultset($view, $expected, $column_map);
$view->destroy();
// Filter by not multiple permissions, that are present in multiple roles.
$view->initHandlers();
$view->filter['permission']->operator = 'not';
$view->filter['permission']->value = ['administer users', 'administer permissions'];
$this->executeView($view);
$this->assertEqual(count($view->result), 2);
$expected = [];
$expected[] = ['uid' => 1];
$expected[] = ['uid' => 2];
$this->assertIdenticalResultset($view, $expected, $column_map);
$view->destroy();
// Filter by another permission of a role with multiple permissions.
$view->initHandlers();
$view->filter['permission']->value = ['administer users'];
$this->executeView($view);
$this->assertEqual(count($view->result), 1);
$expected = [];
$expected[] = ['uid' => 4];
$this->assertIdenticalResultset($view, $expected, $column_map);
$view->destroy();
$view->initDisplay();
$view->initHandlers();
// Test the value options.
$value_options = $view->filter['permission']->getValueOptions();
$permission_by_module = [];
$permissions = \Drupal::service('user.permissions')->getPermissions();
foreach ($permissions as $name => $permission) {
$permission_by_module[$permission['provider']][$name] = $permission;
}
foreach (['system' => 'System', 'user' => 'User'] as $module => $title) {
$expected = array_map(function ($permission) {
return Html::escape(strip_tags($permission['title']));
}, $permission_by_module[$module]);
$this->assertEqual($expected, $value_options[$title], 'Ensure the all permissions are available');
}
}
}
@@ -0,0 +1,70 @@
<?php
namespace Drupal\Tests\user\Kernel\Views;
use Drupal\user\Entity\Role;
use Drupal\views\Entity\View;
use Drupal\views\Views;
/**
* Tests the roles filter handler.
*
* @group user
*
* @see \Drupal\user\Plugin\views\filter\Roles
*/
class HandlerFilterRolesTest extends UserKernelTestBase {
/**
* Views used by this test.
*
* @var array
*/
public static $testViews = ['test_user_name'];
/**
* Tests that role filter dependencies are calculated correctly.
*/
public function testDependencies() {
$role = Role::create(['id' => 'test_user_role']);
$role->save();
$view = View::load('test_user_name');
$expected = [
'module' => ['user'],
];
$this->assertEqual($expected, $view->getDependencies());
$display = &$view->getDisplay('default');
$display['display_options']['filters']['roles_target_id'] = [
'id' => 'roles_target_id',
'table' => 'user__roles',
'field' => 'roles_target_id',
'value' => [
'test_user_role' => 'test_user_role',
],
'plugin_id' => 'user_roles',
];
$view->save();
$expected['config'][] = 'user.role.test_user_role';
$this->assertEqual($expected, $view->getDependencies());
$view = Views::getView('test_user_name');
$view->initDisplay();
$view->initHandlers();
$this->assertEqual(array_keys($view->filter['roles_target_id']->getValueOptions()), ['test_user_role']);
$view = View::load('test_user_name');
$display = &$view->getDisplay('default');
$display['display_options']['filters']['roles_target_id'] = [
'id' => 'roles_target_id',
'table' => 'user__roles',
'field' => 'roles_target_id',
'value' => [],
'plugin_id' => 'user_roles',
];
$view->save();
unset($expected['config']);
$this->assertEqual($expected, $view->getDependencies());
}
}
@@ -0,0 +1,90 @@
<?php
namespace Drupal\Tests\user\Kernel\Views;
use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
use Drupal\views\Tests\ViewTestData;
/**
* Provides a common test base for user views tests.
*/
abstract class UserKernelTestBase extends ViewsKernelTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['user_test_views', 'user', 'system', 'field'];
/**
* Users to use during this test.
*
* @var array
*/
protected $users = [];
/**
* The entity storage for roles.
*
* @var \Drupal\user\RoleStorage
*/
protected $roleStorage;
/**
* The entity storage for users.
*
* @var \Drupal\user\UserStorage
*/
protected $userStorage;
protected function setUp($import_test_views = TRUE) {
parent::setUp();
ViewTestData::createTestViews(get_class($this), ['user_test_views']);
$this->installEntitySchema('user');
$entity_manager = $this->container->get('entity.manager');
$this->roleStorage = $entity_manager->getStorage('user_role');
$this->userStorage = $entity_manager->getStorage('user');
}
/**
* Set some test data for permission related tests.
*/
protected function setupPermissionTestData() {
// Setup a role without any permission.
$this->roleStorage->create(['id' => 'authenticated'])
->save();
$this->roleStorage->create(['id' => 'no_permission'])
->save();
// Setup a role with just one permission.
$this->roleStorage->create(['id' => 'one_permission'])
->save();
user_role_grant_permissions('one_permission', ['administer permissions']);
// Setup a role with multiple permissions.
$this->roleStorage->create(['id' => 'multiple_permissions'])
->save();
user_role_grant_permissions('multiple_permissions', ['administer permissions', 'administer users', 'access user profiles']);
// Setup a user without an extra role.
$this->users[] = $account = $this->userStorage->create(['name' => $this->randomString()]);
$account->save();
// Setup a user with just the first role (so no permission beside the
// ones from the authenticated role).
$this->users[] = $account = $this->userStorage->create(['name' => 'first_role']);
$account->addRole('no_permission');
$account->save();
// Setup a user with just the second role (so one additional permission).
$this->users[] = $account = $this->userStorage->create(['name' => 'second_role']);
$account->addRole('one_permission');
$account->save();
// Setup a user with both the second and the third role.
$this->users[] = $account = $this->userStorage->create(['name' => 'second_third_role']);
$account->addRole('one_permission');
$account->addRole('multiple_permissions');
$account->save();
}
}
@@ -0,0 +1,67 @@
<?php
namespace Drupal\Tests\user\Kernel\Views;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\user\Entity\User;
use Drupal\Tests\views\Kernel\Handler\FieldFieldAccessTestBase;
/**
* Tests base field access in Views for the user entity.
*
* @group user
*/
class UserViewsFieldAccessTest extends FieldFieldAccessTestBase {
/**
* {@inheritdoc}
*/
public static $modules = ['user', 'entity_test', 'language'];
/**
* {@inheritdoc}
*/
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
$this->installEntitySchema('user');
}
public function testUserFields() {
ConfigurableLanguage::create([
'id' => 'es',
'name' => 'Spanish',
])->save();
ConfigurableLanguage::create([
'id' => 'fr',
'name' => 'French',
])->save();
$user = User::create([
'name' => 'test user',
'mail' => 'druplicon@drop.org',
'status' => 1,
'preferred_langcode' => 'es',
'preferred_admin_langcode' => 'fr',
'timezone' => 'ut1',
'created' => 123456,
]);
$user->save();
// @todo Expand the test coverage in https://www.drupal.org/node/2464635
$this->assertFieldAccess('user', 'uid', $user->id());
$this->assertFieldAccess('user', 'uuid', $user->uuid());
$this->assertFieldAccess('user', 'langcode', $user->language()->getName());
$this->assertFieldAccess('user', 'preferred_langcode', 'Spanish');
$this->assertFieldAccess('user', 'preferred_admin_langcode', 'French');
$this->assertFieldAccess('user', 'name', 'test user');
// $this->assertFieldAccess('user', 'mail', 'druplicon@drop.org');
$this->assertFieldAccess('user', 'timezone', 'ut1');
$this->assertFieldAccess('user', 'status', 'On');
// $this->assertFieldAccess('user', 'created', \Drupal::service('date.formatter')->format(123456));
// $this->assertFieldAccess('user', 'changed', \Drupal::service('date.formatter')->format(REQUEST_TIME));
}
}
@@ -0,0 +1,86 @@
<?php
namespace Drupal\Tests\user\Unit\Menu;
use Drupal\Tests\Core\Menu\LocalTaskIntegrationTestBase;
/**
* Tests user local tasks.
*
* @group user
*/
class UserLocalTasksTest extends LocalTaskIntegrationTestBase {
protected function setUp() {
$this->directoryList = ['user' => 'core/modules/user'];
parent::setUp();
}
/**
* Tests local task existence.
*
* @dataProvider getUserAdminRoutes
*/
public function testUserAdminLocalTasks($route, $expected) {
$this->assertLocalTasks($route, $expected);
}
/**
* Provides a list of routes to test.
*/
public function getUserAdminRoutes() {
return [
['entity.user.collection', [['entity.user.collection', 'user.admin_permissions', 'entity.user_role.collection']]],
['user.admin_permissions', [['entity.user.collection', 'user.admin_permissions', 'entity.user_role.collection']]],
['entity.user_role.collection', [['entity.user.collection', 'user.admin_permissions', 'entity.user_role.collection']]],
['entity.user.admin_form', [['user.account_settings_tab']]],
];
}
/**
* Checks user listing local tasks.
*
* @dataProvider getUserLoginRoutes
*/
public function testUserLoginLocalTasks($route) {
$tasks = [
0 => ['user.register', 'user.pass', 'user.login'],
];
$this->assertLocalTasks($route, $tasks);
}
/**
* Provides a list of routes to test.
*/
public function getUserLoginRoutes() {
return [
['user.login'],
['user.register'],
['user.pass'],
];
}
/**
* Checks user listing local tasks.
*
* @dataProvider getUserPageRoutes
*/
public function testUserPageLocalTasks($route, $subtask = []) {
$tasks = [
0 => ['entity.user.canonical', 'entity.user.edit_form'],
];
if ($subtask) $tasks[] = $subtask;
$this->assertLocalTasks($route, $tasks);
}
/**
* Provides a list of routes to test.
*/
public function getUserPageRoutes() {
return [
['entity.user.canonical'],
['entity.user.edit_form'],
];
}
}
@@ -0,0 +1,90 @@
<?php
namespace Drupal\Tests\user\Unit;
use Drupal\Core\Access\AccessResult;
use Drupal\Tests\UnitTestCase;
use Drupal\user\Access\PermissionAccessCheck;
use Symfony\Component\Routing\Route;
use Drupal\Core\Cache\Context\CacheContextsManager;
use Symfony\Component\DependencyInjection\ContainerBuilder;
/**
* @coversDefaultClass \Drupal\user\Access\PermissionAccessCheck
* @group Routing
* @group Access
*/
class PermissionAccessCheckTest extends UnitTestCase {
/**
* The tested access checker.
*
* @var \Drupal\user\Access\PermissionAccessCheck
*/
public $accessCheck;
/**
* The dependency injection container.
*
* @var \Symfony\Component\DependencyInjection\ContainerBuilder
*/
protected $container;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->container = new ContainerBuilder();
$cache_contexts_manager = $this->prophesize(CacheContextsManager::class);
$cache_contexts_manager->assertValidTokens()->willReturn(TRUE);
$cache_contexts_manager->reveal();
$this->container->set('cache_contexts_manager', $cache_contexts_manager);
\Drupal::setContainer($this->container);
$this->accessCheck = new PermissionAccessCheck();
}
/**
* Provides data for the testAccess method.
*
* @return array
*/
public function providerTestAccess() {
return [
[[], FALSE],
[['_permission' => 'allowed'], TRUE, ['user.permissions']],
[['_permission' => 'denied'], FALSE, ['user.permissions'], "The 'denied' permission is required."],
[['_permission' => 'allowed+denied'], TRUE, ['user.permissions']],
[['_permission' => 'allowed+denied+other'], TRUE, ['user.permissions']],
[['_permission' => 'allowed,denied'], FALSE, ['user.permissions'], "The following permissions are required: 'allowed' AND 'denied'."],
];
}
/**
* Tests the access check method.
*
* @dataProvider providerTestAccess
* @covers ::access
*/
public function testAccess($requirements, $access, array $contexts = [], $message = '') {
$access_result = AccessResult::allowedIf($access)->addCacheContexts($contexts);
if (!empty($message)) {
$access_result->setReason($message);
}
$user = $this->getMock('Drupal\Core\Session\AccountInterface');
$user->expects($this->any())
->method('hasPermission')
->will($this->returnValueMap([
['allowed', TRUE],
['denied', FALSE],
['other', FALSE]
]
));
$route = new Route('', [], $requirements);
$this->assertEquals($access_result, $this->accessCheck->access($route, $user));
}
}
@@ -0,0 +1,463 @@
<?php
/**
* @file
* Contains \Drupal\Tests\user\Unit\PermissionHandlerTest.
*/
namespace Drupal\Tests\user\Unit;
use Drupal\Core\Extension\Extension;
use Drupal\Core\StringTranslation\PluralTranslatableMarkup;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Tests\UnitTestCase;
use Drupal\user\PermissionHandler;
use org\bovigo\vfs\vfsStream;
use org\bovigo\vfs\vfsStreamDirectory;
use org\bovigo\vfs\vfsStreamWrapper;
/**
* Tests the permission handler.
*
* @group user
*
* @coversDefaultClass \Drupal\user\PermissionHandler
*/
class PermissionHandlerTest extends UnitTestCase {
/**
* The tested permission handler.
*
* @var \Drupal\Tests\user\Unit\TestPermissionHandler|\Drupal\user\PermissionHandler
*/
protected $permissionHandler;
/**
* The mocked module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $moduleHandler;
/**
* The mocked string translation.
*
* @var \Drupal\Tests\user\Unit\TestTranslationManager
*/
protected $stringTranslation;
/**
* The mocked controller resolver.
*
* @var \Drupal\Core\Controller\ControllerResolverInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $controllerResolver;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->stringTranslation = new TestTranslationManager();
$this->controllerResolver = $this->getMock('Drupal\Core\Controller\ControllerResolverInterface');
}
/**
* Provides an extension object for a given module with a human name.
*
* @param string $module
* The module machine name.
* @param string $name
* The module human name.
*
* @return \Drupal\Core\Extension\Extension
* The extension object.
*/
protected function mockModuleExtension($module, $name) {
$extension = new Extension($this->root, $module, "modules/$module");
$extension->info['name'] = $name;
return $extension;
}
/**
* Tests permissions provided by YML files.
*
* @covers ::__construct
* @covers ::getPermissions
* @covers ::buildPermissionsYaml
* @covers ::moduleProvidesPermissions
*/
public function testBuildPermissionsYaml() {
vfsStreamWrapper::register();
$root = new vfsStreamDirectory('modules');
vfsStreamWrapper::setRoot($root);
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
$this->moduleHandler->expects($this->once())
->method('getModuleDirectories')
->willReturn([
'module_a' => vfsStream::url('modules/module_a'),
'module_b' => vfsStream::url('modules/module_b'),
'module_c' => vfsStream::url('modules/module_c'),
]);
$url = vfsStream::url('modules');
mkdir($url . '/module_a');
file_put_contents($url . '/module_a/module_a.permissions.yml', "access_module_a: single_description");
mkdir($url . '/module_b');
file_put_contents($url . '/module_b/module_b.permissions.yml', <<<EOF
'access module b':
title: 'Access B'
description: 'bla bla'
'access module a via module b':
title: 'Access A via B'
provider: 'module_a'
EOF
);
mkdir($url . '/module_c');
file_put_contents($url . '/module_c/module_c.permissions.yml', <<<EOF
'access_module_c':
title: 'Access C'
description: 'bla bla'
'restrict access': TRUE
EOF
);
$modules = ['module_a', 'module_b', 'module_c'];
$extensions = [
'module_a' => $this->mockModuleExtension('module_a', 'Module a'),
'module_b' => $this->mockModuleExtension('module_b', 'Module b'),
'module_c' => $this->mockModuleExtension('module_c', 'Module c'),
];
$this->moduleHandler->expects($this->any())
->method('getImplementations')
->with('permission')
->willReturn([]);
$this->moduleHandler->expects($this->any())
->method('getModuleList')
->willReturn(array_flip($modules));
$this->controllerResolver->expects($this->never())
->method('getControllerFromDefinition');
$this->permissionHandler = new TestPermissionHandler($this->moduleHandler, $this->stringTranslation, $this->controllerResolver);
// Setup system_rebuild_module_data().
$this->permissionHandler->setSystemRebuildModuleData($extensions);
$actual_permissions = $this->permissionHandler->getPermissions();
$this->assertPermissions($actual_permissions);
$this->assertTrue($this->permissionHandler->moduleProvidesPermissions('module_a'));
$this->assertTrue($this->permissionHandler->moduleProvidesPermissions('module_b'));
$this->assertTrue($this->permissionHandler->moduleProvidesPermissions('module_c'));
$this->assertFalse($this->permissionHandler->moduleProvidesPermissions('module_d'));
}
/**
* Tests permissions sort inside a module.
*
* @covers ::__construct
* @covers ::getPermissions
* @covers ::buildPermissionsYaml
* @covers ::sortPermissions
*/
public function testBuildPermissionsSortPerModule() {
vfsStreamWrapper::register();
$root = new vfsStreamDirectory('modules');
vfsStreamWrapper::setRoot($root);
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
$this->moduleHandler->expects($this->once())
->method('getModuleDirectories')
->willReturn([
'module_a' => vfsStream::url('modules/module_a'),
'module_b' => vfsStream::url('modules/module_b'),
'module_c' => vfsStream::url('modules/module_c'),
]);
$this->moduleHandler->expects($this->exactly(3))
->method('getName')
->will($this->returnValueMap([
['module_a', 'Module a'],
['module_b', 'Module b'],
['module_c', 'A Module'],
]));
$url = vfsStream::url('modules');
mkdir($url . '/module_a');
file_put_contents($url . '/module_a/module_a.permissions.yml', <<<EOF
access_module_a2: single_description2
access_module_a1: single_description1
EOF
);
mkdir($url . '/module_b');
file_put_contents($url . '/module_b/module_b.permissions.yml',
"access_module_a3: single_description"
);
mkdir($url . '/module_c');
file_put_contents($url . '/module_c/module_c.permissions.yml',
"access_module_a4: single_description"
);
$modules = ['module_a', 'module_b', 'module_c'];
$this->moduleHandler->expects($this->once())
->method('getModuleList')
->willReturn(array_flip($modules));
$permissionHandler = new TestPermissionHandler($this->moduleHandler, $this->stringTranslation, $this->controllerResolver);
$actual_permissions = $permissionHandler->getPermissions();
$this->assertEquals(['access_module_a4', 'access_module_a1', 'access_module_a2', 'access_module_a3'],
array_keys($actual_permissions));
}
/**
* Tests dynamic callback permissions provided by YML files.
*
* @covers ::__construct
* @covers ::getPermissions
* @covers ::buildPermissionsYaml
*/
public function testBuildPermissionsYamlCallback() {
vfsStreamWrapper::register();
$root = new vfsStreamDirectory('modules');
vfsStreamWrapper::setRoot($root);
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
$this->moduleHandler->expects($this->once())
->method('getModuleDirectories')
->willReturn([
'module_a' => vfsStream::url('modules/module_a'),
'module_b' => vfsStream::url('modules/module_b'),
'module_c' => vfsStream::url('modules/module_c'),
]);
$url = vfsStream::url('modules');
mkdir($url . '/module_a');
file_put_contents($url . '/module_a/module_a.permissions.yml', <<<EOF
permission_callbacks:
- 'Drupal\\user\\Tests\\TestPermissionCallbacks::singleDescription'
EOF
);
mkdir($url . '/module_b');
file_put_contents($url . '/module_b/module_b.permissions.yml', <<<EOF
permission_callbacks:
- 'Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription'
- 'Drupal\\user\\Tests\\TestPermissionCallbacks::titleProvider'
EOF
);
mkdir($url . '/module_c');
file_put_contents($url . '/module_c/module_c.permissions.yml', <<<EOF
permission_callbacks:
- 'Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescriptionRestrictAccess'
EOF
);
$modules = ['module_a', 'module_b', 'module_c'];
$extensions = [
'module_a' => $this->mockModuleExtension('module_a', 'Module a'),
'module_b' => $this->mockModuleExtension('module_b', 'Module b'),
'module_c' => $this->mockModuleExtension('module_c', 'Module c'),
];
$this->moduleHandler->expects($this->any())
->method('getImplementations')
->with('permission')
->willReturn([]);
$this->moduleHandler->expects($this->any())
->method('getModuleList')
->willReturn(array_flip($modules));
$this->controllerResolver->expects($this->at(0))
->method('getControllerFromDefinition')
->with('Drupal\\user\\Tests\\TestPermissionCallbacks::singleDescription')
->willReturn([new TestPermissionCallbacks(), 'singleDescription']);
$this->controllerResolver->expects($this->at(1))
->method('getControllerFromDefinition')
->with('Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription')
->willReturn([new TestPermissionCallbacks(), 'titleDescription']);
$this->controllerResolver->expects($this->at(2))
->method('getControllerFromDefinition')
->with('Drupal\\user\\Tests\\TestPermissionCallbacks::titleProvider')
->willReturn([new TestPermissionCallbacks(), 'titleProvider']);
$this->controllerResolver->expects($this->at(3))
->method('getControllerFromDefinition')
->with('Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescriptionRestrictAccess')
->willReturn([new TestPermissionCallbacks(), 'titleDescriptionRestrictAccess']);
$this->permissionHandler = new TestPermissionHandler($this->moduleHandler, $this->stringTranslation, $this->controllerResolver);
// Setup system_rebuild_module_data().
$this->permissionHandler->setSystemRebuildModuleData($extensions);
$actual_permissions = $this->permissionHandler->getPermissions();
$this->assertPermissions($actual_permissions);
}
/**
* Tests a YAML file containing both static permissions and a callback.
*/
public function testPermissionsYamlStaticAndCallback() {
vfsStreamWrapper::register();
$root = new vfsStreamDirectory('modules');
vfsStreamWrapper::setRoot($root);
$this->moduleHandler = $this->getMock('Drupal\Core\Extension\ModuleHandlerInterface');
$this->moduleHandler->expects($this->once())
->method('getModuleDirectories')
->willReturn([
'module_a' => vfsStream::url('modules/module_a'),
]);
$url = vfsStream::url('modules');
mkdir($url . '/module_a');
file_put_contents($url . '/module_a/module_a.permissions.yml', <<<EOF
'access module a':
title: 'Access A'
description: 'bla bla'
permission_callbacks:
- 'Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription'
EOF
);
$modules = ['module_a'];
$extensions = [
'module_a' => $this->mockModuleExtension('module_a', 'Module a'),
];
$this->moduleHandler->expects($this->any())
->method('getImplementations')
->with('permission')
->willReturn([]);
$this->moduleHandler->expects($this->any())
->method('getModuleList')
->willReturn(array_flip($modules));
$this->controllerResolver->expects($this->once())
->method('getControllerFromDefinition')
->with('Drupal\\user\\Tests\\TestPermissionCallbacks::titleDescription')
->willReturn([new TestPermissionCallbacks(), 'titleDescription']);
$this->permissionHandler = new TestPermissionHandler($this->moduleHandler, $this->stringTranslation, $this->controllerResolver);
// Setup system_rebuild_module_data().
$this->permissionHandler->setSystemRebuildModuleData($extensions);
$actual_permissions = $this->permissionHandler->getPermissions();
$this->assertCount(2, $actual_permissions);
$this->assertEquals($actual_permissions['access module a']['title'], 'Access A');
$this->assertEquals($actual_permissions['access module a']['provider'], 'module_a');
$this->assertEquals($actual_permissions['access module a']['description'], 'bla bla');
$this->assertEquals($actual_permissions['access module b']['title'], 'Access B');
$this->assertEquals($actual_permissions['access module b']['provider'], 'module_a');
$this->assertEquals($actual_permissions['access module b']['description'], 'bla bla');
}
/**
* Checks that the permissions are like expected.
*
* @param array $actual_permissions
* The actual permissions
*/
protected function assertPermissions(array $actual_permissions) {
$this->assertCount(4, $actual_permissions);
$this->assertEquals($actual_permissions['access_module_a']['title'], 'single_description');
$this->assertEquals($actual_permissions['access_module_a']['provider'], 'module_a');
$this->assertEquals($actual_permissions['access module b']['title'], 'Access B');
$this->assertEquals($actual_permissions['access module b']['provider'], 'module_b');
$this->assertEquals($actual_permissions['access_module_c']['title'], 'Access C');
$this->assertEquals($actual_permissions['access_module_c']['provider'], 'module_c');
$this->assertEquals($actual_permissions['access_module_c']['restrict access'], TRUE);
$this->assertEquals($actual_permissions['access module a via module b']['provider'], 'module_a');
}
}
class TestPermissionHandler extends PermissionHandler {
/**
* Test module data.
*
* @var array
*/
protected $systemModuleData;
protected function systemRebuildModuleData() {
return $this->systemModuleData;
}
public function setSystemRebuildModuleData(array $extensions) {
$this->systemModuleData = $extensions;
}
}
class TestPermissionCallbacks {
public function singleDescription() {
return [
'access_module_a' => 'single_description'
];
}
public function titleDescription() {
return [
'access module b' => [
'title' => 'Access B',
'description' => 'bla bla',
],
];
}
public function titleDescriptionRestrictAccess() {
return [
'access_module_c' => [
'title' => 'Access C',
'description' => 'bla bla',
'restrict access' => TRUE,
],
];
}
public function titleProvider() {
return [
'access module a via module b' => [
'title' => 'Access A via B',
'provider' => 'module_a',
],
];
}
}
/**
* Implements a translation manager in tests.
*/
class TestTranslationManager implements TranslationInterface {
/**
* {@inheritdoc}
*/
public function translate($string, array $args = [], array $options = []) {
return new TranslatableMarkup($string, $args, $options, $this);
}
/**
* {@inheritdoc}
*/
public function translateString(TranslatableMarkup $translated_string) {
return $translated_string->getUntranslatedString();
}
/**
* {@inheritdoc}
*/
public function formatPlural($count, $singular, $plural, array $args = [], array $options = []) {
return new PluralTranslatableMarkup($count, $singular, $plural, $args, $options, $this);
}
}
@@ -0,0 +1,49 @@
<?php
namespace Drupal\Tests\user\Unit\Plugin\Action;
use Drupal\user\Plugin\Action\AddRoleUser;
/**
* @coversDefaultClass \Drupal\user\Plugin\Action\AddRoleUser
* @group user
*/
class AddRoleUserTest extends RoleUserTestBase {
/**
* Tests the execute method on a user with a role.
*/
public function testExecuteAddExistingRole() {
$this->account->expects($this->never())
->method('addRole');
$this->account->expects($this->any())
->method('hasRole')
->with($this->equalTo('test_role_1'))
->will($this->returnValue(TRUE));
$config = ['rid' => 'test_role_1'];
$remove_role_plugin = new AddRoleUser($config, 'user_add_role_action', ['type' => 'user'], $this->userRoleEntityType);
$remove_role_plugin->execute($this->account);
}
/**
* Tests the execute method on a user without a specific role.
*/
public function testExecuteAddNonExistingRole() {
$this->account->expects($this->once())
->method('addRole');
$this->account->expects($this->any())
->method('hasRole')
->with($this->equalTo('test_role_1'))
->will($this->returnValue(FALSE));
$config = ['rid' => 'test_role_1'];
$remove_role_plugin = new AddRoleUser($config, 'user_remove_role_action', ['type' => 'user'], $this->userRoleEntityType);
$remove_role_plugin->execute($this->account);
}
}
@@ -0,0 +1,49 @@
<?php
namespace Drupal\Tests\user\Unit\Plugin\Action;
use Drupal\user\Plugin\Action\RemoveRoleUser;
/**
* @coversDefaultClass \Drupal\user\Plugin\Action\RemoveRoleUser
* @group user
*/
class RemoveRoleUserTest extends RoleUserTestBase {
/**
* Tests the execute method on a user with a role.
*/
public function testExecuteRemoveExistingRole() {
$this->account->expects($this->once())
->method('removeRole');
$this->account->expects($this->any())
->method('hasRole')
->with($this->equalTo('test_role_1'))
->will($this->returnValue(TRUE));
$config = ['rid' => 'test_role_1'];
$remove_role_plugin = new RemoveRoleUser($config, 'user_remove_role_action', ['type' => 'user'], $this->userRoleEntityType);
$remove_role_plugin->execute($this->account);
}
/**
* Tests the execute method on a user without a specific role.
*/
public function testExecuteRemoveNonExistingRole() {
$this->account->expects($this->never())
->method('removeRole');
$this->account->expects($this->any())
->method('hasRole')
->with($this->equalTo('test_role_1'))
->will($this->returnValue(FALSE));
$config = ['rid' => 'test_role_1'];
$remove_role_plugin = new RemoveRoleUser($config, 'user_remove_role_action', ['type' => 'user'], $this->userRoleEntityType);
$remove_role_plugin->execute($this->account);
}
}
@@ -0,0 +1,39 @@
<?php
namespace Drupal\Tests\user\Unit\Plugin\Action;
use Drupal\Tests\UnitTestCase;
/**
* Provides a base class for user role action tests.
*/
abstract class RoleUserTestBase extends UnitTestCase {
/**
* The mocked account.
*
* @var \Drupal\user\UserInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $account;
/**
* The user role entity type.
*
* @var \Drupal\Core\Entity\EntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $userRoleEntityType;
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->account = $this
->getMockBuilder('Drupal\user\Entity\User')
->disableOriginalConstructor()
->getMock();
$this->userRoleEntityType = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
}
}
@@ -0,0 +1,57 @@
<?php
namespace Drupal\Tests\user\Unit\Plugin\Core\Entity;
use Drupal\Tests\Core\Session\UserSessionTest;
use Drupal\user\RoleInterface;
/**
* @coversDefaultClass \Drupal\user\Entity\User
* @group user
*/
class UserTest extends UserSessionTest {
/**
* {@inheritdoc}
*/
protected function createUserSession(array $rids = [], $authenticated = FALSE) {
$user = $this->getMockBuilder('Drupal\user\Entity\User')
->disableOriginalConstructor()
->setMethods(['get', 'id'])
->getMock();
$user->expects($this->any())
->method('id')
// @todo Also test the uid = 1 handling.
->will($this->returnValue($authenticated ? 2 : 0));
$roles = [];
foreach ($rids as $rid) {
$roles[] = (object) [
'target_id' => $rid,
];
}
$user->expects($this->any())
->method('get')
->with('roles')
->will($this->returnValue($roles));
return $user;
}
/**
* Tests the method getRoles exclude or include locked roles based in param.
*
* @see \Drupal\user\Entity\User::getRoles()
* @covers ::getRoles
*/
public function testUserGetRoles() {
// Anonymous user.
$user = $this->createUserSession([]);
$this->assertEquals([RoleInterface::ANONYMOUS_ID], $user->getRoles());
$this->assertEquals([], $user->getRoles(TRUE));
// Authenticated user.
$user = $this->createUserSession([], TRUE);
$this->assertEquals([RoleInterface::AUTHENTICATED_ID], $user->getRoles());
$this->assertEquals([], $user->getRoles(TRUE));
}
}

Some files were not shown because too many files have changed in this diff Show More