mongo_browser 0.1.3 → 0.2.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/.gitignore +3 -0
  2. data/.travis.yml +3 -3
  3. data/README.md +1 -25
  4. data/Rakefile +0 -1
  5. data/app/assets/images/background.png +0 -0
  6. data/app/assets/javascripts/app/controllers/alerts.js.coffee +12 -0
  7. data/app/assets/javascripts/app/controllers/breadcrumbs.js.coffee +25 -0
  8. data/app/assets/javascripts/app/controllers/collections.js.coffee +40 -0
  9. data/app/assets/javascripts/app/controllers/databases.js.coffee +39 -0
  10. data/app/assets/javascripts/app/controllers/documents.js.coffee +49 -0
  11. data/app/assets/javascripts/app/controllers/main.js.coffee +10 -0
  12. data/app/assets/javascripts/app/controllers/server_info.js.coffee +14 -0
  13. data/app/assets/javascripts/app/controllers.js.coffee +2 -0
  14. data/app/assets/javascripts/app/directives.js.coffee +20 -0
  15. data/app/assets/javascripts/app/filters.js.coffee +48 -0
  16. data/app/assets/javascripts/app/modules/dialogs.js.coffee +29 -0
  17. data/app/assets/javascripts/app/modules/pager.js.coffee +87 -0
  18. data/app/assets/javascripts/app/modules/table_filter.js.coffee +27 -0
  19. data/app/assets/javascripts/app/resources.js.coffee +22 -0
  20. data/app/assets/javascripts/app/services.js.coffee +36 -0
  21. data/app/assets/javascripts/app.js.coffee +8 -0
  22. data/app/assets/javascripts/application.js.coffee +35 -6
  23. data/app/assets/javascripts/templates/.gitkeep +0 -0
  24. data/app/assets/javascripts/templates.js.coffee +1 -0
  25. data/app/assets/javascripts/vendor.js.coffee +5 -0
  26. data/app/assets/stylesheets/application.css.scss +46 -3
  27. data/app/assets/templates/collections.html +53 -0
  28. data/app/assets/templates/databases.html +32 -0
  29. data/app/assets/templates/documents.html +45 -0
  30. data/app/assets/templates/pager.html +13 -0
  31. data/app/{views/server_info.erb → assets/templates/server_info.html} +5 -7
  32. data/app/assets/templates/table_filter.html +10 -0
  33. data/bin/mongo_browser +8 -45
  34. data/config-e2e.ru +20 -0
  35. data/grunt.js +36 -0
  36. data/lib/mongo_browser/application.rb +143 -64
  37. data/lib/mongo_browser/middleware/sprockets_base.rb +11 -0
  38. data/lib/mongo_browser/middleware/sprockets_sinatra.rb +3 -7
  39. data/lib/mongo_browser/middleware/sprockets_specs.rb +18 -0
  40. data/lib/mongo_browser/models/collection.rb +67 -0
  41. data/lib/mongo_browser/models/database.rb +52 -0
  42. data/lib/mongo_browser/models/document.rb +17 -0
  43. data/lib/mongo_browser/models/pager.rb +30 -0
  44. data/lib/mongo_browser/models/server.rb +51 -0
  45. data/lib/mongo_browser/version.rb +1 -1
  46. data/lib/mongo_browser.rb +10 -5
  47. data/mongo_browser.gemspec +4 -11
  48. data/public/index.html +47 -0
  49. data/script/ci_all +21 -0
  50. data/script/ci_e2e +11 -0
  51. data/script/ci_javascripts +4 -0
  52. data/script/ci_rspec +3 -0
  53. data/spec/features/collections_list_spec.rb +6 -49
  54. data/spec/features/documents_list_spec.rb +15 -14
  55. data/spec/features/server_info_spec.rb +3 -3
  56. data/spec/javascripts/app/controllers/alerts_spec.js.coffee +36 -0
  57. data/spec/javascripts/app/controllers/breadcrumbs_spec.js.coffee +28 -0
  58. data/spec/javascripts/app/controllers/collections_spec.js.coffee +78 -0
  59. data/spec/javascripts/app/controllers/databases_spec.js.coffee +55 -0
  60. data/spec/javascripts/app/controllers/documents_spec.js.coffee +62 -0
  61. data/spec/javascripts/app/controllers/main_spec.js.coffee +20 -0
  62. data/spec/javascripts/app/controllers/server_info_spec.js.coffee +21 -0
  63. data/spec/javascripts/app/directives_spec.js.coffee +58 -0
  64. data/spec/javascripts/app/filters_spec.js.coffee +99 -0
  65. data/spec/javascripts/app/modules/dialogs_spec.js.coffee +51 -0
  66. data/spec/javascripts/app/modules/pager_spec.js.coffee +104 -0
  67. data/spec/javascripts/app/modules/table_filter_spec.js.coffee +76 -0
  68. data/spec/javascripts/app/services_spec.js.coffee +83 -0
  69. data/spec/javascripts/config/testacular-e2e.conf.js +19 -0
  70. data/spec/javascripts/config/testacular.conf.js +43 -0
  71. data/spec/javascripts/e2e/collections_scenario.js.coffee +49 -0
  72. data/spec/javascripts/e2e/databases_scenario.js.coffee +74 -0
  73. data/spec/javascripts/e2e/documents_scenario.js.coffee +18 -0
  74. data/spec/javascripts/e2e/server_info_scenario.js.coffee +12 -0
  75. data/spec/javascripts/helpers/matchers.js.coffee +5 -0
  76. data/spec/javascripts/helpers/mocks.js.coffee +7 -0
  77. data/spec/javascripts/helpers_e2e/app_element.js.coffee +6 -0
  78. data/spec/javascripts/lib/angular-mocks.js +1740 -0
  79. data/spec/javascripts/lib/angular-scenario.js +26147 -0
  80. data/spec/javascripts/lib/jasmine-html.js +681 -0
  81. data/spec/javascripts/lib/jasmine.css +82 -0
  82. data/spec/javascripts/lib/jasmine.js +2600 -0
  83. data/spec/javascripts/runner.html +54 -0
  84. data/spec/javascripts/runner_e2e.html +10 -0
  85. data/spec/javascripts/spec.js.coffee +2 -0
  86. data/spec/javascripts/spec_e2e.js.coffee +2 -0
  87. data/spec/lib/models/collection_spec.rb +80 -0
  88. data/spec/lib/models/database_spec.rb +75 -0
  89. data/spec/lib/models/document_spec.rb +17 -0
  90. data/spec/lib/models/pager_spec.rb +64 -0
  91. data/spec/lib/models/server_spec.rb +76 -0
  92. data/spec/lib/mongo_browser_spec.rb +1 -1
  93. data/spec/spec_helper.rb +2 -19
  94. data/spec/support/feature_example_group.rb +8 -3
  95. data/spec/support/fixtures/databases.json +8 -0
  96. data/spec/support/fixtures.rb +20 -3
  97. data/spec/support/matchers/have_flash_message.rb +1 -1
  98. data/spec/support/mongod.rb +37 -21
  99. data/spec/support/mongodb.conf +47 -0
  100. data/vendor/assets/javascripts/angular/angular-bootstrap.js +166 -0
  101. data/vendor/assets/javascripts/angular/angular-resource.js +435 -0
  102. data/vendor/assets/javascripts/angular/angular-sanitize.js +535 -0
  103. data/vendor/assets/javascripts/angular/angular.js +14531 -0
  104. data/vendor/assets/javascripts/underscore.js +1200 -0
  105. metadata +136 -148
  106. data/app/assets/javascripts/app/table_filter.js.coffee +0 -50
  107. data/app/assets/javascripts/ujs.js.coffee +0 -23
  108. data/app/views/collections/index.erb +0 -59
  109. data/app/views/databases/index.erb +0 -29
  110. data/app/views/documents/index.erb +0 -61
  111. data/app/views/layout/_flash_messages.erb +0 -10
  112. data/app/views/layout/_navbar.erb +0 -22
  113. data/app/views/layout.erb +0 -20
  114. data/app/views/shared/_filter.erb +0 -14
  115. data/features/mongo_browser.feature +0 -18
  116. data/features/step_definitions/mongo_browser_steps.rb +0 -1
  117. data/features/support/env.rb +0 -18
  118. data/spec/features/databases_list_spec.rb +0 -65
