diff --git a/static/js/directives/ui/manage-trigger-githost/manage-trigger-githost.component.html b/static/js/directives/ui/manage-trigger-githost/manage-trigger-githost.component.html
index c7bdacc10..142ec850e 100644
--- a/static/js/directives/ui/manage-trigger-githost/manage-trigger-githost.component.html
+++ b/static/js/directives/ui/manage-trigger-githost/manage-trigger-githost.component.html
@@ -356,7 +356,10 @@
total-count="$ctrl.local.orderedRobotAccounts.entries.length"
current-page="$ctrl.local.robotOptions.page"
page-size="$ctrl.robotsPerPage">
-
+
diff --git a/static/js/directives/ui/manage-trigger-githost/manage-trigger-githost.component.spec.ts b/static/js/directives/ui/manage-trigger-githost/manage-trigger-githost.component.spec.ts
index 547781352..91a0cf15c 100644
--- a/static/js/directives/ui/manage-trigger-githost/manage-trigger-githost.component.spec.ts
+++ b/static/js/directives/ui/manage-trigger-githost/manage-trigger-githost.component.spec.ts
@@ -1,27 +1,30 @@
-import { ManageTriggerGithostComponent, Local, Trigger } from './manage-trigger-githost.component';
+import { ManageTriggerGithostComponent } from './manage-trigger-githost.component';
+import { Local, Trigger, Repository } from '../../../types/common.types';
+import { Mock } from 'ts-mocks';
+import Spy = jasmine.Spy;
describe("ManageTriggerGithostComponent", () => {
var component: ManageTriggerGithostComponent;
- var apiServiceMock: any;
- var tableServiceMock: any;
- var triggerServiceMock: any;
- var rolesServiceMock: any;
+ var apiServiceMock: Mock;
+ var tableServiceMock: Mock;
+ var triggerServiceMock: Mock;
+ var rolesServiceMock: Mock;
var repository: any;
var trigger: Trigger;
- var $scope: ng.IScope;
+ var $scopeMock: Mock;
beforeEach(inject(($injector: ng.auto.IInjectorService) => {
- apiServiceMock = jasmine.createSpyObj('apiServiceMock', ['listTriggerBuildSourceNamespaces']);
- tableServiceMock = jasmine.createSpyObj('tableServiceMock', ['buildOrderedItems']);
- triggerServiceMock = jasmine.createSpyObj('triggerServiceMock', ['getIcon']);
- rolesServiceMock = jasmine.createSpyObj('rolesServiceMock', ['setRepositoryRole']);
- $scope = $injector.get('$rootScope');
- component = new ManageTriggerGithostComponent(apiServiceMock,
- tableServiceMock,
- triggerServiceMock,
- rolesServiceMock,
- $scope);
+ apiServiceMock = new Mock();
+ tableServiceMock = new Mock();
+ triggerServiceMock = new Mock();
+ rolesServiceMock = new Mock();
+ $scopeMock = new Mock();
+ component = new ManageTriggerGithostComponent(apiServiceMock.Object,
+ tableServiceMock.Object,
+ triggerServiceMock.Object,
+ rolesServiceMock.Object,
+ $scopeMock.Object);
trigger = {service: "serviceMock", id: 1};
component.trigger = trigger;
}));
@@ -36,14 +39,75 @@ describe("ManageTriggerGithostComponent", () => {
describe("getTriggerIcon", () => {
- it("calls trigger service to get icon", () => {
- component.getTriggerIcon();
+ beforeEach(() => {
+ triggerServiceMock.setup(mock => mock.getIcon).is((service: any) => null);
+ });
- expect(triggerServiceMock.getIcon.calls.argsFor(0)[0]).toEqual(component.trigger.service);
+ it("calls trigger service to get icon", () => {
+ const icon: any = component.getTriggerIcon();
+
+ expect((triggerServiceMock.Object.getIcon).calls.argsFor(0)[0]).toEqual(component.trigger.service);
});
});
describe("createTrigger", () => {
- // TODO
+
+ beforeEach(() => {
+ component.local.selectedRepository = new Mock().Object;
+ component.local.selectedRepository.full_name = "someorg/some-repository";
+ component.local.dockerfilePath = "/Dockerfile";
+ component.local.dockerContext = "/";
+ component.local.triggerOptions = {};
+ component.local.triggerAnalysis = {};
+ rolesServiceMock.setup(mock => mock.setRepositoryRole).is((repo, role, entityKind, entityName, callback) => {
+ callback();
+ });
+ });
+
+ it("calls roles service to grant read access to selected robot if robot is required and cannot read", (done) => {
+ component.local.triggerAnalysis = {status: 'requiresrobot', name: 'privatebase', namespace: 'someorg'};
+ component.local.robotAccount = {can_read: false, is_robot: true, kind: 'user', name: 'test-robot'};
+ component.activateTrigger.subscribe((event: {config: any, pull_robot: any}) => {
+ expect((rolesServiceMock.Object.setRepositoryRole).calls.argsFor(0)[0]).toEqual({
+ name: component.local.triggerAnalysis.name,
+ namespace: component.local.triggerAnalysis.namespace,
+ });
+ expect((rolesServiceMock.Object.setRepositoryRole).calls.argsFor(0)[1]).toEqual('read');
+ expect((rolesServiceMock.Object.setRepositoryRole).calls.argsFor(0)[2]).toEqual('robot');
+ done();
+ });
+
+ component.createTrigger();
+ });
+
+ it("does not call roles service if robot is required but already has read access", (done) => {
+ component.local.robotAccount = {can_read: true, is_robot: true, kind: 'user', name: 'test-robot'};
+ component.activateTrigger.subscribe((event: {config: any, pull_robot: any}) => {
+ expect((rolesServiceMock.Object.setRepositoryRole)).not.toHaveBeenCalled();
+ done();
+ });
+
+ component.createTrigger();
+ });
+
+ it("does not call roles service if robot is not required", (done) => {
+ component.activateTrigger.subscribe((event: {config: any, pull_robot: any}) => {
+ expect((rolesServiceMock.Object.setRepositoryRole)).not.toHaveBeenCalled();
+ done();
+ });
+
+ component.createTrigger();
+ });
+
+ it("emits output event with config and pull robot", (done) => {
+ component.activateTrigger.subscribe((event: {config: any, pull_robot: any}) => {
+ expect(event.config.build_source).toEqual(component.local.selectedRepository.full_name);
+ expect(event.config.dockerfile_path).toEqual(component.local.dockerfilePath);
+ expect(event.config.context).toEqual(component.local.dockerContext);
+ done();
+ });
+
+ component.createTrigger();
+ });
});
});
\ No newline at end of file
diff --git a/static/js/directives/ui/manage-trigger-githost/manage-trigger-githost.component.ts b/static/js/directives/ui/manage-trigger-githost/manage-trigger-githost.component.ts
index bc731626b..be7969965 100644
--- a/static/js/directives/ui/manage-trigger-githost/manage-trigger-githost.component.ts
+++ b/static/js/directives/ui/manage-trigger-githost/manage-trigger-githost.component.ts
@@ -1,5 +1,6 @@
import { Input, Output, Component, Inject, EventEmitter, OnInit } from 'ng-metadata/core';
import * as moment from 'moment';
+import { Local, Trigger, Repository, Namespace } from '../../../types/common.types';
/**
@@ -12,30 +13,14 @@ import * as moment from 'moment';
export class ManageTriggerGithostComponent implements OnInit {
// FIXME: Use one-way data binding
- @Input('=') public repository: any;
+ @Input('=') public repository: Repository;
@Input('=') public trigger: Trigger;
@Output() public activateTrigger: EventEmitter<{config: any, pull_robot?: any}> = new EventEmitter();
- private config: any;
- private local: any = {
- namespaceOptions: {
- filter: '',
- predicate: 'score',
- reverse: false,
- page: 0
- },
- repositoryOptions: {
- filter: '',
- predicate: 'score',
- reverse: false,
- page: 0,
- hideStale: true
- },
- robotOptions: {
- filter: '',
- predicate: 'score',
- reverse: false,
- page: 0
- }
+ public config: any;
+ public local: Local = {
+ namespaceOptions: {filter: '', predicate: 'score', reverse: false, page: 0},
+ repositoryOptions: {filter: '', predicate: 'score', reverse: false, page: 0, hideStale: true},
+ robotOptions: {filter: '', predicate: 'score', reverse: false, page: 0},
};
private currentState: any | null;
private namespacesPerPage: number = 10;
@@ -128,23 +113,21 @@ export class ManageTriggerGithostComponent implements OnInit {
context: this.local.dockerContext
};
- if (this.local.triggerOptions.hasBranchTagFilter &&
- this.local.triggerOptions.branchTagFilter) {
- config['branchtag_regex'] = this.local.triggerOptions.branchTagFilter;
+ if (this.local.triggerOptions['hasBranchTagFilter'] && this.local.triggerOptions['branchTagFilter']) {
+ config['branchtag_regex'] = this.local.triggerOptions['branchTagFilter'];
}
- var activate = () => {
+ const activate = () => {
this.activateTrigger.emit({config: config, pull_robot: this.local.robotAccount});
};
- if (this.local.robotAccount && this.local.triggerAnalysis.status == 'requiresrobot') {
+ if (this.local.triggerAnalysis.status == 'requiresrobot' && this.local.robotAccount) {
if (this.local.robotAccount.can_read) {
activate();
} else {
- // Add read permission onto the base repository for the robot and then activate the
- // trigger.
- var robot_name = this.local.robotAccount.name;
- this.RolesService.setRepositoryRole(this.repository, 'read', 'robot', robot_name, activate);
+ // Add read permission onto the base repository for the robot and then activate the trigger.
+ const baseRepo: any = {name: this.local.triggerAnalysis.name, namespace: this.local.triggerAnalysis.namespace};
+ this.RolesService.setRepositoryRole(baseRepo, 'read', 'robot', this.local.robotAccount.name, activate);
}
} else {
activate();
@@ -156,7 +139,7 @@ export class ManageTriggerGithostComponent implements OnInit {
return;
}
- var namespaces = this.local.namespaces || [];
+ var namespaces: Namespace[] = this.local.namespaces || [];
this.local.orderedNamespaces = this.TableService.buildOrderedItems(namespaces,
this.local.namespaceOptions,
['id'],
@@ -305,9 +288,9 @@ export class ManageTriggerGithostComponent implements OnInit {
var robots = this.local.triggerAnalysis.robots;
this.local.orderedRobotAccounts = this.TableService.buildOrderedItems(robots,
- this.local.robotOptions,
- ['name'],
- []);
+ this.local.robotOptions,
+ ['name'],
+ []);
}
private checkDockerfilePath(repository: any, path: string, context: string): void {
@@ -342,38 +325,3 @@ export class ManageTriggerGithostComponent implements OnInit {
}
}
}
-
-
-/**
- * A type representing local application data.
- */
-export type Local = {
- namespaceOptions: {
- filter: string;
- predicate: string;
- reverse: boolean;
- page: number;
- };
- repositoryOptions: {
- filter: string;
- predicate: string;
- reverse: boolean;
- page: number;
- hideStale: boolean;
- };
- robotOptions: {
- filter: string;
- predicate: string;
- reverse: boolean;
- page: number;
- };
-};
-
-
-/**
- * A type representing a trigger.
- */
-export type Trigger = {
- id: number;
- service: any;
-};
\ No newline at end of file
diff --git a/static/js/types/common.types.ts b/static/js/types/common.types.ts
new file mode 100644
index 000000000..316176a34
--- /dev/null
+++ b/static/js/types/common.types.ts
@@ -0,0 +1,104 @@
+import { ViewArray } from '../services/view-array/view-array';
+
+
+/**
+ * A type representing local application data.
+ */
+export type Local = {
+ contexts?: string[];
+ dockerContext?: string;
+ dockerfileLocations?: any;
+ dockerfilePath?: string;
+ hasValidContextLocation?: boolean;
+ hasValidDockerfilePath?: boolean;
+ maxScore?: number;
+ namespaceOptions?: {
+ filter: string;
+ predicate: string;
+ reverse: boolean;
+ page: number;
+ };
+ namespaces?: Namespace[];
+ orderedNamespaces?: ViewArray;
+ orderedRepositories?: ViewArray;
+ orderedRobotAccounts?: ViewArray;
+ repositories?: Repository[];
+ repositoryFullRefs?: {
+ icon: string;
+ title: string;
+ value: string;
+ }[];
+ repositoryOptions?: {
+ filter: string;
+ predicate: string;
+ reverse: boolean;
+ page: number;
+ hideStale: boolean;
+ };
+ repositoryRefs?: {
+ kind: string;
+ name: string;
+ }[];
+ robotAccount?: RobotAccount;
+ robotOptions?: {
+ filter: string;
+ predicate: string;
+ reverse: boolean;
+ page: number;
+ };
+ selectedNamespace?: Namespace;
+ selectedRepository?: Repository;
+ triggerAnalysis?: any;
+ triggerOptions?: {
+ [key: string]: boolean;
+ };
+};
+
+
+/**
+ * A type representing a robot account.
+ */
+export type RobotAccount = {
+ can_read: boolean;
+ is_robot: boolean;
+ kind: string;
+ name: string;
+};
+
+
+/**
+ * A type representing a Git repository.
+ */
+export type Repository = {
+ description: string;
+ full_name: string;
+ has_admin_permissions: boolean;
+ last_updated: number;
+ last_updated_datetime: Date;
+ name: string;
+ private: boolean;
+ url: string;
+ namespace?: string;
+}
+
+
+/**
+ * A type representing a repository namespace.
+ */
+export type Namespace = {
+ avatar_url: string;
+ id: string;
+ personal: boolean;
+ score: number;
+ title: string;
+ url: string;
+};
+
+
+/**
+ * A type representing a trigger.
+ */
+export type Trigger = {
+ id: number;
+ service: any;
+};
\ No newline at end of file
diff --git a/test/data/test.db b/test/data/test.db
index 914c1c29e..abfe7ef07 100644
Binary files a/test/data/test.db and b/test/data/test.db differ