@@ -389,4 +389,200 @@ private function add_data(array $data, $datatable, $mapvar = '', array $replvars
389
389
}
390
390
391
391
}
392
+
393
+ /**
394
+ * Uploads a file to the specified filemanager leaving other fields in upload form default. The paths should be relative to moodle codebase.
395
+ *
396
+ * @When /^I upload "(?P<filepath_string>(?:[^"]|\\")*)" to questionnaire filemanager$/
397
+ * @throws DriverException
398
+ * @throws ExpectationException Thrown by behat_base::find
399
+ * @param string $filepath
400
+ */
401
+ public function i_upload_file_to_questionnaire_filemanager ($ filepath ) {
402
+ $ this ->upload_file_to_filemanager_questionnaire ($ filepath , new TableNode (array ()));
403
+ }
404
+
405
+ /**
406
+ * Try to get the filemanager node specified by the element
407
+ *
408
+ * @param string $filepickerelement
409
+ * @return \Behat\Mink\Element\NodeElement
410
+ * @throws ExpectationException
411
+ */
412
+ protected function get_filemanager () {
413
+
414
+ // If no file picker label is mentioned take the first file picker from the page.
415
+ return $ this ->find (
416
+ 'xpath ' ,
417
+ '//div[contains(concat(" ", normalize-space(@class), " "), " filemanager ")] '
418
+ );
419
+ }
420
+
421
+ /**
422
+ * Uploads a file to filemanager
423
+ *
424
+ * @throws DriverException
425
+ * @throws ExpectationException Thrown by behat_base::find
426
+ * @param string $filepath Normally a path relative to $CFG->dirroot, but can be an absolute path too.
427
+ * @param string $filemanagerelement
428
+ * @param TableNode $data Data to fill in upload form
429
+ * @param false|string $overwriteaction false if we don't expect that file with the same name already exists,
430
+ * or button text in overwrite dialogue ("Overwrite", "Rename to ...", "Cancel")
431
+ */
432
+ protected function upload_file_to_filemanager_questionnaire ($ filepath , TableNode $ data , $ overwriteaction = false ) {
433
+ global $ CFG ;
434
+
435
+ if (!$ this ->has_tag ('_file_upload ' )) {
436
+ throw new DriverException ('File upload tests must have the @_file_upload tag on either the scenario or feature. ' );
437
+ }
438
+
439
+ $ filemanagernode = $ this ->get_filemanager ();
440
+
441
+ // Opening the select repository window and selecting the upload repository.
442
+ $ this ->open_add_file_window ($ filemanagernode , get_string ('pluginname ' , 'repository_upload ' ));
443
+
444
+ // Ensure all the form is ready.
445
+ $ noformexception = new ExpectationException ('The upload file form is not ready ' , $ this ->getSession ());
446
+ $ this ->find (
447
+ 'xpath ' ,
448
+ "//div[contains(concat(' ', normalize-space(@class), ' '), ' container ')] " .
449
+ "[contains(concat(' ', normalize-space(@class), ' '), ' repository_upload ')] " .
450
+ "/descendant::div[contains(concat(' ', normalize-space(@class), ' '), ' file-picker ')] " .
451
+ "/descendant::div[contains(concat(' ', normalize-space(@class), ' '), ' fp-content ')] " .
452
+ "/descendant::div[contains(concat(' ', normalize-space(@class), ' '), ' fp-upload-form ')] " .
453
+ "/descendant::form " ,
454
+ $ noformexception
455
+ );
456
+ // After this we have the elements we want to interact with.
457
+
458
+ // Form elements to interact with.
459
+ $ file = $ this ->find_file ('repo_upload_file ' );
460
+
461
+ // Attaching specified file to the node.
462
+ // Replace 'admin/' if it is in start of path with $CFG->admin .
463
+ if (substr ($ filepath , 0 , 6 ) === 'admin/ ' ) {
464
+ $ filepath = $ CFG ->dirroot . DIRECTORY_SEPARATOR . $ CFG ->admin .
465
+ DIRECTORY_SEPARATOR . substr ($ filepath , 6 );
466
+ }
467
+ $ filepath = str_replace ('/ ' , DIRECTORY_SEPARATOR , $ filepath );
468
+ if (!is_readable ($ filepath )) {
469
+ $ filepath = $ CFG ->dirroot . DIRECTORY_SEPARATOR . $ filepath ;
470
+ if (!is_readable ($ filepath )) {
471
+ throw new ExpectationException ('The file to be uploaded does not exist. ' , $ this ->getSession ());
472
+ }
473
+ }
474
+ $ file ->attachFile ($ filepath );
475
+
476
+ // Fill the form in Upload window.
477
+ $ datahash = $ data ->getRowsHash ();
478
+
479
+ // The action depends on the field type.
480
+ foreach ($ datahash as $ locator => $ value ) {
481
+
482
+ $ field = behat_field_manager::get_form_field_from_label ($ locator , $ this );
483
+
484
+ // Delegates to the field class.
485
+ $ field ->set_value ($ value );
486
+ }
487
+
488
+ // Submit the file.
489
+ $ submit = $ this ->find_button (get_string ('upload ' , 'repository ' ));
490
+ $ submit ->press ();
491
+
492
+ // We wait for all the JS to finish as it is performing an action.
493
+ $ this ->getSession ()->wait (self ::get_timeout (), self ::PAGE_READY_JS );
494
+
495
+ if ($ overwriteaction !== false ) {
496
+ $ overwritebutton = $ this ->find_button ($ overwriteaction );
497
+ $ this ->ensure_node_is_visible ($ overwritebutton );
498
+ $ overwritebutton ->click ();
499
+
500
+ // We wait for all the JS to finish.
501
+ $ this ->getSession ()->wait (self ::get_timeout (), self ::PAGE_READY_JS );
502
+ }
503
+
504
+ }
505
+
506
+ /**
507
+ * Try to get the filemanager node specified by the element
508
+ *
509
+ * @param string $filepickerelement
510
+ * @return \Behat\Mink\Element\NodeElement
511
+ * @throws ExpectationException
512
+ */
513
+ protected function get_filepicker_node ($ filepickerelement ) {
514
+
515
+ // More info about the problem (in case there is a problem).
516
+ $ exception = new ExpectationException ('" ' . $ filepickerelement . '" filepicker can not be found ' , $ this ->getSession ());
517
+
518
+ // If no file picker label is mentioned take the first file picker from the page.
519
+ if (empty ($ filepickerelement )) {
520
+ $ filepickercontainer = $ this ->find (
521
+ 'xpath ' ,
522
+ "//*[@class= \"form-filemanager \"] " ,
523
+ $ exception
524
+ );
525
+ } else {
526
+ // Gets the filemanager node specified by the locator which contains the filepicker container
527
+ // either for filepickers created by mform or by admin config.
528
+ $ filepickerelement = behat_context_helper::escape ($ filepickerelement );
529
+ $ filepickercontainer = $ this ->find (
530
+ 'xpath ' ,
531
+ "//input[./@id = substring-before(//p[normalize-space(.)= $ filepickerelement]/@id, '_label')] " .
532
+ "//ancestor::*[@data-fieldtype = 'filemanager' or @data-fieldtype = 'filepicker'] " ,
533
+ $ exception
534
+ );
535
+ }
536
+
537
+ return $ filepickercontainer ;
538
+ }
539
+ /**
540
+ * Opens the filepicker modal window and selects the repository.
541
+ *
542
+ * @throws ExpectationException Thrown by behat_base::find
543
+ * @param NodeElement $filemanagernode The filemanager or filepicker form element DOM node.
544
+ * @param mixed $repositoryname The repo name.
545
+ * @return void
546
+ */
547
+ protected function open_add_file_window ($ filemanagernode , $ repositoryname ) {
548
+ $ exception = new ExpectationException ('No files can be added to the specified filemanager ' , $ this ->getSession ());
549
+
550
+ // We should deal with single-file and multiple-file filemanagers,
551
+ // catching the exception thrown by behat_base::find() in case is not multiple
552
+ $ this ->execute ('behat_general::i_click_on_in_the ' , [
553
+ 'div.fp-btn-add a, input.fp-btn-choose ' , 'css_element ' ,
554
+ $ filemanagernode , 'NodeElement '
555
+ ]);
556
+
557
+ // Wait for the default repository (if any) to load. This checks that
558
+ // the relevant div exists and that it does not include the loading image.
559
+ $ this ->ensure_element_exists (
560
+ "//div[contains(concat(' ', normalize-space(@class), ' '), ' file-picker ')] " .
561
+ "//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-content ')] " .
562
+ "[not(descendant::div[contains(concat(' ', normalize-space(@class), ' '), ' fp-content-loading ')])] " ,
563
+ 'xpath_element ' );
564
+
565
+ // Getting the repository link and opening it.
566
+ $ repoexception = new ExpectationException ('The " ' . $ repositoryname . '" repository has not been found ' , $ this ->getSession ());
567
+
568
+ // Avoid problems with both double and single quotes in the same string.
569
+ $ repositoryname = behat_context_helper::escape ($ repositoryname );
570
+
571
+ // Here we don't need to look inside the selected element because there can only be one modal window.
572
+ $ repositorylink = $ this ->find (
573
+ 'xpath ' ,
574
+ "//div[contains(concat(' ', normalize-space(@class), ' '), ' fp-repo-area ')] " .
575
+ "//descendant::span[contains(concat(' ', normalize-space(@class), ' '), ' fp-repo-name ')] " .
576
+ "[normalize-space(.)= $ repositoryname] " ,
577
+ $ repoexception
578
+ );
579
+
580
+ // Selecting the repo.
581
+ $ this ->ensure_node_is_visible ($ repositorylink );
582
+ if (!$ repositorylink ->getParent ()->getParent ()->hasClass ('active ' )) {
583
+ // If the repository link is active, then the repository is already loaded.
584
+ // Clicking it while it's active causes issues, so only click it when it isn't (see MDL-51014).
585
+ $ this ->execute ('behat_general::i_click_on ' , [$ repositorylink , 'NodeElement ' ]);
586
+ }
587
+ }
392
588
}
0 commit comments