@@ -0,0 +1,78 @@
1
+ describe "collections", ->
2
+ beforeEach module("mb.controllers")
3
+ beforeEach module("mb.dialogs")
4
+ beforeEach module("mocks")
5
+
6
+ $scope = null
7
+ $httpBackend = null
8
+ alerts = null
9
+
10
+ beforeEach inject ($injector, $rootScope, $controller) ->
11
+ alerts = $injector.get("alerts")
12
+
13
+ $routeParams = $injector.get("$routeParams")
14
+ $routeParams.dbName = "test_database"
15
+
16
+ $httpBackend = $injector.get("$httpBackend")
17
+ $httpBackend.when("GET", "/api/databases/test_database/collections.json")
18
+ .respond([])
19
+ $httpBackend.when("GET", "/api/databases/test_database/stats.json")
20
+ .respond({})
21
+
22
+ $scope = $rootScope.$new()
23
+ $controller "collections",
24
+ $scope: $scope
25
+
26
+ $httpBackend.flush()
27
+
28
+ afterEach ->
29
+ $httpBackend.verifyNoOutstandingExpectation()
30
+ $httpBackend.verifyNoOutstandingRequest()
31
+
32
+ describe "#isLoading", ->
33
+ it "returns true when the resouce it loading", ->
34
+ $scope.loading = true
35
+ expect($scope.isLoading()).toBeTruthy()
36
+
37
+ it "otherwise returns false", ->
38
+ $scope.loading = false
39
+ expect($scope.isLoading()).toBeFalsy()
40
+
41
+ # TODO refactor this spec
42
+ describe "#delete", ->
43
+ collection = null
44
+
45
+ beforeEach ->
46
+ collection = dbName: "test_database", name: "dummy-collection-id"
47
+
48
+ it "shows a confirmation dialog", inject (dialogsHandler) ->
49
+ spyOn(dialogsHandler, "confirm")
50
+
51
+
52
+ $scope.delete(collection)
53
+
54
+ expect(dialogsHandler.confirm).toHaveBeenCalledWith \
55
+ "Deleting dummy-collection-id. Are you sure?",
56
+ jasmine.any(Function)
57
+
58
+ describe "when the dialog was confirmed", ->
59
+ beforeEach inject (dialogsHandler) ->
60
+ $httpBackend.when("DELETE", "/api/databases/test_database/collections.json?id=dummy-collection-id")
61
+ .respond([])
62
+
63
+ spyOn(alerts, "info")
64
+ $scope.delete(collection)
65
+ dialogsHandler.confirmed()
66
+
67
+ it "sends a delete request", ->
68
+ $httpBackend.flush()
69
+
70
+ it "displays a flash message", ->
71
+ $httpBackend.flush()
72
+ expect(alerts.info).toHaveBeenCalledWith("Collection dummy-collection-id has been deleted.")
73
+
74
+ describe "when the dialog was disposed", ->
75
+ it "does nothing", inject (dialogsHandler) ->
76
+ # When
77
+ $scope.delete(name: "dummy-collection-id")
78
+ dialogsHandler.disposed()
@@ -0,0 +1,55 @@
1
+ describe "databases", ->
2
+ beforeEach module("mb.controllers")
3
+ beforeEach module("mb.dialogs")
4
+ beforeEach module("mocks")
5
+
6
+ $scope = null
7
+ $httpBackend = null
8
+ alerts = null
9
+
10
+ beforeEach inject ($injector, $rootScope, $controller) ->
11
+ alerts = $injector.get("alerts")
12
+
13
+ $httpBackend = $injector.get("$httpBackend")
14
+ $httpBackend.when("GET", "/api/databases.json").respond([])
15
+
16
+ $scope = $rootScope.$new()
17
+ $controller "databases",
18
+ $scope: $scope
19
+
20
+ $httpBackend.flush()
21
+
22
+ afterEach ->
23
+ $httpBackend.verifyNoOutstandingExpectation()
24
+ $httpBackend.verifyNoOutstandingRequest()
25
+
26
+ # TODO rewrite this spec
27
+ describe "#delete", ->
28
+ it "shows a confirmation dialog", inject (dialogsHandler) ->
29
+ spyOn(dialogsHandler, "confirm")
30
+ $scope.delete(name: "test_database_name")
31
+ expect(dialogsHandler.confirm).toHaveBeenCalledWith \
32
+ "Deleting test_database_name. Are you sure?",
33
+ jasmine.any(Function)
34
+
35
+ describe "when the dialog was confirmed", ->
36
+ beforeEach inject (dialogsHandler) ->
37
+ $httpBackend.when("DELETE", "/api/databases.json?id=test_database_name")
38
+ .respond([])
39
+
40
+ spyOn(alerts, "info")
41
+ $scope.delete(name: "test_database_name")
42
+ dialogsHandler.confirmed()
43
+
44
+ it "sends a delete request", ->
45
+ $httpBackend.flush()
46
+
47
+ it "displays a flash message", ->
48
+ $httpBackend.flush()
49
+ expect(alerts.info).toHaveBeenCalledWith("Database test_database_name has been deleted.")
50
+
51
+ describe "when the dialog was disposed", ->
52
+ it "does nothing", inject (dialogsHandler) ->
53
+ # When
54
+ $scope.delete(name: "test_database_name")
55
+ dialogsHandler.disposed()
@@ -0,0 +1,62 @@
1
+ describe "documents", ->
2
+ beforeEach module("mb.controllers")
3
+ beforeEach module("mb.dialogs")
4
+ beforeEach module("mocks")
5
+
6
+ $scope = null
7
+ $httpBackend = null
8
+ alerts = null
9
+
10
+ beforeEach inject ($injector, $rootScope, $controller) ->
11
+ alerts = $injector.get("alerts")
12
+
13
+ $routeParams = $injector.get("$routeParams")
14
+ $routeParams.dbName = "test_database"
15
+ $routeParams.collectionName = "test_collection"
16
+
17
+ $httpBackend = $injector.get('$httpBackend')
18
+ $httpBackend.when("GET", "/api/databases/test_database/collections/test_collection/documents.json?page=1")
19
+ .respond([])
20
+ $httpBackend.when("GET", "/api/databases/test_database/collections/test_collection/stats.json")
21
+ .respond({})
22
+
23
+ $scope = $rootScope.$new()
24
+ $controller "documents",
25
+ $scope: $scope
26
+
27
+ $httpBackend.flush()
28
+
29
+ afterEach ->
30
+ $httpBackend.verifyNoOutstandingExpectation()
31
+ $httpBackend.verifyNoOutstandingRequest()
32
+
33
+ # TODO rewrite this spec
34
+ describe "#delete", ->
35
+ it "shows a confirmation dialog", inject (dialogsHandler) ->
36
+ spyOn(dialogsHandler, "confirm")
37
+ $scope.delete(id: "dummy-document-id")
38
+ expect(dialogsHandler.confirm).toHaveBeenCalledWith \
39
+ "Are you sure?",
40
+ jasmine.any(Function)
41
+
42
+ describe "when the dialog was confirmed", ->
43
+ beforeEach inject (dialogsHandler) ->
44
+ $httpBackend.when("DELETE", "/api/databases/test_database/collections/test_collection/documents.json?id=dummy-document-id")
45
+ .respond([])
46
+
47
+ spyOn(alerts, "info")
48
+ $scope.delete(id: "dummy-document-id")
49
+ dialogsHandler.confirmed()
50
+
51
+ it "sends a delete request", ->
52
+ $httpBackend.flush()
53
+
54
+ it "displays a flash message", ->
55
+ $httpBackend.flush()
56
+ expect(alerts.info).toHaveBeenCalledWith("Document dummy-document-id has been deleted.")
57
+
58
+ describe "when the dialog was disposed", ->
59
+ it "does nothing", inject (dialogsHandler) ->
60
+ # When
61
+ $scope.delete(id: "dummy-document-id")
62
+ dialogsHandler.disposed()
@@ -0,0 +1,20 @@
1
+ describe "main", ->
2
+ beforeEach module("mb.controllers")
3
+
4
+ $scope = null
5
+ $httpBackend = null
6
+
7
+ beforeEach inject ($injector, $rootScope, $controller) ->
8
+ $scope = $rootScope.$new()
9
+
10
+ $httpBackend = $injector.get('$httpBackend')
11
+ $httpBackend.when("GET", "/api/version.json").respond([])
12
+
13
+ $controller "main",
14
+ $scope: $scope
15
+
16
+ $httpBackend.flush()
17
+
18
+ it "fetches the app version", ->
19
+ $httpBackend.verifyNoOutstandingExpectation()
20
+ $httpBackend.verifyNoOutstandingRequest()
@@ -0,0 +1,21 @@
1
+ describe "serverInfo", ->
2
+ beforeEach module("mb.controllers")
3
+ beforeEach module("mocks")
4
+
5
+ $scope = null
6
+ $httpBackend = null
7
+
8
+ beforeEach inject ($injector, $rootScope, $controller) ->
9
+ $scope = $rootScope.$new()
10
+
11
+ $httpBackend = $injector.get('$httpBackend')
12
+ $httpBackend.when("GET", "/api/server_info.json").respond([])
13
+
14
+ $controller "serverInfo",
15
+ $scope: $scope
16
+
17
+ $httpBackend.flush()
18
+
19
+ it "fetches information about the server", ->
20
+ $httpBackend.verifyNoOutstandingExpectation()
21
+ $httpBackend.verifyNoOutstandingRequest()
@@ -0,0 +1,58 @@
1
+ describe "directives", ->
2
+ beforeEach module("mb.directives")
3
+
4
+ $scope = null
5
+ element = null
6
+
7
+ describe "osEsc", ->
8
+ beforeEach inject ($compile, $rootScope) ->
9
+ $scope = $rootScope.$new()
10
+ $scope.bar = ->
11
+
12
+ element = $compile('<input type="text" on-esc="bar()" />')($scope)
13
+ $scope.$digest()
14
+
15
+ it "calls the given function when the ESC was pressed", ->
16
+ spyOn($scope, 'bar')
17
+
18
+ event = jQuery.Event("keyup", keyCode: 27)
19
+ element.trigger(event)
20
+
21
+ expect($scope.bar).toHaveBeenCalled()
22
+
23
+ it "does nothing on other keys", ->
24
+ spyOn($scope, 'bar')
25
+
26
+ event = jQuery.Event("keyup", keyCode: 13)
27
+ element.trigger(event)
28
+
29
+ expect($scope.bar).not.toHaveBeenCalled()
30
+
31
+ describe "deleteButton", ->
32
+ beforeEach inject ($compile, $rootScope) ->
33
+ $scope = $rootScope.$new()
34
+ $scope.bar = ->
35
+
36
+ template = """
37
+ <div>
38
+ <delete-button ng-click="bar()" />
39
+ </div>
40
+ """
41
+ element = $compile(template)($scope)
42
+ $scope.$digest()
43
+
44
+ it "renders bar button", ->
45
+ button = element.find("a")
46
+
47
+ expect(button.length).toBe(1)
48
+ expect(button.hasClass("btn")).toBeTruthy()
49
+ expect(button.hasClass("btn-danger")).toBeTruthy()
50
+ expect(button.text()).toContain("Delete")
51
+
52
+ it "ng-click", ->
53
+ spyOn($scope, 'bar')
54
+
55
+ button = element.find("button")
56
+ button.click()
57
+
58
+ expect($scope.bar).not.toHaveBeenCalled()
@@ -0,0 +1,99 @@
1
+ describe "filters", ->
2
+ beforeEach module("mb.filters")
3
+
4
+ describe "humanSize", ->
5
+ filter = null
6
+
7
+ beforeEach inject (humanSizeFilter) ->
8
+ filter = humanSizeFilter
9
+
10
+ it "formats bytes", ->
11
+ expect(filter(1)).toEqual("1 Bytes")
12
+ expect(filter(1000)).toEqual("1000 Bytes")
13
+ expect(filter(1023)).toEqual("1023 Bytes")
14
+
15
+ it "formats kilobytes", ->
16
+ expect(filter(1024)).toEqual("1 KB")
17
+
18
+ it "formats megabytes", ->
19
+ megabyte = 1024 * 1024
20
+
21
+ expect(filter(megabyte)).toEqual("1 MB")
22
+ expect(filter(250 * megabyte)).toEqual("250 MB")
23
+
24
+ it "formats gigabytes", ->
25
+ gigabyte = 1024 * 1024 * 1024
26
+
27
+ expect(filter(gigabyte)).toEqual("1 GB")
28
+ expect(filter(2.6 * gigabyte)).toEqual("3 GB")
29
+
30
+ describe "jsonDocument", ->
31
+ filter = null
32
+
33
+ beforeEach inject (jsonDocumentFilter) ->
34
+ filter = jsonDocumentFilter
35
+
36
+ it "can highlight strings", ->
37
+ o = { foo: "bar" }
38
+
39
+ expect(filter(o)).toContain('<span class="key">foo:</span>')
40
+ expect(filter(o)).toContain('<span class="string">"bar"</span>')
41
+
42
+ it "can highlight numbers", ->
43
+ o = { bar: 123.99 }
44
+
45
+ expect(filter(o)).toContain('<span class="key">bar:</span>')
46
+ expect(filter(o)).toContain('<span class="number">123.99</span>')
47
+
48
+ it "can highlight booleans", ->
49
+ o = { foo: false }
50
+
51
+ expect(filter(o)).toContain('<span class="key">foo:</span>')
52
+ expect(filter(o)).toContain('<span class="boolean">false</span>')
53
+
54
+ it "can highlight nulls", ->
55
+ o = { foo: null }
56
+
57
+ expect(filter(o)).toContain('<span class="key">foo:</span>')
58
+ expect(filter(o)).toContain('<span class="null">null</span>')
59
+
60
+ it "can format ObjectId", ->
61
+ o = {
62
+ _id: { $oid: "50bfc4b6dac5d5630800017a" },
63
+ foo: "something",
64
+ comapany_id: { $oid: "50bfc4b6dac5d56308000119" }
65
+ }
66
+
67
+ expect(filter(o)).toContain('<span class="key">_id:</span>')
68
+ expect(filter(o)).toContain('ObjectId(<span class="string">"50bfc4b6dac5d5630800017a"</span>)')
69
+
70
+ expect(filter(o)).toContain('<span class="key">comapany_id:</span>')
71
+ expect(filter(o)).toContain('ObjectId(<span class="string">"50bfc4b6dac5d56308000119"</span>)')
72
+
73
+ # url helpers
74
+
75
+ describe "#collectionsPath", ->
76
+ filter = null
77
+
78
+ beforeEach inject (collectionsPathFilter) ->
79
+ filter = collectionsPathFilter
80
+
81
+ it "without parameters generates an url with placeholders", ->
82
+ expect(filter()).toEqual("/databases/:dbName/collections")
83
+
84
+ it "generates an url for the given database collections", ->
85
+ database = { name: "foo_bar" }
86
+ expect(filter(database)).toEqual("/databases/foo_bar/collections")
87
+
88
+ describe "#documentsPath", ->
89
+ filter = null
90
+
91
+ beforeEach inject (documentsPathFilter) ->
92
+ filter = documentsPathFilter
93
+
94
+ it "without parameters generates an url with placeholders", ->
95
+ expect(filter()).toEqual("/databases/:dbName/collections/:collectionName/documents")
96
+
97
+ it "generates na url for the given collection documents", ->
98
+ collection = { dbName: "foo", name: "bars" }
99
+ expect(filter(collection)).toEqual("/databases/foo/collections/bars/documents")
@@ -0,0 +1,51 @@
1
+ describe "mb.dialogs", ->
2
+ beforeEach module("mb.dialogs")
3
+
4
+ describe "dialogsHandler", ->
5
+ beforeEach inject ($window) ->
6
+ $window.bootbox = "dummy bootbox"
7
+
8
+ it "by default is set to bootbox", inject (dialogsHandler) ->
9
+ expect(dialogsHandler).toEqual("dummy bootbox")
10
+
11
+ describe "confirmationDialog", ->
12
+ beforeEach module("mocks")
13
+
14
+ it "is defined", inject (confirmationDialog) ->
15
+ expect(confirmationDialog).toBeDefined()
16
+
17
+ it "calls the handler", inject (confirmationDialog, dialogsHandler) ->
18
+ # Given
19
+ spyOn(dialogsHandler, "confirm")
20
+
21
+ # When
22
+ confirmationDialog(message: "This is a test message")
23
+
24
+ # Then
25
+ expect(dialogsHandler.confirm).toHaveBeenCalledWith \
26
+ "This is a test message",
27
+ jasmine.any(Function)
28
+
29
+ describe "when the dialog was confirmed", ->
30
+ it "calls the given #onOk callback", inject (confirmationDialog, dialogsHandler) ->
31
+ # Given
32
+ onOk = jasmine.createSpy("#onOk callback")
33
+ confirmationDialog(onOk: onOk)
34
+
35
+ # When
36
+ dialogsHandler.confirmed()
37
+
38
+ # Then
39
+ expect(onOk).toHaveBeenCalled()
40
+
41
+ describe "when the dialog was disposed", ->
42
+ it "calls the given #onOk callback", inject (confirmationDialog, dialogsHandler) ->
43
+ # Given
44
+ onCancel= jasmine.createSpy("#onCancel callback")
45
+ confirmationDialog(onCancel: onCancel)
46
+
47
+ # When
48
+ dialogsHandler.disposed()
49
+
50
+ # Then
51
+ expect(onCancel).toHaveBeenCalled()
@@ -0,0 +1,104 @@
1
+ describe "mb.pager", ->
2
+ beforeEach module("mb.pager")
3
+
4
+ describe "pager service", ->
5
+ it "is defined", inject (pager) ->
6
+ expect(pager).toBeDefined()
7
+
8
+ it "can be instantiated", inject (pager) ->
9
+ p = pager(totalPages: 99, outerWindow: 0)
10
+
11
+ expect(p.page).toEqual(1)
12
+ expect(p.totalPages).toEqual(99)
13
+ expect(p.innerWindow).toEqual(4)
14
+ expect(p.outerWindow).toEqual(0)
15
+
16
+ describe "windowedPageNumbers", ->
17
+
18
+ it "calculates windowed visible links", inject (pager) ->
19
+ prepare = pager(page: 6, totalPages: 11, innerWindow: 1, outerWindow: 1)
20
+ expect(prepare.windowedPageNumbers()).toEqual [1, 2, null, 5, 6, 7, null, 10, 11]
21
+
22
+ it "eliminates small gaps", inject (pager) ->
23
+ prepare = pager(page: 6, totalPages: 11, innerWindow: 2, outerWindow: 1)
24
+ # pages 4 and 8 appear instead of the gap
25
+ expect(prepare.windowedPageNumbers()).toEqual [1..11]
26
+
27
+ it "supports having no windows at all", inject (pager) ->
28
+ prepare = pager(page: 4, totalPages: 7, innerWindow: 0, outerWindow: 0)
29
+ expect(prepare.windowedPageNumbers()).toEqual [1, null, 4, null, 7]
30
+
31
+ it "adjusts upper limit if lower is out of bounds", inject (pager) ->
32
+ prepare = pager(page: 1, totalPages: 10, innerWindow: 2, outerWindow: 1)
33
+ expect(prepare.windowedPageNumbers()).toEqual [1, 2, 3, 4, 5, null, 9, 10]
34
+
35
+ it "adjusts lower limit if upper is out of bounds", inject (pager) ->
36
+ prepare = pager(page: 10, totalPages: 10, innerWindow: 2, outerWindow: 1)
37
+ expect(prepare.windowedPageNumbers()).toEqual [1, 2, null, 6, 7, 8, 9, 10]
38
+
39
+ describe "pager controller", ->
40
+ $scope = null
41
+
42
+ beforeEach inject ($rootScope, $controller) ->
43
+ $scope = $rootScope.$new()
44
+ $controller("pager", $scope: $scope)
45
+
46
+ $scope.page = 2
47
+ $scope.totalPages = 10
48
+
49
+ describe "#setPage", ->
50
+ it "sets the current page", ->
51
+ $scope.setPage(3)
52
+ expect($scope.page).toBe(3)
53
+
54
+ describe "when the new page number is < 1", ->
55
+ it "sets to the first page", ->
56
+ for newPage in [1, 0, -1]
57
+ $scope.setPage(newPage)
58
+ expect($scope.page).toBe(1)
59
+
60
+ describe "when the new page is > totalPages", ->
61
+ it "sets to the last page", ->
62
+ for newPage in [10, 11, 12]
63
+ $scope.setPage(newPage)
64
+ expect($scope.page).toBe(10)
65
+
66
+ describe "#next", ->
67
+ it "sets to the next page", ->
68
+ $scope.page = 9
69
+ $scope.next()
70
+ expect($scope.page).toBe(10)
71
+
72
+ describe "when the current page is the last page", ->
73
+ it "sets does nothig", ->
74
+ $scope.page = 9
75
+ $scope.next()
76
+ expect($scope.page).toBe(10)
77
+
78
+ describe "#hasNext", ->
79
+ it "return true when there is a next page", ->
80
+ $scope.page = 9
81
+ expect($scope.hasNext()).toBeTruthy()
82
+
83
+ $scope.page = 10
84
+ expect($scope.hasNext()).toBeFalsy()
85
+
86
+ describe "#prev", ->
87
+ it "sets to the prev page", ->
88
+ $scope.page = 9
89
+ $scope.prev()
90
+ expect($scope.page).toBe(8)
91
+
92
+ describe "when the current page is the last first", ->
93
+ it "sets does nothig", ->
94
+ $scope.page = 1
95
+ $scope.prev()
96
+ expect($scope.page).toBe(1)
97
+
98
+ describe "#hasPrev", ->
99
+ it "return true when there is a previous page", ->
100
+ $scope.page = 9
101
+ expect($scope.hasPrev()).toBeTruthy()
102
+
103
+ $scope.page = 1
104
+ expect($scope.hasPrev()).toBeFalsy()
@@ -0,0 +1,76 @@
1
+ describe "mb.tableFilter", ->
2
+ beforeEach module("mb.tableFilter")
3
+
4
+ describe "tableFilter controller", ->
5
+ $scope = null
6
+
7
+ beforeEach inject ($controller, $rootScope) ->
8
+ $scope = $rootScope.$new()
9
+ $controller("tableFilter", $scope: $scope)
10
+
11
+ describe "#isEmpty", ->
12
+ it "returns true when the value is empty", ->
13
+ for value in [null, undefined, ""]
14
+ $scope.value = value
15
+ expect($scope.isEmpty()).toBeTruthy()
16
+
17
+ it "returs false when the value is not empty", ->
18
+ $scope.value = "foo"
19
+ expect($scope.isEmpty()).toBeFalsy()
20
+
21
+ describe "#clear", ->
22
+ it "clears the filter value", ->
23
+ $scope.value = "foo"
24
+ $scope.clear()
25
+
26
+ expect($scope.value).toEqual("")
27
+
28
+ describe "tableFilter", ->
29
+ $scope = null
30
+ element = null
31
+
32
+ beforeEach module("app/assets/templates/table_filter.html")
33
+
34
+ beforeEach inject ($rootScope, $compile) ->
35
+ $scope = $rootScope
36
+
37
+ tpl = """
38
+ <div>
39
+ <table-filter value="filterValue" placeholder="Enter database name"></table-filter>
40
+ </div>
41
+ """
42
+ element = $compile(tpl)($scope)
43
+ $scope.$digest()
44
+
45
+ it "sets the valid placeholder", ->
46
+ input = element.find("input[type='text']")
47
+ expect(input.attr('placeholder')).toEqual("Enter database name")
48
+
49
+ it "binds the filter value", ->
50
+ $scope.$apply -> $scope.filterValue = "Test filter value"
51
+
52
+ input = element.find("input[type='text']")
53
+ expect(input.val()).toEqual("Test filter value")
54
+
55
+ describe "the clear button", ->
56
+ button = null
57
+
58
+ beforeEach ->
59
+ button = element.find("button")
60
+
61
+ it "is initially disabled", ->
62
+ expect(button).toHaveCssClass("disabled")
63
+
64
+ describe "when value is not empty", ->
65
+ beforeEach ->
66
+ $scope.$apply -> $scope.filterValue = "some value"
67
+
68
+ it "is enabled", ->
69
+ expect(button).not.toHaveCssClass("disabled")
70
+
71
+ describe "when the value is empty", ->
72
+ beforeEach ->
73
+ $scope.$apply -> $scope.filterValue = ""
74
+
75
+ it "is disabled", ->
76
+ expect(button).toHaveCssClass("disabled")