mongo_browser 0.1.3 → 0.2.0.rc2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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")