Convert wp-destroy modal

pull/6284/head
Oliver Günther 7 years ago
parent d88dbdb1f7
commit b38d86ee3a
No known key found for this signature in database
GPG Key ID: 88872239EB414F99
  1. 5
      app/assets/stylesheets/content/_forms.sass
  2. 5
      frontend/app/angular4-modules.ts
  3. 1
      frontend/app/angular4-transition-utils.ts
  4. 105
      frontend/app/components/modals/wp-destroy-modal/wp-destroy-modal.controller.ts
  5. 76
      frontend/app/components/modals/wp-destroy-modal/wp-destroy-modal.html
  6. 39
      frontend/app/components/modals/wp-destroy-modal/wp-destroy-modal.ts
  7. 78
      frontend/app/components/modals/wp-destroy-modal/wp-destroy.modal.html
  8. 118
      frontend/app/components/modals/wp-destroy-modal/wp-destroy.modal.ts
  9. 11
      frontend/app/components/op-context-menu/wp-context-menu/wp-single-context-menu.ts
  10. 8
      frontend/app/components/op-context-menu/wp-context-menu/wp-table-context-menu.directive.ts
  11. 76
      frontend/tests/unit/tests/ui_components/focus-directive-test.js

@ -161,7 +161,10 @@ $form--field-types: (text-field, text-area, select, check-box, radio-button, ran
border-bottom-width: 0px
.form--space
padding-top: 10px
padding-top: 1rem
&.-left-spacing
padding-left: 1rem
&.-big
padding-top: 20px

@ -74,7 +74,6 @@ import {
TextileServiceToken,
upgradeService,
upgradeServiceWithToken, WorkPackageServiceToken,
wpDestroyModalToken,
wpMoreMenuServiceToken
} from './angular4-transition-utils';
import {WpCustomActionComponent} from 'core-components/wp-custom-actions/wp-custom-actions/wp-custom-action.component';
@ -220,6 +219,7 @@ import {SaveQueryModal} from "core-components/modals/save-modal/save-query.modal
import {QuerySharingForm} from "core-components/modals/share-modal/query-sharing-form.component";
import {RenameQueryModal} from "core-components/modals/rename-query-modal/rename-query.modal";
import {FocusHelperService} from 'core-components/common/focus/focus-helper';
import {WpDestroyModal} from "core-components/modals/wp-destroy-modal/wp-destroy.modal";
@NgModule({
imports: [
@ -250,7 +250,6 @@ import {FocusHelperService} from 'core-components/common/focus/focus-helper';
PathHelperService,
upgradeServiceWithToken('wpMoreMenuService', wpMoreMenuServiceToken),
TimezoneService,
upgradeServiceWithToken('wpDestroyModal', wpDestroyModalToken),
upgradeService('wpRelations', WorkPackageRelationsService),
UrlParamsHelperService,
WorkPackageCacheService,
@ -453,6 +452,7 @@ import {FocusHelperService} from 'core-components/common/focus/focus-helper';
SaveQueryModal,
QuerySharingForm,
RenameQueryModal,
WpDestroyModal,
// Notifications
NotificationsContainerComponent,
@ -522,6 +522,7 @@ import {FocusHelperService} from 'core-components/common/focus/focus-helper';
QuerySharingModal,
SaveQueryModal,
RenameQueryModal,
WpDestroyModal,
// Notifications
NotificationsContainerComponent,

@ -43,7 +43,6 @@ export const AutoCompleteHelperServiceToken = new InjectionToken<any>('AutoCompl
export const TextileServiceToken = new InjectionToken<any>('TextileServiceToken');
export const wpMoreMenuServiceToken = new InjectionToken<any>('wpMoreMenuService');
export const $httpToken = new InjectionToken<any>('$http');
export const wpDestroyModalToken = new InjectionToken<any>('wpDestroyModal');
export const OpContextMenuLocalsToken = new InjectionToken<any>('CONTEXT_MENU_LOCALS');
export const OpModalLocalsToken = new InjectionToken<any>('OP_MODAL_LOCALS');
export const HookServiceToken = new InjectionToken<any>('HookService');

@ -1,105 +0,0 @@
//-- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2013 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See doc/COPYRIGHT.rdoc for more details.
//++
import {wpControllersModule} from '../../../angular-modules';
import {States} from '../../states.service';
import {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';
import {WorkPackageTableFocusService} from 'core-components/wp-fast-table/state/wp-table-focus.service';
import {StateService} from '@uirouter/core';
export class WorkPackageDestroyModalController {
public text:any;
public workPackages:WorkPackageResource[];
public workPackageLabel:string;
constructor(private $scope:any,
private $state:StateService,
private states:States,
private WorkPackageService:any,
private wpTableFocus:WorkPackageTableFocusService,
private I18n:op.I18n,
private wpDestroyModal:any) {
this.workPackages = $scope.workPackages;
this.workPackageLabel = I18n.t('js.units.workPackage', { count: this.workPackages.length });
this.text = {
close: I18n.t('js.close_popup_title'),
cancel: I18n.t('js.button_cancel'),
confirm: I18n.t('js.button_confirm'),
warning: I18n.t('js.label_warning'),
title: I18n.t('js.modals.destroy_work_package.title', { label: this.workPackageLabel }),
text: I18n.t('js.modals.destroy_work_package.text', { label: this.workPackageLabel, count: this.workPackages.length }),
childCount: (wp:WorkPackageResource) => {
const count = this.children(wp).length;
return this.I18n.t('js.units.child_work_packages', {count: count});
},
hasChildren: (wp:WorkPackageResource) =>
I18n.t('js.modals.destroy_work_package.has_children', {childUnits: this.text.childCount(wp) }),
deletesChildren: I18n.t('js.modals.destroy_work_package.deletes_children')
};
}
public $onInit() {
// Created for interface compliance
}
public close() {
try {
this.wpDestroyModal.deactivate();
} catch(e) {
console.error("Failed to close deletion modal: " + e);
}
}
public confirmDeletion() {
this.wpDestroyModal.deactivate();
this.WorkPackageService.performBulkDelete(this.workPackages.map(el => el.id), true)
.then(() => {
this.close();
this.wpTableFocus.clear();
this.$state.go('work-packages.list');
});
}
public childLabel (workPackage:WorkPackageResource) {
}
public children(workPackage:WorkPackageResource) {
if (workPackage.hasOwnProperty('children')) {
return workPackage.children;
} else {
return [];
}
}
}
wpControllersModule.controller('WorkPackageDestroyModalController', WorkPackageDestroyModalController);

@ -1,76 +0,0 @@
<div class="op-modal--portal" id="wp_destroy_modal">
<div class="op-modal--modal-container">
<div class="op-modal--modal-header">
<a>
<i class="icon-close"
ng-click="$ctrl.close()"
title="{{ ::$ctrl.text.close }}">
</i>
</a>
</div>
<form name="modalWpDestroyForm" class="form danger-zone">
<section class="form--section -inner-scrolling">
<h3 class="form--section-title" ng-bind="::$ctrl.text.title"></h3>
<div ng-if="$ctrl.workPackages.length === 1"
class="modal-inner-scrolling-container"
ng-init="workPackage = $ctrl.workPackages[0]; children = $ctrl.children(workPackage)">
<p>
<span ng-bind="$ctrl.text.text"></span>
<br/>
<strong>
{{ workPackage.type.name }}
#{{ workPackage.id }}
{{ workPackage.subject }}
</strong>
</p>
<div ng-if="children.length > 0">
<p class="danger-zone--warning">
<span class="icon icon-error"></span>
<strong ng-bind="$ctrl.text.warning"></strong>:
<span ng-bind="$ctrl.text.hasChildren(workPackage)"></span>
</p>
<ul>
<li ng-repeat="child in children track by $index">
#<span ng-bind="child.id"></span>
<span ng-bind="child.subject"></span>
</li>
</ul>
<p>
<span ng-bind="$ctrl.text.deletesChildren"></span>
</p>
</div>
</div>
<div class="modal-inner-scrolling-container" ng-if="$ctrl.workPackages.length > 1">
<p class="danger-zone--warning">
<span class="icon icon-error"></span>
<strong ng-bind="$ctrl.text.text"></strong>
</p>
<ul>
<li ng-repeat="wp in $ctrl.workPackages track by $index">
#<span ng-bind="wp.id"></span>
<span ng-bind="wp.subject"></span>
<strong ng-if="$ctrl.children(wp).length > 0">
(&plus; {{ $ctrl.text.childCount(wp) }})
</strong>
</li>
</ul>
</div>
</section>
<div class="form--space -left-spacing">
<button class="button -danger"
ng-bind="::$ctrl.text.confirm"
ng-click="$ctrl.confirmDeletion()">
</button>
<button class="button"
ng-bind="::$ctrl.text.cancel"
ng-click="$ctrl.close()">
</button>
</div>
</form>
</div>
</div>

@ -1,39 +0,0 @@
//-- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2013 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See doc/COPYRIGHT.rdoc for more details.
//++
import {wpControllersModule} from '../../../angular-modules';
function wpDestroyService(btfModal:any) {
return btfModal({
controller: 'WorkPackageDestroyModalController',
controllerAs: '$ctrl',
templateUrl: '/components/modals/wp-destroy-modal/wp-destroy-modal.html'
});
}
wpControllersModule.factory('wpDestroyModal', wpDestroyService);

@ -0,0 +1,78 @@
<div class="op-modal--portal ">
<div id="wp_destroy_modal"
class="op-modal--modal-container wp-table--configuration-modal loading-indicator--location"
data-indicator-name="modal"
tabindex="0">
<div class="op-modal--modal-header">
<a class="op-modal--modal-close-button">
<i
class="icon-close"
(click)="closeMe($event)"
[attr.title]="text.close">
</i>
</a>
</div>
<form name="modalWpDestroyForm" class="form danger-zone">
<section class="form--section -inner-scrolling">
<h3 class="form--section-title" [textContent]="text.title"></h3>
<div *ngIf="singleWorkPackage"
class="modal-inner-scrolling-container">
<p>
<span [textContent]="text.text"></span>
<br/>
<strong>
{{ singleWorkPackage.type.name }}
#{{ singleWorkPackage.id }}
{{ singleWorkPackage.subject }}
</strong>
</p>
<div *ngIf="singleWorkPackageChildren && singleWorkPackageChildren.length > 0">
<p class="danger-zone--warning">
<span class="icon icon-error"></span>
<strong [textContent]="text.warning"></strong>:
<span [textContent]="text.hasChildren(singleWorkPackage)"></span>
</p>
<ul>
<li *ngFor="let child of singleWorkPackageChildren">
#<span [textContent]="child.id"></span>
<span [textContent]="child.subject"></span>
</li>
</ul>
<p>
<span [textContent]="text.deletesChildren"></span>
</p>
</div>
</div>
<div class="modal-inner-scrolling-container" *ngIf="workPackages.length > 1">
<p class="danger-zone--warning">
<span class="icon icon-error"></span>
<strong [textContent]="text.text"></strong>
</p>
<ul>
<li *ngFor="let wp of workPackages">
#<span [textContent]="wp.id"></span>
<span [textContent]="wp.subject"></span>
<strong *ngIf="children(wp).length > 0">
(+ {{ text.childCount(wp) }})
</strong>
</li>
</ul>
</div>
</section>
<div class="form--space -left-spacing">
<button class="button -danger"
[textContent]="text.confirm"
(click)="confirmDeletion($event)">
</button>
<button class="button"
[textContent]="text.cancel"
(click)="closeMe($event)">
</button>
</div>
</form>
</div>
</div>

@ -0,0 +1,118 @@
//-- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2013 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See doc/COPYRIGHT.rdoc for more details.
//++
import {WorkPackagesListService} from '../../wp-list/wp-list.service';
import {States} from '../../states.service';
import {WorkPackageNotificationService} from '../../wp-edit/wp-notification.service';
import {NotificationsService} from "core-components/common/notifications/notifications.service";
import {OpModalComponent} from "core-components/op-modals/op-modal.component";
import {Component, ElementRef, Inject, OnInit} from "@angular/core";
import {$stateToken, I18nToken, OpModalLocalsToken, WorkPackageServiceToken} from "core-app/angular4-transition-utils";
import {OpModalLocalsMap} from "core-components/op-modals/op-modal.types";
import {WorkPackageResource} from 'core-app/modules/hal/resources/work-package-resource';
import {WorkPackageTableFocusService} from 'core-components/wp-fast-table/state/wp-table-focus.service';
import {StateService} from '@uirouter/core';
@Component({
template: require('!!raw-loader!./wp-destroy.modal.html')
})
export class WpDestroyModal extends OpModalComponent implements OnInit {
// When deleting multiple
public workPackages:WorkPackageResource[];
public workPackageLabel:string;
// Single work package
public singleWorkPackage:WorkPackageResource;
public singleWorkPackageChildren:WorkPackageResource[];
public text:{ [key:string]:any } = {
label_visibility_settings: this.I18n.t('js.label_visibility_settings'),
button_save: this.I18n.t('js.modals.button_save'),
confirm: this.I18n.t('js.button_confirm'),
warning: this.I18n.t('js.label_warning'),
cancel: this.I18n.t('js.button_cancel'),
close: this.I18n.t('js.close_popup_title'),
};
constructor(readonly elementRef:ElementRef,
@Inject(WorkPackageServiceToken) readonly WorkPackageService:any,
@Inject(OpModalLocalsToken) public locals:OpModalLocalsMap,
@Inject(I18nToken) readonly I18n:op.I18n,
@Inject($stateToken) readonly $state:StateService,
readonly states:States,
readonly wpTableFocus:WorkPackageTableFocusService,
readonly wpListService:WorkPackagesListService,
readonly wpNotificationsService:WorkPackageNotificationService,
readonly notificationsService:NotificationsService) {
super(locals, elementRef);
}
ngOnInit() {
super.ngOnInit();
this.workPackages = this.locals.workPackages;
this.workPackageLabel = this.I18n.t('js.units.workPackage', { count: this.workPackages.length });
// Ugly way to provide the same view bindings as the ng-init in the previous template.
if (this.workPackages.length === 1) {
this.singleWorkPackage = this.workPackages[0];
this.singleWorkPackageChildren = this.singleWorkPackage.children;
}
this.text.title = this.I18n.t('js.modals.destroy_work_package.title', { label: this.workPackageLabel }),
this.text.text = this.I18n.t('js.modals.destroy_work_package.text', { label: this.workPackageLabel, count: this.workPackages.length }),
this.text.childCount = (wp:WorkPackageResource) => {
const count = this.children(wp).length;
return this.I18n.t('js.units.child_work_packages', {count: count});
};
this.text.hasChildren = (wp:WorkPackageResource) =>
this.I18n.t('js.modals.destroy_work_package.has_children', {childUnits: this.text.childCount(wp) }),
this.text.deletesChildren = this.I18n.t('js.modals.destroy_work_package.deletes_children');
}
public confirmDeletion($event:JQueryEventObject) {
this.WorkPackageService.performBulkDelete(this.workPackages.map(el => el.id), true)
.then(() => {
this.closeMe($event);
this.wpTableFocus.clear();
this.$state.go('work-packages.list');
});
}
public children(workPackage:WorkPackageResource) {
if (workPackage.hasOwnProperty('children')) {
return workPackage.children;
} else {
return [];
}
}
}

@ -2,8 +2,7 @@ import {Directive, ElementRef, Inject, Input} from "@angular/core";
import {WorkPackageAction} from "core-components/wp-table/context-menu-helper/wp-context-menu-helper.service";
import {
$stateToken,
HookServiceToken,
wpDestroyModalToken
HookServiceToken
} from "core-app/angular4-transition-utils";
import {LinkHandling} from "core-components/common/link-handling/link-handling";
import {OPContextMenuService} from "core-components/op-context-menu/op-context-menu.service";
@ -13,6 +12,8 @@ import {OpContextMenuTrigger} from "core-components/op-context-menu/handlers/op-
import {WorkPackageAuthorization} from "core-components/work-packages/work-package-authorization.service";
import {AuthorisationService} from "core-components/common/model-auth/model-auth.service";
import {StateService} from "@uirouter/core";
import {OpModalService} from "core-components/op-modals/op-modal.service";
import {WpDestroyModal} from "core-components/modals/wp-destroy-modal/wp-destroy.modal";
@Directive({
selector: '[wpSingleContextMenu]'
@ -21,9 +22,9 @@ export class WorkPackageSingleContextMenuDirective extends OpContextMenuTrigger
@Input('wpSingleContextMenu-workPackage') public workPackage:WorkPackageResource;
constructor(@Inject(HookServiceToken) readonly HookService:any,
@Inject(wpDestroyModalToken) readonly wpDestroyModal:any,
@Inject($stateToken) readonly $state:StateService,
readonly elementRef:ElementRef,
readonly opModalService:OpModalService,
readonly opContextMenuService:OPContextMenuService,
readonly authorisationService:AuthorisationService) {
super(elementRef, opContextMenuService);
@ -50,7 +51,7 @@ export class WorkPackageSingleContextMenuDirective extends OpContextMenuTrigger
this.$state.go('work-packages.copy', {copiedFromWorkPackageId: this.workPackage.id});
break;
case 'delete':
this.wpDestroyModal.activate({workPackages: [this.workPackage]});
this.opModalService.show(WpDestroyModal, {workPackages: [this.workPackage]});
break;
default:
@ -78,7 +79,7 @@ export class WorkPackageSingleContextMenuDirective extends OpContextMenuTrigger
private getPermittedPluginActions(authorization:WorkPackageAuthorization) {
var pluginActions:WorkPackageAction[] = [];
angular.forEach(this.HookService.call('workPackageDetailsMoreMenu'), function (action) {
angular.forEach(this.HookService.call('workPackageDetailsMoreMenu'), function(action) {
pluginActions = pluginActions.concat(action);
});

@ -6,7 +6,7 @@ import {
import {WorkPackageTable} from "core-components/wp-fast-table/wp-fast-table";
import {States} from "core-components/states.service";
import {WorkPackageRelationsHierarchyService} from "core-components/wp-relations/wp-relations-hierarchy/wp-relations-hierarchy.service";
import {$stateToken, wpDestroyModalToken} from "core-app/angular4-transition-utils";
import {$stateToken} from "core-app/angular4-transition-utils";
import {WorkPackageTableSelection} from "core-components/wp-fast-table/state/wp-table-selection.service";
import {LinkHandling} from "core-components/common/link-handling/link-handling";
import {OpContextMenuHandler} from "core-components/op-context-menu/op-context-menu-handler";
@ -16,12 +16,14 @@ import {
OpContextMenuLocalsMap
} from "core-components/op-context-menu/op-context-menu.types";
import {PERMITTED_CONTEXT_MENU_ACTIONS} from "core-components/op-context-menu/wp-context-menu/wp-static-context-menu-actions";
import {OpModalService} from "core-components/op-modals/op-modal.service";
import {WpDestroyModal} from "core-components/modals/wp-destroy-modal/wp-destroy.modal";
export class OpWorkPackageContextMenu extends OpContextMenuHandler {
private states = this.injector.get(States);
private wpRelationsHierarchyService = this.injector.get(WorkPackageRelationsHierarchyService);
private wpDestroyModal = this.injector.get(wpDestroyModalToken);
private opModalService:OpModalService = this.injector.get(OpModalService);
private $state = this.injector.get($stateToken);
private wpTableSelection = this.injector.get(WorkPackageTableSelection);
private WorkPackageContextMenuHelper = this.injector.get(WorkPackageContextMenuHelperService);
@ -89,7 +91,7 @@ export class OpWorkPackageContextMenu extends OpContextMenuHandler {
private deleteSelectedWorkPackages() {
var selected = this.getSelectedWorkPackages();
this.wpDestroyModal.activate({workPackages: selected});
this.opModalService.show(WpDestroyModal, {workPackages: selected});
}
private editSelectedWorkPackages(link:any) {

@ -1,76 +0,0 @@
//-- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2017 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See docs/COPYRIGHT.rdoc for more details.
//++
/*jshint expr: true*/
describe('focus Directive', function() {
var doc, compile, element, rootScope, scope, timeout, body;
var input = '<input type="text" name="testInput" focus id="focusTest"></input>',
element = angular.element(input);
beforeEach(angular.mock.module('openproject.uiComponents'));
beforeEach(angular.mock.module('openproject.templates'));
beforeEach(angular.mock.module('openproject.uiComponents', function($provide) {
var configurationService = {};
configurationService.isTimezoneSet = sinon.stub().returns(false);
configurationService.accessibilityModeEnabled = sinon.stub().returns(false);
$provide.constant('ConfigurationService', configurationService);
}));
beforeEach(inject(function($compile, $rootScope, $document, $timeout) {
doc = $document[0];
rootScope = $rootScope;
scope = $rootScope.$new();
body = angular.element(doc.body);
body.append(element);
compile = $compile;
timeout = $timeout;
}));
afterEach(function() {
var body = angular.element(doc.body);
body.find('#focusTest').remove();
});
describe('element', function() {
it('should focus the element', function() {
compile(element)(scope);
scope.$digest();
timeout.flush();
expect(doc.activeElement).to.equal(element[0]);
});
});
});
Loading…
Cancel
Save