router_test.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. var App = require('app');
  19. var testHelpers = require('test/helpers');
  20. require('router');
  21. describe('App.Router', function () {
  22. var router = App.Router.create();
  23. describe('#initAdmin()', function () {
  24. var cases = [
  25. {
  26. user: {
  27. admin: true
  28. },
  29. isAdmin: true,
  30. isOperator: false,
  31. isPermissionDataLoaded: true,
  32. title: 'admin'
  33. },
  34. {
  35. user: {
  36. operator: true
  37. },
  38. isAdmin: false,
  39. isOperator: true,
  40. isPermissionDataLoaded: true,
  41. title: 'operator'
  42. },
  43. {
  44. user: {},
  45. isAdmin: false,
  46. isOperator: false,
  47. isPermissionDataLoaded: true,
  48. title: 'read only access'
  49. },
  50. {
  51. user: null,
  52. isAdmin: false,
  53. isOperator: false,
  54. isPermissionDataLoaded: false,
  55. title: 'no user'
  56. }
  57. ];
  58. beforeEach(function () {
  59. this.getUser = sinon.stub(App.db, 'getUser');
  60. App.setProperties({
  61. isAdmin: false,
  62. isOperator: false,
  63. isPermissionDataLoaded: false
  64. });
  65. });
  66. afterEach(function () {
  67. this.getUser.restore();
  68. });
  69. cases.forEach(function (item) {
  70. it(item.title, function () {
  71. this.getUser.returns(item.user);
  72. router.initAdmin();
  73. expect(App.get('isAdmin')).to.equal(item.isAdmin);
  74. expect(App.get('isOperator')).to.equal(item.isOperator);
  75. expect(App.get('isPermissionDataLoaded')).to.equal(item.isPermissionDataLoaded);
  76. });
  77. });
  78. });
  79. describe('#adminViewInfoSuccessCallback', function() {
  80. beforeEach(function() {
  81. sinon.stub(window.location, 'replace', Em.K);
  82. });
  83. afterEach(function() {
  84. window.location.replace.restore();
  85. });
  86. var tests = [{
  87. mockData: {
  88. components: [{
  89. 'RootServiceComponents': {
  90. 'component_version': '1.9.0'
  91. }
  92. }, {
  93. 'RootServiceComponents': {
  94. 'component_version': '2.0.0'
  95. }
  96. }]
  97. },
  98. expected: '/views/ADMIN_VIEW/2.0.0/INSTANCE/#/'
  99. }, {
  100. mockData: {
  101. components: [{
  102. 'RootServiceComponents': {
  103. 'component_version': '1.9.0'
  104. }
  105. }, {
  106. 'RootServiceComponents': {
  107. 'component_version': '2.1.0'
  108. }
  109. }, {
  110. 'RootServiceComponents': {
  111. 'component_version': '2.0.0'
  112. }
  113. }]
  114. },
  115. expected: '/views/ADMIN_VIEW/2.1.0/INSTANCE/#/'
  116. }, {
  117. mockData: {
  118. components: [{
  119. 'RootServiceComponents': {
  120. component_version: '2.1.0'
  121. }
  122. }]
  123. },
  124. expected: '/views/ADMIN_VIEW/2.1.0/INSTANCE/#/'
  125. }];
  126. tests.forEach(function(data, index) {
  127. it('should redirect to the latest version of admin view ("' + data.expected + '") #' + (index + 1), function () {
  128. router.adminViewInfoSuccessCallback(data.mockData);
  129. expect(window.location.replace.calledWith(data.expected)).to.be.true;
  130. });
  131. });
  132. });
  133. describe.skip("#savePreferedPath()", function() {
  134. beforeEach(function () {
  135. router.set('preferedPath', null);
  136. });
  137. it("has no key", function() {
  138. router.savePreferedPath('path');
  139. expect(router.get('preferedPath')).to.equal('path');
  140. });
  141. it("path does not contain key", function() {
  142. router.savePreferedPath('path', 'key');
  143. expect(router.get('preferedPath')).to.be.null;
  144. });
  145. it("path contains key", function() {
  146. router.savePreferedPath('key=path', 'key=');
  147. expect(router.get('preferedPath')).to.equal('path');
  148. });
  149. });
  150. describe.skip("#restorePreferedPath()", function() {
  151. it("preferedPath is null", function() {
  152. router.set('preferedPath', null);
  153. expect(router.restorePreferedPath()).to.be.false;
  154. expect(router.get('preferedPath')).to.be.null;
  155. });
  156. it("preferedPath is '/relativeURL'", function() {
  157. router.set('preferedPath', '/relativeURL');
  158. expect(router.restorePreferedPath()).to.be.true;
  159. expect(router.get('preferedPath')).to.be.null;
  160. });
  161. it("preferedPath is '#/relativeURL'", function() {
  162. router.set('preferedPath', '#/relativeURL');
  163. expect(router.restorePreferedPath()).to.be.true;
  164. expect(router.get('preferedPath')).to.be.null;
  165. });
  166. it("preferedPath is '#/login'", function() {
  167. router.set('preferedPath', '#/login');
  168. expect(router.restorePreferedPath()).to.be.false;
  169. expect(router.get('preferedPath')).to.be.null;
  170. });
  171. it("preferedPath is 'http://absoluteURL'", function() {
  172. router.set('preferedPath', 'http://absoluteURL');
  173. expect(router.restorePreferedPath()).to.be.false;
  174. expect(router.get('preferedPath')).to.be.null;
  175. });
  176. });
  177. describe.skip("#loginGetClustersSuccessCallback()", function () {
  178. var mock = {dataLoading: Em.K};
  179. beforeEach(function () {
  180. sinon.stub(router, 'setClusterInstalled', Em.K);
  181. sinon.stub(router, 'transitionToApp', Em.K);
  182. sinon.stub(router, 'transitionToViews', Em.K);
  183. sinon.stub(router, 'transitionToAdminView', Em.K);
  184. sinon.stub(App.router, 'get').returns(mock);
  185. sinon.spy(mock, 'dataLoading');
  186. App.setProperties({
  187. isAdmin: false,
  188. isOperator: false,
  189. isPermissionDataLoaded: false
  190. });
  191. });
  192. afterEach(function () {
  193. router.setClusterInstalled.restore();
  194. router.transitionToApp.restore();
  195. router.transitionToViews.restore();
  196. router.transitionToAdminView.restore();
  197. App.router.get.restore();
  198. mock.dataLoading.restore();
  199. });
  200. it("cluster exists, OPERATOR privileges", function () {
  201. var clusterData = {
  202. items: [{
  203. Clusters: {
  204. cluster_name: 'c1'
  205. }
  206. }]
  207. };
  208. var params = {
  209. loginData: {
  210. privileges: [{
  211. PrivilegeInfo: {
  212. cluster_name: 'c1',
  213. permission_name: 'CLUSTER.ADMINISTRATOR'
  214. }
  215. }]
  216. }
  217. };
  218. router.loginGetClustersSuccessCallback(clusterData, {}, params);
  219. expect(router.setClusterInstalled.calledWith(clusterData)).to.be.true;
  220. expect(router.transitionToApp.calledOnce).to.be.true;
  221. expect(App.get('isAdmin')).to.be.true;
  222. expect(App.get('isOperator')).to.be.true;
  223. expect(App.get('isPermissionDataLoaded')).to.be.true;
  224. expect(mock.dataLoading.calledOnce).to.be.true;
  225. });
  226. it("cluster exists, READ privileges", function () {
  227. var clusterData = {
  228. items: [{
  229. Clusters: {
  230. cluster_name: 'c1'
  231. }
  232. }]
  233. };
  234. var params = {
  235. loginData: {
  236. privileges: [{
  237. PrivilegeInfo: {
  238. cluster_name: 'c1',
  239. permission_name: 'CLUSTER.USER'
  240. }
  241. }]
  242. }
  243. };
  244. router.loginGetClustersSuccessCallback(clusterData, {}, params);
  245. expect(router.setClusterInstalled.calledWith(clusterData)).to.be.true;
  246. expect(router.transitionToApp.calledOnce).to.be.true;
  247. expect(App.get('isAdmin')).to.be.false;
  248. expect(App.get('isOperator')).to.be.false;
  249. expect(App.get('isPermissionDataLoaded')).to.be.true;
  250. expect(mock.dataLoading.calledOnce).to.be.true;
  251. });
  252. it("cluster exists, ADMIN privileges", function () {
  253. var clusterData = {
  254. items: [{
  255. Clusters: {
  256. cluster_name: 'c1'
  257. }
  258. }]
  259. };
  260. var params = {
  261. loginData: {
  262. privileges: [{
  263. PrivilegeInfo: {
  264. cluster_name: 'c1',
  265. permission_name: 'AMBARI.ADMINISTRATOR'
  266. }
  267. }]
  268. }
  269. };
  270. router.loginGetClustersSuccessCallback(clusterData, {}, params);
  271. expect(router.setClusterInstalled.calledWith(clusterData)).to.be.true;
  272. expect(router.transitionToApp.calledOnce).to.be.true;
  273. expect(App.get('isAdmin')).to.be.true;
  274. expect(App.get('isOperator')).to.be.false;
  275. expect(App.get('isPermissionDataLoaded')).to.be.true;
  276. expect(mock.dataLoading.calledOnce).to.be.true;
  277. });
  278. it("cluster exists, no privileges", function () {
  279. var clusterData = {
  280. items: [{
  281. Clusters: {
  282. cluster_name: 'c1'
  283. }
  284. }]
  285. };
  286. var params = {
  287. loginData: {
  288. privileges: []
  289. }
  290. };
  291. router.loginGetClustersSuccessCallback(clusterData, {}, params);
  292. expect(router.setClusterInstalled.calledWith(clusterData)).to.be.true;
  293. expect(router.transitionToViews.calledOnce).to.be.true;
  294. expect(App.get('isAdmin')).to.be.false;
  295. expect(App.get('isOperator')).to.be.false;
  296. expect(App.get('isPermissionDataLoaded')).to.be.true;
  297. expect(mock.dataLoading.calledOnce).to.be.true;
  298. });
  299. it("cluster not installed, ADMIN privileges", function () {
  300. var clusterData = {
  301. items: []
  302. };
  303. var params = {
  304. loginData: {
  305. privileges: [{
  306. PrivilegeInfo: {
  307. cluster_name: 'c1',
  308. permission_name: 'AMBARI.ADMINISTRATOR'
  309. }
  310. }]
  311. }
  312. };
  313. router.loginGetClustersSuccessCallback(clusterData, {}, params);
  314. expect(router.transitionToAdminView.calledOnce).to.be.true;
  315. expect(App.get('isAdmin')).to.be.true;
  316. expect(App.get('isOperator')).to.be.false;
  317. expect(App.get('isPermissionDataLoaded')).to.be.true;
  318. expect(mock.dataLoading.calledOnce).to.be.true;
  319. });
  320. it("cluster not installed, non-admin privileges", function () {
  321. var clusterData = {
  322. items: []
  323. };
  324. var params = {
  325. loginData: {
  326. privileges: []
  327. }
  328. };
  329. router.loginGetClustersSuccessCallback(clusterData, {}, params);
  330. expect(router.transitionToViews.calledOnce).to.be.true;
  331. expect(App.get('isAdmin')).to.be.false;
  332. expect(App.get('isOperator')).to.be.false;
  333. expect(App.get('isPermissionDataLoaded')).to.be.true;
  334. expect(mock.dataLoading.calledOnce).to.be.true;
  335. });
  336. });
  337. describe("#transitionToAdminView()", function () {
  338. it("valid request is sent", function () {
  339. router.transitionToAdminView();
  340. var args = testHelpers.findAjaxRequest('name', 'ambari.service.load_server_version');
  341. expect(args[0]).to.exists;
  342. });
  343. });
  344. describe("#transitionToApp()", function () {
  345. beforeEach(function () {
  346. this.mock = sinon.stub(router, 'restorePreferedPath');
  347. sinon.stub(router, 'getSection', function (callback) {
  348. callback('route');
  349. });
  350. sinon.stub(router, 'transitionTo');
  351. });
  352. afterEach(function () {
  353. this.mock.restore();
  354. router.getSection.restore();
  355. router.transitionTo.restore();
  356. });
  357. it("has restore path", function () {
  358. this.mock.returns(true);
  359. router.transitionToApp();
  360. expect(router.getSection.called).to.be.false;
  361. expect(router.transitionTo.called).to.be.false;
  362. });
  363. it("does not have restore path", function () {
  364. this.mock.returns(false);
  365. router.transitionToApp();
  366. expect(router.getSection.calledOnce).to.be.true;
  367. expect(router.transitionTo.calledWith('route')).to.be.true;
  368. });
  369. });
  370. describe("#transitionToViews()", function () {
  371. var mock = {loadAmbariViews: Em.K};
  372. beforeEach(function () {
  373. sinon.stub(App.router, 'get').returns(mock);
  374. sinon.stub(router, 'transitionTo');
  375. sinon.spy(mock, 'loadAmbariViews');
  376. });
  377. afterEach(function () {
  378. App.router.get.restore();
  379. router.transitionTo.restore();
  380. mock.loadAmbariViews.restore();
  381. });
  382. it("transitionTo called with corrent route", function () {
  383. router.transitionToViews();
  384. expect(mock.loadAmbariViews.calledOnce).to.be.true;
  385. expect(router.transitionTo.calledWith('main.views.index')).to.be.true;
  386. });
  387. });
  388. describe("#adminViewInfoErrorCallback()", function () {
  389. beforeEach(function () {
  390. sinon.stub(router, 'transitionToViews');
  391. });
  392. afterEach(function () {
  393. router.transitionToViews.restore();
  394. });
  395. it("transitionToViews called once", function () {
  396. router.adminViewInfoErrorCallback();
  397. expect(router.transitionToViews.calledOnce).to.be.true;
  398. });
  399. });
  400. describe("#getAuthenticated", function() {
  401. beforeEach(function () {
  402. router = App.Router.create();
  403. this.mockGetCurrentLocationUrl = sinon.stub(router, 'getCurrentLocationUrl');
  404. sinon.stub(router, 'redirectByURL', Em.K);
  405. });
  406. afterEach(function () {
  407. router.getCurrentLocationUrl.restore();
  408. router.redirectByURL.restore();
  409. this.mockGetCurrentLocationUrl.restore();
  410. });
  411. [
  412. {
  413. lastSetURL: '/login/local',
  414. isResolved: false,
  415. responseData: {
  416. responseText: "",
  417. status: 403
  418. },
  419. redirectCalled: false,
  420. m: 'no jwtProviderUrl in auth response, no redirect'
  421. },
  422. {
  423. lastSetURL: '/main/dashboard',
  424. isResolved: false,
  425. responseData: {
  426. responseText: JSON.stringify({ jwtProviderUrl: 'http://some.com?originalUrl=' }),
  427. status: 403
  428. },
  429. redirectCalled: true,
  430. m: 'jwtProviderUrl is present, current location not local login url, redirect according to jwtProviderUrl value'
  431. },
  432. {
  433. lastSetURL: '/login/local',
  434. isResolved: false,
  435. responseData: {
  436. responseText: JSON.stringify({ jwtProviderUrl: 'http://some.com?originalUrl=' }),
  437. status: 403
  438. },
  439. redirectCalled: false,
  440. m: 'jwtProviderUrl is present, current location is local login url, no redirect'
  441. }
  442. ].forEach(function(test) {
  443. describe(test.m, function() {
  444. var mockCurrentUrl;
  445. beforeEach(function () {
  446. mockCurrentUrl = 'http://localhost:3333/#/some/hash';
  447. router.set('location.lastSetURL', test.lastSetURL);
  448. App.ajax.send.restore(); // default ajax-mock can't be used here
  449. sinon.stub(App.ajax, 'send', function() {
  450. if (!test.isResolved) {
  451. router.onAuthenticationError(test.responseData);
  452. }
  453. return {
  454. complete: function() {}
  455. };
  456. });
  457. this.mockGetCurrentLocationUrl.returns(mockCurrentUrl);
  458. router.getAuthenticated();
  459. });
  460. it('redirectByURL is ' + (test.redirectCalled ? '' : 'not') + ' called', function () {
  461. expect(router.redirectByURL.calledOnce).to.be.eql(test.redirectCalled);
  462. });
  463. if (test.redirectCalled) {
  464. it('redirectByURL is correct', function () {
  465. expect(router.redirectByURL.args[0][0]).to.be.eql(JSON.parse(test.responseData.responseText).jwtProviderUrl + encodeURIComponent(mockCurrentUrl));
  466. });
  467. }
  468. });
  469. });
  470. });
  471. });