+
+
+
+
{{t 'githubIntegration'}}
-
-
-
\ No newline at end of file
+
diff --git a/app/templates/components/jira-account.emblem b/app/templates/components/jira-account.emblem
deleted file mode 100644
index a03a49664..000000000
--- a/app/templates/components/jira-account.emblem
+++ /dev/null
@@ -1,34 +0,0 @@
-if isJIRAConnected
- .integration.integration-jira
- .integration-logo-container
- img.integration-logo src="/images/jira-icon.png"
- .integration-account-container
- .integration-account
- div
- .text-lightgray.padding-b-q
- | #{connectedHost}
- .black-text
- | #{connectedUsername}
- button.is-primary.mp-jira-revoke click="openRevokeJIRAConfirmBox"
- = t "disconnect"
-else
- if checkJIRA.isRunning
- i.fa class="fa-spinner fa-spin margin-r-h"
- | #{t "loading"}...
- else
- form
- .input-wrap
- = input class="input-field" classNameBindings="changeset.error.host:has-error" placeholder=(t "jiraHost") type="text" value=changeset.host
- .input-wrap
- .half-wrap
- = input class="input-field" classNameBindings="changeset.error.username:has-error" placeholder=(t "username") type="text" value=changeset.username
- = input class="input-field" classNameBindings="changeset.error.password:has-error" placeholder=(t "apiKey") type="password" value=changeset.password autocomplete="jira-password"
-
- button.is-primary click={(perform integrateJIRA changeset)} class="mp-jira-integrate" disabled=isIntegratingJIRA
- if integrateJIRA.isRunning
- .fa-font-size
- i.fa class="fa-spinner fa-spin"
- |
- = t "integrateJIRA"
-
-= confirm-box isActive=showRevokeJIRAConfirmBox title=(t 'confirmBox.revokeJira') delegate=this disabled=isRevokingJIRA
diff --git a/config/environment.js b/config/environment.js
index ea9712183..ed3e520b0 100644
--- a/config/environment.js
+++ b/config/environment.js
@@ -13,6 +13,7 @@ const possibleENVS = [
'WHITELABEL_LOGO',
'WHITELABEL_THEME',
'WHITELABEL_FAVICON',
+ 'IRENE_SHOW_JIRA_CLOUD',
];
const ENVHandlerCONST = {
@@ -31,6 +32,7 @@ const ENVHandlerCONST = {
WHITELABEL_NAME: '',
WHITELABEL_LOGO: '',
WHITELABEL_THEME: 'dark',
+ IRENE_SHOW_JIRA_CLOUD: true,
},
processENV: Object.keys(process.env).reduce((acc, key) => {
@@ -144,6 +146,7 @@ module.exports = function (environment) {
var devicefarmHost = handler.getEnv('IRENE_DEVICEFARM_HOST');
var isEnterprise = handler.getBoolean('ENTERPRISE');
var showLicense = handler.getBoolean('IRENE_SHOW_LICENSE');
+ var showJiraCloud = handler.getBoolean('IRENE_SHOW_JIRA_CLOUD');
var ENV = {
ENVHandlerCONST: ENVHandlerCONST,
version: Date.now(),
@@ -151,6 +154,7 @@ module.exports = function (environment) {
isAppknox: false,
isEnterprise: isEnterprise,
showLicense: showLicense,
+ showJiraCloud: showJiraCloud,
exportApplicationGlobal: true,
devknoxPrice: 9, // This should also change in `mycroft/settings.py`
platform: -1,
@@ -469,6 +473,11 @@ module.exports = function (environment) {
module: 'Report',
product: 'Appknox',
},
+ integrateJIRACloud: {
+ feature: 'Integrate JIRA Cloud',
+ module: 'Report',
+ product: 'Appknox',
+ },
changePassword: {
feature: 'Change Password',
module: 'Setup',
diff --git a/tests/integration/components/jira-account-test.js b/tests/integration/components/jira-account-test.js
deleted file mode 100644
index 33f3b1e2d..000000000
--- a/tests/integration/components/jira-account-test.js
+++ /dev/null
@@ -1,50 +0,0 @@
-// import { getOwner } from '@ember/application';
-// import tHelper from 'ember-i18n/helper';
-// import localeConfig from 'ember-i18n/config/en';
-// import { test, moduleForComponent } from 'ember-qunit';
-// import { startMirage } from 'irene/initializers/ember-cli-mirage';
-// import { run } from '@ember/runloop';
-//
-// moduleForComponent('jira-account', 'Integration | Component | jira account', {
-// unit: true,
-// needs: [
-// 'service:i18n',
-// 'service:ajax',
-// 'service:notifications',
-// 'service:session',
-// 'locale:en/translations',
-// 'locale:en/config',
-// 'util:i18n/missing-message',
-// 'util:i18n/compile-template',
-// 'config:environment'
-// ],
-// beforeEach() {
-// // set the locale and the config
-// getOwner(this).lookup('service:i18n').set('locale', 'en');
-// this.register('locale:en/config', localeConfig);
-//
-// // register t helper
-// this.register('helper:t', tHelper);
-//
-// // start Mirage
-// this.server = startMirage();
-// },
-// afterEach() {
-// // shutdown Mirage
-// this.server.shutdown();
-// }
-// });
-//
-// test('tapping button fires an external action', function(assert) {
-//
-// var component = this.subject();
-//
-// run(function() {
-// component.send('openRevokeJIRAConfirmBox');
-// assert.equal(component.get('showRevokeJIRAConfirmBox'),true, "Open Modal");
-// component.send('closeRevokeJIRAConfirmBox');
-// assert.equal(component.get('showRevokeJIRAConfirmBox'),false, "Close Modal");
-//
-// assert.equal(component.confirmCallback(),undefined, "Confirm Callback");
-// });
-// });
diff --git a/tests/integration/components/jira-integration-test.js b/tests/integration/components/jira-integration-test.js
new file mode 100644
index 000000000..dc7dda0fb
--- /dev/null
+++ b/tests/integration/components/jira-integration-test.js
@@ -0,0 +1,189 @@
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'ember-qunit';
+import { render, click } from '@ember/test-helpers';
+import { hbs } from 'ember-cli-htmlbars';
+import { setupIntl } from 'ember-intl/test-support';
+import { setupMirage } from 'ember-cli-mirage/test-support';
+import ENV from 'irene/config/environment';
+import Service from '@ember/service';
+
+class NotificationsStub extends Service {
+ errorMsg = null;
+ successMsg = null;
+ error(msg) {
+ return (this.errorMsg = msg);
+ }
+ success(msg) {
+ return (this.successMsg = msg);
+ }
+}
+
+module('Integration | Component | jira-integration', function (hooks) {
+ setupRenderingTest(hooks);
+ setupMirage(hooks);
+ setupIntl(hooks);
+
+ hooks.beforeEach(async function () {
+ await this.server.createList('organization', 2);
+ await this.owner.lookup('service:organization').load();
+ this.owner.register('service:notifications', NotificationsStub);
+ });
+
+ test('it should render on-premise integration', async function (assert) {
+ ENV.showJiraCloud = false;
+ this.server.get('organizations/:orgId/integrate_jira', () => {
+ return Response(404);
+ });
+ await render(hbs`
`);
+ assert.dom(`[data-test-jira-cloud-integration]`).doesNotExist();
+ assert.dom(`[data-test-jira-on-premise-integration-title]`).exists();
+ assert
+ .dom(`[data-test-jira-on-premise-integration-title]`)
+ .hasText(`t:jiraOnPremiseIntegration:()`);
+ assert.dom(`[data-test-jira-on-premise-integration-form]`).exists();
+ assert.dom(`[data-test-jira-integrated]`).doesNotExist();
+ });
+
+ test('it should render both cloud & on-premise integration', async function (assert) {
+ ENV.showJiraCloud = true;
+ await render(hbs`
`);
+
+ assert.dom(`[data-test-jira-cloud-integration]`).exists();
+ assert.dom(`[data-test-jira-on-premise-integration-title]`).exists();
+ assert
+ .dom(`[data-test-jira-cloud-integration-title]`)
+ .hasText(`t:jiraCloudIntegration:()`);
+ assert.dom(`[data-test-jira-cloud-integration-btn]`).exists();
+ assert.dom(`[data-test-jira-integrated]`).doesNotExist();
+ });
+
+ test('it should render jira cloud integrated container', async function (assert) {
+ ENV.showJiraCloud = true;
+ this.server.get('organizations/:orgId/integrate_jira', () => {
+ return {
+ type: 'jira_cloud_oauth',
+ accounts: 'http://test.com',
+ };
+ });
+ await render(hbs`
`);
+
+ assert.dom(`[data-test-jira-on-premise-integration-title]`).doesNotExist();
+ assert.dom(`[data-test-jira-cloud-integration-title]`).exists();
+ assert.dom(`[data-test-jira-cloud-integration-btn]`).doesNotExist();
+ assert.dom(`[data-test-jira-integrated-host]`).hasText('http://test.com');
+ });
+
+ test('it should render jira on-premise integrated container', async function (assert) {
+ this.server.get('organizations/:orgId/integrate_jira', () => {
+ return {
+ type: 'jira',
+ host: 'http://test.com',
+ username: 'testuser',
+ };
+ });
+ await render(hbs`
`);
+
+ assert.dom(`[data-test-jira-on-premise-integration-title]`).exists();
+ assert.dom(`[data-test-jira-cloud-integration-title]`).doesNotExist();
+ assert.dom(`[data-test-jira-cloud-integration-btn]`).doesNotExist();
+ assert.dom(`[data-test-jira-integrated-host]`).hasText('http://test.com');
+ assert.dom(`[data-test-jira-integrated-username]`).hasText('testuser');
+ });
+
+ test('it should render jira integrated container', async function (assert) {
+ this.server.get('organizations/:orgId/integrate_jira', () => {
+ return {
+ type: 'jira',
+ host: 'http://test.com',
+ username: 'testuser',
+ };
+ });
+ await render(hbs`
`);
+
+ assert
+ .dom(`[data-test-jira-logo]`)
+ .hasAttribute('src', '/images/jira-icon.png');
+ assert.dom(`[data-test-jira-integrated-host]`).hasText('http://test.com');
+ assert.dom(`[data-test-jira-integrated-username]`).hasText('testuser');
+ assert.dom(`[data-test-jira-disconnect-btn]`).hasText(`t:disconnect:()`);
+ });
+
+ test('it should handle disconnect jira integration', async function (assert) {
+ this.server.get('organizations/:orgId/integrate_jira', () => {
+ return {
+ type: 'jira',
+ host: 'http://test.com',
+ username: 'testuser',
+ };
+ });
+
+ this.server.delete('organizations/:orgId/integrate_jira', () => {
+ return {};
+ });
+ await render(hbs`
`);
+
+ assert.dom(`[data-test-jira-disconnect-confirm-label]`).doesNotExist();
+ await click(`[data-test-jira-disconnect-btn]`);
+ assert.dom(`[data-test-jira-disconnect-confirm-label]`).exists();
+ assert
+ .dom(`[data-test-jira-disconnect-confirm-label]`)
+ .hasText(`t:confirmBox.revokeJira:()`);
+ assert.dom(`[data-test-jira-disconnect-confirm-ok-btn]`).hasText(`t:ok:()`);
+ assert
+ .dom(`[data-test-jira-disconnect-confirm-cancel-btn]`)
+ .hasText(`t:cancel:()`);
+
+ await click(`[data-test-jira-disconnect-confirm-ok-btn]`);
+ this.notifyService = this.owner.lookup('service:notifications');
+ assert.equal(
+ this.notifyService.get('successMsg'),
+ `t:jiraWillBeRevoked:()`
+ );
+ assert.dom(`[data-test-jira-disconnect-confirm-label]`).doesNotExist();
+ });
+
+ test('it should close confirm modal while clicking at cancel btn', async function (assert) {
+ this.server.get('organizations/:orgId/integrate_jira', () => {
+ return {
+ type: 'jira',
+ host: 'http://test.com',
+ username: 'testuser',
+ };
+ });
+
+ await render(hbs`
`);
+
+ assert.dom(`[data-test-jira-disconnect-confirm-label]`).doesNotExist();
+ await click(`[data-test-jira-disconnect-btn]`);
+ assert.dom(`[data-test-jira-disconnect-confirm-label]`).exists();
+
+ await click(`[data-test-jira-disconnect-confirm-cancel-btn]`);
+
+ assert.dom(`[data-test-jira-disconnect-confirm-label]`).doesNotExist();
+ });
+
+ test('it should handle disconnect jira integration failed', async function (assert) {
+ this.server.get('organizations/:orgId/integrate_jira', () => {
+ return {
+ type: 'jira',
+ host: 'http://test.com',
+ username: 'testuser',
+ };
+ });
+
+ this.server.delete('organizations/:orgId/integrate_jira', () => {
+ return Response(500);
+ });
+ await render(hbs`
`);
+
+ await click(`[data-test-jira-disconnect-btn]`);
+
+ await click(`[data-test-jira-disconnect-confirm-ok-btn]`);
+ this.notifyService = this.owner.lookup('service:notifications');
+ assert.equal(
+ this.notifyService.get('errorMsg'),
+ 'Request was rejected due to server error'
+ );
+ assert.dom(`[data-test-jira-disconnect-confirm-label]`).doesNotExist();
+ });
+});
diff --git a/translations/en.json b/translations/en.json
index 448ab28a2..fbf57ff05 100644
--- a/translations/en.json
+++ b/translations/en.json
@@ -313,6 +313,7 @@
"idpMetadataUpload": "Upload your IdP Metadata XML file",
"impact": "Impact",
"improved": "Improved",
+ "inValidCredentials": "Invalid credentials",
"inactive": "inactive",
"inactiveCaptital": "Inactive",
"includeInactiveMembers": "Include inactive members",
@@ -356,10 +357,13 @@
"jaHTMLReport": "JA HTML Report",
"jenkinsPipeline": "Jenkins Pipeline",
"jira": "Jira",
+ "jiraCloudIntegration": "JIRA Cloud Integration",
+ "jiraErrorIntegration": "Intergration failed, please contact support",
"jiraHost": "Jira Host",
"jiraIntegrated": "JIRA integrated",
"jiraIntegration": "JIRA Integration",
"jiraNoProject": "Linked JIRA account doesn't have any projects",
+ "jiraOnPremiseIntegration": "JIRA On-Premise Integration",
"jiraPageConfigure": "page to configure JIRA integration",
"jiraWillBeRevoked": "Your JIRA authorization will be revoked in a moment",
"language": "Language",
@@ -812,7 +816,6 @@
"sync": "Sync More",
"system": "System",
"systemStatus": "System Status",
- "tInValidCredentials": "Invalid credentials",
"tablet": "Tablet",
"team": "Team",
"teamCreated": "Team Created Successfully",
diff --git a/translations/ja.json b/translations/ja.json
index 1854adf54..8f8d7ef67 100644
--- a/translations/ja.json
+++ b/translations/ja.json
@@ -313,6 +313,7 @@
"idpMetadataUpload": "Upload your IdP Metadata XML file",
"impact": "Impact",
"improved": "改善",
+ "inValidCredentials": "Invalid credentials",
"inactive": "inactive",
"inactiveCaptital": "Inactive",
"includeInactiveMembers": "Include inactive members",
@@ -356,10 +357,13 @@
"jaHTMLReport": "JA HTML Report",
"jenkinsPipeline": "Jenkins Pipeline",
"jira": "JIRA",
+ "jiraCloudIntegration": "JIRA Cloud Integration",
+ "jiraErrorIntegration": "Intergration failed, please contact support",
"jiraHost": "JIRAホスト",
"jiraIntegrated": "JIRAと連携されました",
"jiraIntegration": "JIRA連携",
"jiraNoProject": "Linked JIRA account doesn't have any projects",
+ "jiraOnPremiseIntegration": "JIRA On-Premise Integration",
"jiraPageConfigure": "JIRA連携設定ページ",
"jiraWillBeRevoked": "JIRA認証は直ちに取り消されます",
"language": "言語",
@@ -812,7 +816,6 @@
"sync": "同期する",
"system": "System",
"systemStatus": "System Status",
- "tInValidCredentials": "Invalid credentials",
"tablet": "タブレット",
"team": "チーム",
"teamCreated": "チームが作成されました",