3 class UserTest < ActiveSupport::TestCase
4 include CurrentApiClient
6 # The fixture services/api/test/fixtures/users.yml serves as the input for this test case
8 # Make sure system_user exists before making "pre-test users" list
12 %w(a aa a0 aA Aa AA A0).each do |username|
13 test "#{username.inspect} is a valid username" do
14 user = User.new(username: username)
19 test "username is not required" do
20 user = User.new(username: nil)
24 test "username beginning with numeral is invalid" do
25 user = User.new(username: "0a")
29 "\\.-_/!@#$%^&*()[]{}".each_char do |bad_char|
30 test "username containing #{bad_char.inspect} is invalid" do
31 user = User.new(username: "bad#{bad_char}username")
36 test "username must be unique" do
37 user = User.new(username: users(:active).username)
41 test "non-admin can't update username" do
42 set_user_from_auth :active_trustedclient
43 user = User.find_by_uuid(users(:active).uuid)
44 user.username = "selfupdate"
47 rescue ArvadosModel::PermissionDeniedError
52 def check_admin_username_change(fixture_name)
53 set_user_from_auth :admin_trustedclient
54 user = User.find_by_uuid(users(fixture_name).uuid)
55 user.username = "newnamefromtest"
59 test "admin can set username" do
60 check_admin_username_change(:active_no_prefs)
63 test "admin can update username" do
64 check_admin_username_change(:active)
67 test "admin can update own username" do
68 check_admin_username_change(:admin)
71 def check_new_username_setting(email_name, expect_name)
72 set_user_from_auth :admin
73 user = User.create!(email: "#{email_name}@example.org")
74 assert_equal(expect_name, user.username)
77 test "new username set from e-mail" do
78 check_new_username_setting("dakota", "dakota")
81 test "new username set from e-mail with leading digits" do
82 check_new_username_setting("1dakota9", "dakota9")
85 test "new username set from e-mail with punctuation" do
86 check_new_username_setting("dakota.9", "dakota9")
89 test "new username set from e-mail with leading digits and punctuation" do
90 check_new_username_setting("1.dakota.z", "dakotaz")
93 test "new username set from e-mail with extra part" do
94 check_new_username_setting("dakota+arvados", "dakota")
97 test "new username set with deduplication" do
98 name = users(:active).username
99 check_new_username_setting(name, "#{name}2")
102 test "new username set avoiding blacklist" do
103 Rails.configuration.auto_setup_name_blacklist = ["root"]
104 check_new_username_setting("root", "root2")
107 test "no username set when no base available" do
108 check_new_username_setting("_", nil)
111 [[false, 'foo@example.com', true, nil],
112 [false, 'bar@example.com', nil, true],
113 [true, 'foo@example.com', true, nil],
114 [true, 'bar@example.com', true, true],
115 [false, false, nil, nil],
116 [true, false, true, nil]
117 ].each do |auto_admin_first_user_config, auto_admin_user_config, foo_should_be_admin, bar_should_be_admin|
118 # In each case, 'foo' is created first, then 'bar', then 'bar2', then 'baz'.
119 test "auto admin with auto_admin_first=#{auto_admin_first_user_config} auto_admin=#{auto_admin_user_config}" do
121 if auto_admin_first_user_config
122 # This test requires no admin users exist (except for the system user)
124 @all_users = User.where("uuid not like '%-000000000000000'").where(:is_admin => true).find(:all)
125 assert_equal 0, @all_users.size, "No admin users should exist (except for the system user)"
128 Rails.configuration.auto_admin_first_user = auto_admin_first_user_config
129 Rails.configuration.auto_admin_user = auto_admin_user_config
131 # See if the foo user has is_admin
133 foo.first_name = 'foo'
134 foo.email = 'foo@example.com'
136 act_as_system_user do
140 foo = User.find(foo.id) # get the user back
141 assert_equal foo_should_be_admin, foo.is_admin, "is_admin is wrong for user foo"
142 assert_equal 'foo', foo.first_name
144 # See if the bar user has is_admin
146 bar.first_name = 'bar'
147 bar.email = 'bar@example.com'
149 act_as_system_user do
153 bar = User.find(bar.id) # get the user back
154 assert_equal bar_should_be_admin, bar.is_admin, "is_admin is wrong for user bar"
155 assert_equal 'bar', bar.first_name
157 # A subsequent user with the bar@example.com address should never be
160 bar2.first_name = 'bar2'
161 bar2.email = 'bar@example.com'
163 act_as_system_user do
167 bar2 = User.find(bar2.id) # get the user back
168 assert !bar2.is_admin, "is_admin is wrong for user bar2"
169 assert_equal 'bar2', bar2.first_name
171 # An ordinary new user should not be elevated to admin
173 baz.first_name = 'baz'
174 baz.email = 'baz@example.com'
176 act_as_system_user do
180 baz = User.find(baz.id) # get the user back
182 assert_equal 'baz', baz.first_name
187 test "check non-admin active user properties" do
188 @active_user = users(:active) # get the active user
189 assert !@active_user.is_admin, 'is_admin should not be set for a non-admin user'
190 assert @active_user.is_active, 'user should be active'
191 assert @active_user.is_invited, 'is_invited should be set'
192 assert_not_nil @active_user.prefs, "user's preferences should be non-null, but may be size zero"
193 assert (@active_user.can? :read=>"#{@active_user.uuid}"), "user should be able to read own object"
194 assert (@active_user.can? :write=>"#{@active_user.uuid}"), "user should be able to write own object"
195 assert (@active_user.can? :manage=>"#{@active_user.uuid}"), "user should be able to manage own object"
197 assert @active_user.groups_i_can(:read).size > 0, "active user should be able read at least one group"
199 # non-admin user cannot manage or write other user objects
200 @uninvited_user = users(:inactive_uninvited) # get the uninvited user
201 assert !(@active_user.can? :read=>"#{@uninvited_user.uuid}")
202 assert !(@active_user.can? :write=>"#{@uninvited_user.uuid}")
203 assert !(@active_user.can? :manage=>"#{@uninvited_user.uuid}")
206 test "check admin user properties" do
207 @admin_user = users(:admin) # get the admin user
208 assert @admin_user.is_admin, 'is_admin should be set for admin user'
209 assert @admin_user.is_active, 'admin user cannot be inactive'
210 assert @admin_user.is_invited, 'is_invited should be set'
211 assert_not_nil @admin_user.uuid.size, "user's uuid should be non-null"
212 assert_not_nil @admin_user.prefs, "user's preferences should be non-null, but may be size zero"
213 assert @admin_user.identity_url.size > 0, "user's identity url is expected"
214 assert @admin_user.can? :read=>"#{@admin_user.uuid}"
215 assert @admin_user.can? :write=>"#{@admin_user.uuid}"
216 assert @admin_user.can? :manage=>"#{@admin_user.uuid}"
218 assert @admin_user.groups_i_can(:read).size > 0, "admin active user should be able read at least one group"
219 assert @admin_user.groups_i_can(:write).size > 0, "admin active user should be able write to at least one group"
220 assert @admin_user.groups_i_can(:manage).size > 0, "admin active user should be able manage at least one group"
222 # admin user can also write or manage other users
223 @uninvited_user = users(:inactive_uninvited) # get the uninvited user
224 assert @admin_user.can? :read=>"#{@uninvited_user.uuid}"
225 assert @admin_user.can? :write=>"#{@uninvited_user.uuid}"
226 assert @admin_user.can? :manage=>"#{@uninvited_user.uuid}"
229 test "check inactive and uninvited user properties" do
230 @uninvited_user = users(:inactive_uninvited) # get the uninvited user
231 assert !@uninvited_user.is_admin, 'is_admin should not be set for a non-admin user'
232 assert !@uninvited_user.is_active, 'user should be inactive'
233 assert !@uninvited_user.is_invited, 'is_invited should not be set'
234 assert @uninvited_user.can? :read=>"#{@uninvited_user.uuid}"
235 assert @uninvited_user.can? :write=>"#{@uninvited_user.uuid}"
236 assert @uninvited_user.can? :manage=>"#{@uninvited_user.uuid}"
238 assert @uninvited_user.groups_i_can(:read).size == 1, "inactive and uninvited user can only read anonymous user group"
239 assert @uninvited_user.groups_i_can(:read).first.ends_with? 'anonymouspublic' , "inactive and uninvited user can only read anonymous user group"
240 assert @uninvited_user.groups_i_can(:write).size == 0, "inactive and uninvited user should not be able write to any groups"
241 assert @uninvited_user.groups_i_can(:manage).size == 0, "inactive and uninvited user should not be able manage any groups"
244 test "find user method checks" do
245 User.find(:all).each do |user|
246 assert_not_nil user.uuid, "non-null uuid expected for " + user.full_name
249 user = users(:active) # get the active user
251 found_user = User.find(user.id) # find a user by the row id
253 assert_equal found_user.full_name, user.first_name + ' ' + user.last_name
254 assert_equal found_user.identity_url, user.identity_url
257 test "full name should not contain spurious whitespace" do
258 set_user_from_auth :admin
260 user = User.create ({uuid: 'zzzzz-tpzed-abcdefghijklmno', email: 'foo@example.com' })
262 assert_equal '', user.full_name
264 user.first_name = 'John'
265 user.last_name = 'Smith'
267 assert_equal user.first_name + ' ' + user.last_name, user.full_name
270 test "create new user" do
271 set_user_from_auth :admin
273 @all_users = User.find(:all)
276 user.first_name = "first_name_for_newly_created_user"
279 # verify there is one extra user in the db now
280 assert_equal @all_users.size+1, User.find(:all).size
282 user = User.find(user.id) # get the user back
283 assert_equal(user.first_name, 'first_name_for_newly_created_user')
284 assert_not_nil user.uuid, 'uuid should be set for newly created user'
285 assert_nil user.email, 'email should be null for newly created user, because it was not passed in'
286 assert_nil user.identity_url, 'identity_url should be null for newly created user, because it was not passed in'
288 user.first_name = 'first_name_for_newly_created_user_updated'
290 user = User.find(user.id) # get the user back
291 assert_equal(user.first_name, 'first_name_for_newly_created_user_updated')
294 test "create new user with notifications" do
295 set_user_from_auth :admin
297 create_user_and_verify_setup_and_notifications true, 'active-notify-address@example.com', 'inactive-notify-address@example.com', nil, nil
298 create_user_and_verify_setup_and_notifications true, 'active-notify-address@example.com', [], nil, nil
299 create_user_and_verify_setup_and_notifications true, [], [], nil, nil
300 create_user_and_verify_setup_and_notifications false, 'active-notify-address@example.com', 'inactive-notify-address@example.com', nil, nil
301 create_user_and_verify_setup_and_notifications false, [], 'inactive-notify-address@example.com', nil, nil
302 create_user_and_verify_setup_and_notifications false, [], [], nil, nil
306 # Easy inactive user tests.
307 [false, [], [], "inactive-none@example.com", false, false, "inactivenone"],
308 [false, [], [], "inactive-vm@example.com", true, false, "inactivevm"],
309 [false, [], [], "inactive-repo@example.com", false, true, "inactiverepo"],
310 [false, [], [], "inactive-both@example.com", true, true, "inactiveboth"],
312 # Easy active user tests.
313 [true, "active-notify@example.com", "inactive-notify@example.com", "active-none@example.com", false, false, "activenone"],
314 [true, "active-notify@example.com", "inactive-notify@example.com", "active-vm@example.com", true, false, "activevm"],
315 [true, "active-notify@example.com", "inactive-notify@example.com", "active-repo@example.com", false, true, "activerepo"],
316 [true, "active-notify@example.com", "inactive-notify@example.com", "active-both@example.com", true, true, "activeboth"],
318 # Test users with malformed e-mail addresses.
319 [false, [], [], nil, true, true, nil],
320 [false, [], [], "arvados", true, true, nil],
321 [false, [], [], "@example.com", true, true, nil],
322 [true, "active-notify@example.com", "inactive-notify@example.com", "*!*@example.com", true, false, nil],
323 [true, "active-notify@example.com", "inactive-notify@example.com", "*!*@example.com", false, false, nil],
325 # Test users with various username transformations.
326 [false, [], [], "arvados@example.com", false, false, "arvados2"],
327 [true, "active-notify@example.com", "inactive-notify@example.com", "arvados@example.com", false, false, "arvados2"],
328 [true, "active-notify@example.com", "inactive-notify@example.com", "root@example.com", true, false, "root2"],
329 [false, "active-notify@example.com", "inactive-notify@example.com", "root@example.com", true, false, "root2"],
330 [true, "active-notify@example.com", "inactive-notify@example.com", "roo_t@example.com", false, true, "root2"],
331 [false, [], [], "^^incorrect_format@example.com", true, true, "incorrectformat"],
332 [true, "active-notify@example.com", "inactive-notify@example.com", "&4a_d9.@example.com", true, true, "ad9"],
333 [true, "active-notify@example.com", "inactive-notify@example.com", "&4a_d9.@example.com", false, false, "ad9"],
334 [false, "active-notify@example.com", "inactive-notify@example.com", "&4a_d9.@example.com", true, true, "ad9"],
335 [false, "active-notify@example.com", "inactive-notify@example.com", "&4a_d9.@example.com", false, false, "ad9"],
336 ].each do |active, new_user_recipients, inactive_recipients, email, auto_setup_vm, auto_setup_repo, expect_username|
337 test "create new user with auto setup #{active} #{email} #{auto_setup_vm} #{auto_setup_repo}" do
338 set_user_from_auth :admin
340 Rails.configuration.auto_setup_new_users = true
343 Rails.configuration.auto_setup_new_users_with_vm_uuid = virtual_machines(:testvm)['uuid']
345 Rails.configuration.auto_setup_new_users_with_vm_uuid = false
348 Rails.configuration.auto_setup_new_users_with_repository = auto_setup_repo
350 create_user_and_verify_setup_and_notifications active, new_user_recipients, inactive_recipients, email, expect_username
354 test "update existing user" do
355 set_user_from_auth :active # set active user as current user
357 @active_user = users(:active) # get the active user
359 @active_user.first_name = "first_name_changed"
362 @active_user = User.find(@active_user.id) # get the user back
363 assert_equal(@active_user.first_name, 'first_name_changed')
365 # admin user also should be able to update the "active" user info
366 set_user_from_auth :admin # set admin user as current user
367 @active_user.first_name = "first_name_changed_by_admin_for_active_user"
370 @active_user = User.find(@active_user.id) # get the user back
371 assert_equal(@active_user.first_name, 'first_name_changed_by_admin_for_active_user')
374 test "delete a user and verify" do
375 @active_user = users(:active) # get the active user
376 active_user_uuid = @active_user.uuid
378 set_user_from_auth :admin
381 found_deleted_user = false
382 User.find(:all).each do |user|
383 if user.uuid == active_user_uuid
384 found_deleted_user = true
388 assert !found_deleted_user, "found deleted user: "+active_user_uuid
392 test "create new user as non-admin user" do
393 set_user_from_auth :active
398 rescue ArvadosModel::PermissionDeniedError => e
400 assert (e.message.include? 'PermissionDeniedError'),
401 'Expected PermissionDeniedError'
404 test "setup new user" do
405 set_user_from_auth :admin
407 email = 'foo@example.com'
408 openid_prefix = 'http://openid/prefix'
410 user = User.create ({uuid: 'zzzzz-tpzed-abcdefghijklmno', email: email})
412 vm = VirtualMachine.create
414 response = User.setup user, openid_prefix, 'test_repo', vm.uuid
416 resp_user = find_obj_in_resp response, 'User'
417 verify_user resp_user, email
419 oid_login_perm = find_obj_in_resp response, 'Link', 'arvados#user'
421 verify_link oid_login_perm, 'permission', 'can_login', resp_user[:email],
424 assert_equal openid_prefix, oid_login_perm[:properties]['identity_url_prefix'],
425 'expected identity_url_prefix not found for oid_login_perm'
427 group_perm = find_obj_in_resp response, 'Link', 'arvados#group'
428 verify_link group_perm, 'permission', 'can_read', resp_user[:uuid], nil
430 repo_perm = find_obj_in_resp response, 'Link', 'arvados#repository'
431 verify_link repo_perm, 'permission', 'can_manage', resp_user[:uuid], nil
433 vm_perm = find_obj_in_resp response, 'Link', 'arvados#virtualMachine'
434 verify_link vm_perm, 'permission', 'can_login', resp_user[:uuid], vm.uuid
437 test "setup new user with junk in database" do
438 set_user_from_auth :admin
440 email = 'foo@example.com'
441 openid_prefix = 'http://openid/prefix'
443 user = User.create ({uuid: 'zzzzz-tpzed-abcdefghijklmno', email: email})
445 vm = VirtualMachine.create
447 # Set up the bogus Link
448 bad_uuid = 'zzzzz-tpzed-xyzxyzxyzxyzxyz'
450 resp_link = Link.create ({tail_uuid: email, link_class: 'permission',
451 name: 'can_login', head_uuid: bad_uuid})
452 resp_link.save(validate: false)
454 verify_link resp_link, 'permission', 'can_login', email, bad_uuid
456 response = User.setup user, openid_prefix, 'test_repo', vm.uuid
458 resp_user = find_obj_in_resp response, 'User'
459 verify_user resp_user, email
461 oid_login_perm = find_obj_in_resp response, 'Link', 'arvados#user'
463 verify_link oid_login_perm, 'permission', 'can_login', resp_user[:email],
466 assert_equal openid_prefix, oid_login_perm[:properties]['identity_url_prefix'],
467 'expected identity_url_prefix not found for oid_login_perm'
469 group_perm = find_obj_in_resp response, 'Link', 'arvados#group'
470 verify_link group_perm, 'permission', 'can_read', resp_user[:uuid], nil
472 repo_perm = find_obj_in_resp response, 'Link', 'arvados#repository'
473 verify_link repo_perm, 'permission', 'can_manage', resp_user[:uuid], nil
475 vm_perm = find_obj_in_resp response, 'Link', 'arvados#virtualMachine'
476 verify_link vm_perm, 'permission', 'can_login', resp_user[:uuid], vm.uuid
479 test "setup new user in multiple steps" do
480 set_user_from_auth :admin
482 email = 'foo@example.com'
483 openid_prefix = 'http://openid/prefix'
485 user = User.create ({uuid: 'zzzzz-tpzed-abcdefghijklmno', email: email})
487 response = User.setup user, openid_prefix
489 resp_user = find_obj_in_resp response, 'User'
490 verify_user resp_user, email
492 oid_login_perm = find_obj_in_resp response, 'Link', 'arvados#user'
493 verify_link oid_login_perm, 'permission', 'can_login', resp_user[:email],
495 assert_equal openid_prefix, oid_login_perm[:properties]['identity_url_prefix'],
496 'expected identity_url_prefix not found for oid_login_perm'
498 group_perm = find_obj_in_resp response, 'Link', 'arvados#group'
499 verify_link group_perm, 'permission', 'can_read', resp_user[:uuid], nil
501 # invoke setup again with repo_name
502 response = User.setup user, openid_prefix, 'test_repo'
503 resp_user = find_obj_in_resp response, 'User', nil
504 verify_user resp_user, email
505 assert_equal user.uuid, resp_user[:uuid], 'expected uuid not found'
507 group_perm = find_obj_in_resp response, 'Link', 'arvados#group'
508 verify_link group_perm, 'permission', 'can_read', resp_user[:uuid], nil
510 repo_perm = find_obj_in_resp response, 'Link', 'arvados#repository'
511 verify_link repo_perm, 'permission', 'can_manage', resp_user[:uuid], nil
513 # invoke setup again with a vm_uuid
514 vm = VirtualMachine.create
516 response = User.setup user, openid_prefix, 'test_repo', vm.uuid
518 resp_user = find_obj_in_resp response, 'User', nil
519 verify_user resp_user, email
520 assert_equal user.uuid, resp_user[:uuid], 'expected uuid not found'
522 group_perm = find_obj_in_resp response, 'Link', 'arvados#group'
523 verify_link group_perm, 'permission', 'can_read', resp_user[:uuid], nil
525 repo_perm = find_obj_in_resp response, 'Link', 'arvados#repository'
526 verify_link repo_perm, 'permission', 'can_manage', resp_user[:uuid], nil
528 vm_perm = find_obj_in_resp response, 'Link', 'arvados#virtualMachine'
529 verify_link vm_perm, 'permission', 'can_login', resp_user[:uuid], vm.uuid
532 def find_obj_in_resp (response_items, object_type, head_kind=nil)
534 response_items.each { |x|
539 if object_type == 'User'
540 if ArvadosModel::resource_class_for_uuid(x['uuid']) == User
544 else # looking for a link
545 if ArvadosModel::resource_class_for_uuid(x['head_uuid']).kind == head_kind
554 def verify_user (resp_user, email)
555 assert_not_nil resp_user, 'expected user object'
556 assert_not_nil resp_user['uuid'], 'expected user object'
557 assert_equal email, resp_user['email'], 'expected email not found'
561 def verify_link (link_object, link_class, link_name, tail_uuid, head_uuid)
562 assert_not_nil link_object, "expected link for #{link_class} #{link_name}"
563 assert_not_nil link_object[:uuid],
564 "expected non-nil uuid for link for #{link_class} #{link_name}"
565 assert_equal link_class, link_object[:link_class],
566 "expected link_class not found for #{link_class} #{link_name}"
567 assert_equal link_name, link_object[:name],
568 "expected link_name not found for #{link_class} #{link_name}"
569 assert_equal tail_uuid, link_object[:tail_uuid],
570 "expected tail_uuid not found for #{link_class} #{link_name}"
572 assert_equal head_uuid, link_object[:head_uuid],
573 "expected head_uuid not found for #{link_class} #{link_name}"
577 def create_user_and_verify_setup_and_notifications (active, new_user_recipients, inactive_recipients, email, expect_username)
578 Rails.configuration.new_user_notification_recipients = new_user_recipients
579 Rails.configuration.new_inactive_user_notification_recipients = inactive_recipients
581 ActionMailer::Base.deliveries = []
583 can_setup = (Rails.configuration.auto_setup_new_users and
584 (not expect_username.nil?))
585 prior_repo = Repository.where(name: expect_username).first
588 user.first_name = "first_name_for_newly_created_user"
590 user.is_active = active
592 assert_equal(expect_username, user.username)
595 verify_link_exists(Rails.configuration.auto_setup_new_users,
596 groups(:all_users).uuid, user.uuid,
597 "permission", "can_read")
598 # Check for OID login link.
599 verify_link_exists(Rails.configuration.auto_setup_new_users,
600 user.uuid, user.email, "permission", "can_login")
601 # Check for repository.
602 if named_repo = (prior_repo or
603 Repository.where(name: expect_username).first)
604 verify_link_exists((can_setup and prior_repo.nil? and
605 Rails.configuration.auto_setup_new_users_with_repository),
606 named_repo.uuid, user.uuid, "permission", "can_manage")
608 # Check for VM login.
609 if auto_vm_uuid = Rails.configuration.auto_setup_new_users_with_vm_uuid
610 verify_link_exists(can_setup, auto_vm_uuid, user.uuid,
611 "permission", "can_login", "username", expect_username)
614 # check email notifications
616 new_inactive_user_email = nil
618 new_user_email_subject = "#{Rails.configuration.email_subject_prefix}New user created notification"
619 if Rails.configuration.auto_setup_new_users
620 new_user_email_subject = (expect_username or active) ?
621 "#{Rails.configuration.email_subject_prefix}New user created and setup notification" :
622 "#{Rails.configuration.email_subject_prefix}New user created, but not setup notification"
625 ActionMailer::Base.deliveries.each do |d|
626 if d.subject == new_user_email_subject then
628 elsif d.subject == "#{Rails.configuration.email_subject_prefix}New inactive user notification" then
629 new_inactive_user_email = d
633 # both active and inactive user creations should result in new user creation notification mails,
634 # if the new user email recipients config parameter is set
635 if not new_user_recipients.empty? then
636 assert_not_nil new_user_email, 'Expected new user email after setup'
637 assert_equal Rails.configuration.user_notifier_email_from, new_user_email.from[0]
638 assert_equal new_user_recipients, new_user_email.to[0]
639 assert_equal new_user_email_subject, new_user_email.subject
641 assert_nil new_user_email, 'Did not expect new user email after setup'
645 if not inactive_recipients.empty? then
646 assert_not_nil new_inactive_user_email, 'Expected new inactive user email after setup'
647 assert_equal Rails.configuration.user_notifier_email_from, new_inactive_user_email.from[0]
648 assert_equal inactive_recipients, new_inactive_user_email.to[0]
649 assert_equal "#{Rails.configuration.email_subject_prefix}New inactive user notification", new_inactive_user_email.subject
651 assert_nil new_inactive_user_email, 'Did not expect new inactive user email after setup'
654 assert_nil new_inactive_user_email, 'Expected no inactive user email after setting up active user'
656 ActionMailer::Base.deliveries = []
660 def verify_link_exists link_exists, head_uuid, tail_uuid, link_class, link_name, property_name=nil, property_value=nil
661 all_links = Link.where(head_uuid: head_uuid,
662 tail_uuid: tail_uuid,
663 link_class: link_class,
665 assert_equal link_exists, all_links.any?, "Link #{'not' if link_exists} found for #{link_name} #{link_class} #{property_value}"
666 if link_exists && property_name && property_value
667 all_links.each do |link|
668 assert_equal true, all_links.first.properties[property_name].start_with?(property_value), 'Property not found in link'