admin_data 1.0.22 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/History.txt +23 -16
  2. data/README.md +1 -1
  3. data/Rakefile +2 -2
  4. data/app/controllers/admin_data/application_controller.rb +111 -0
  5. data/app/controllers/admin_data/crud_controller.rb +100 -0
  6. data/app/controllers/admin_data/feed_controller.rb +38 -16
  7. data/app/controllers/admin_data/home_controller.rb +11 -0
  8. data/app/controllers/admin_data/migration_controller.rb +12 -12
  9. data/app/controllers/admin_data/public_controller.rb +29 -19
  10. data/app/controllers/admin_data/search_controller.rb +99 -103
  11. data/app/controllers/admin_data/table_structure_controller.rb +25 -0
  12. data/app/helpers/admin_data/application_helper.rb +287 -0
  13. data/app/views/admin_data/crud/association/_association_info.html.erb +11 -0
  14. data/app/views/admin_data/crud/association/_belongs_to_info.html.erb +7 -0
  15. data/app/views/admin_data/{main → crud}/association/_habtm_info.html.erb +3 -3
  16. data/app/views/admin_data/{main → crud}/association/_has_many_info.html.erb +3 -3
  17. data/app/views/admin_data/crud/association/_has_one_info.html.erb +6 -0
  18. data/app/views/admin_data/{main → crud}/edit.html.erb +9 -9
  19. data/app/views/admin_data/{main → crud}/misc/_form.html.erb +6 -6
  20. data/app/views/admin_data/{main → crud}/misc/_modify_record.html.erb +4 -4
  21. data/app/views/admin_data/{main → crud}/new.html.erb +7 -7
  22. data/app/views/admin_data/{main → crud}/show.html.erb +10 -10
  23. data/app/views/admin_data/{main → home}/index.html.erb +2 -2
  24. data/app/views/admin_data/migration/index.html.erb +3 -3
  25. data/app/views/admin_data/search/_search_base.html.erb +5 -5
  26. data/app/views/admin_data/search/quick_search.html.erb +4 -4
  27. data/app/views/admin_data/search/search/_listing.html.erb +11 -9
  28. data/app/views/admin_data/search/search/_sortby.html.erb +4 -3
  29. data/app/views/admin_data/search/search/_title.html.erb +7 -7
  30. data/app/views/admin_data/shared/_breadcrum.html.erb +11 -5
  31. data/app/views/admin_data/shared/_header.html.erb +6 -6
  32. data/app/views/admin_data/shared/_secondary_navigation.html.erb +13 -14
  33. data/app/views/admin_data/{main/table_structure.html.erb → table_structure/index.html.erb} +11 -11
  34. data/app/views/layouts/admin_data.html.erb +15 -15
  35. data/config/routes.rb +3 -3
  36. data/lib/admin_data.rb +29 -6
  37. data/lib/admin_data/active_record_util.rb +38 -6
  38. data/lib/admin_data/configuration.rb +113 -0
  39. data/lib/admin_data/deprecation.rb +31 -0
  40. data/lib/admin_data/railtie.rb +2 -7
  41. data/lib/admin_data/search.rb +1 -1
  42. data/lib/admin_data/util.rb +74 -161
  43. data/lib/admin_data/version.rb +1 -1
  44. data/test/rails_root/app/controllers/application_controller.rb +3 -0
  45. data/test/rails_root/app/helpers/application_helper.rb +5 -0
  46. data/test/rails_root/app/models/city.rb +22 -0
  47. data/test/rails_root/app/models/club.rb +3 -0
  48. data/test/rails_root/app/models/newspaper.rb +4 -0
  49. data/test/rails_root/app/models/phone_number.rb +3 -0
  50. data/test/rails_root/app/models/user.rb +17 -0
  51. data/test/rails_root/app/models/website.rb +3 -0
  52. data/test/rails_root/config/application.rb +42 -0
  53. data/test/rails_root/config/boot.rb +13 -0
  54. data/test/rails_root/config/environment.rb +5 -0
  55. data/test/rails_root/config/environments/development.rb +22 -0
  56. data/test/rails_root/config/environments/production.rb +49 -0
  57. data/test/rails_root/config/environments/test.rb +35 -0
  58. data/test/rails_root/config/initializers/admin_data.rb +22 -0
  59. data/test/rails_root/config/initializers/backtrace_silencers.rb +7 -0
  60. data/test/rails_root/config/initializers/empty_spaces_to_nil.rb +10 -0
  61. data/test/rails_root/config/initializers/inflections.rb +10 -0
  62. data/test/rails_root/config/initializers/mime_types.rb +5 -0
  63. data/test/rails_root/config/initializers/secret_token.rb +7 -0
  64. data/test/rails_root/config/initializers/session_store.rb +8 -0
  65. data/test/rails_root/config/routes.rb +9 -0
  66. data/test/rails_root/db/migrate/20091030202259_create_users.rb +55 -0
  67. data/test/rails_root/db/schema.rb +63 -0
  68. data/test/rails_root/db/seeds.rb +40 -0
  69. data/test/rails_root/features/step_definitions/advance_search_steps.rb +13 -0
  70. data/test/rails_root/features/step_definitions/app_steps.rb +40 -0
  71. data/test/rails_root/features/step_definitions/async.rb +18 -0
  72. data/test/rails_root/features/step_definitions/crud_show_steps.rb +37 -0
  73. data/test/rails_root/features/step_definitions/feed_steps.rb +3 -0
  74. data/test/rails_root/features/step_definitions/quick_search_steps.rb +65 -0
  75. data/test/rails_root/features/step_definitions/util.rb +86 -0
  76. data/test/rails_root/features/step_definitions/web_steps.rb +219 -0
  77. data/test/rails_root/features/support/env.rb +68 -0
  78. data/test/rails_root/features/support/paths.rb +33 -0
  79. data/test/rails_root/test/factories.rb +30 -0
  80. data/test/rails_root/test/performance/browsing_test.rb +9 -0
  81. data/test/rails_root/test/test_helper.rb +13 -0
  82. metadata +100 -49
  83. data/app/controllers/admin_data/base_controller.rb +0 -112
  84. data/app/controllers/admin_data/main_controller.rb +0 -141
  85. data/app/views/admin_data/main/association/_association_info.html.erb +0 -11
  86. data/app/views/admin_data/main/association/_belongs_to_info.html.erb +0 -7
  87. data/app/views/admin_data/main/association/_has_one_info.html.erb +0 -6
  88. data/lib/admin_data/chelper.rb +0 -37
  89. data/lib/admin_data/helpers.rb +0 -271
  90. data/lib/admin_data/settings.rb +0 -67
  91. data/lib/css/base.css +0 -1108
  92. data/lib/css/vendor/jquery-ui-1.7.2.custom.css +0 -406
  93. data/lib/js/advance_search/act_on_result.js +0 -45
  94. data/lib/js/advance_search/advance_search.js +0 -83
  95. data/lib/js/advance_search/advance_search_structure.js +0 -79
  96. data/lib/js/advance_search/ajaxify_advance_search.js +0 -28
  97. data/lib/js/advance_search/build_first_row.js +0 -8
  98. data/lib/js/advance_search/event_bindings.js +0 -76
  99. data/lib/js/advance_search/global_ajax_setting.js +0 -10
  100. data/lib/js/advance_search/trigger_submit_on_domready.js +0 -6
  101. data/lib/js/misc/drop_down_change.js +0 -8
  102. data/lib/js/misc/js_util.js +0 -58
  103. data/lib/js/misc/quick_search_input_focus.js +0 -6
  104. data/lib/js/test/act_on_result.js +0 -120
  105. data/lib/js/test/advance_search.js +0 -80
  106. data/lib/js/test/ajaxify_advance_search.js +0 -29
  107. data/lib/js/test/build_first_row.js +0 -10
  108. data/lib/js/test/event_bindings.js +0 -100
  109. data/lib/js/vendor/jack.js +0 -903
  110. data/lib/js/vendor/jquery-1.4.2.js +0 -6240
  111. data/lib/js/vendor/jquery-ui-1.7.2.custom.min.js +0 -298
  112. data/lib/js/vendor/jquery.ba-isjquery.js +0 -21
  113. data/lib/js/vendor/jquery.form.js +0 -814
  114. data/lib/js/vendor/log.js +0 -9
  115. data/lib/js/vendor/qunit.js +0 -1043
  116. data/lib/js/vendor/rails.js +0 -132
@@ -1,80 +0,0 @@
1
- module('advance_search');
2
-
3
- test('buildFirstRow', function() {
4
- expect(2);
5
- $('#advance_search_table').html('');
6
- AdminData.advanceSearch.buildFirstRow();
7
- var $a = $('#advance_search_table').find('a');
8
- ok($a.hasClass('add_row_link'), 'first row should have anchor element with class remove_row');
9
- ok('+', $a.text(), 'first row should have anchor element with text +');
10
- });
11
-
12
-
13
- test("buildCol1", function() {
14
- expect(3);
15
-
16
- var $td = AdminData.advanceSearch.buildCol1();
17
- ok($.isjQuery($td), "buildCol1 should return an instance of jQuery");
18
-
19
- var className = $td.find('select').attr('className');
20
- equals('col1', className, 'buildCol1 should have select with class col1');
21
-
22
- var countOfOptions = $td.find('select option').length;
23
- equals(12, countOfOptions, 'buildCol1 should have select with 12 options');
24
- });
25
-
26
- test("buildCol2", function() {
27
- expect(3);
28
-
29
- var $td = AdminData.advanceSearch.buildCol2();
30
- ok($.isjQuery($td), "buildCol2 should return an instance of jQuery");
31
-
32
- ok($td.find('select').hasClass('col2'), 'buildCol2 should have class col2');
33
- ok($td.find('select').hasClass('disabled'), 'buildCol2 should have class disabled');
34
- });
35
-
36
- test("buildCol3", function() {
37
- expect(3);
38
-
39
- var $td = AdminData.advanceSearch.buildCol3();
40
- ok($.isjQuery($td), "buildCol3 should return an instance of jQuery");
41
-
42
- ok($td.find('input').hasClass('col3'), 'buildCol3 should have input element with class col3');
43
- ok($td.find('input').attr('disabled'), 'buildCol3 should have input element with attribute disabled');
44
- });
45
-
46
- test("buildCol4", function() {
47
- expect(3);
48
-
49
- var $td = AdminData.advanceSearch.buildCol4();
50
- ok($.isjQuery($td), "buildCol4 should return an instance of jQuery");
51
-
52
- var a = $td.find('a');
53
- ok(a.hasClass('remove_row'), 'buildCol4 should have anchor element with class remove_row');
54
- equals('x', a.text(), 'buildCol4 should have anchor element with text x');
55
- });
56
-
57
- test("buildRow", function() {
58
- expect(8);
59
- jack(function() {
60
- jack.expect("AdminData.jsUtil.randomNumber").exactly("1 time").mock(function() {
61
- return 100;
62
- });
63
-
64
- var $tr = AdminData.advanceSearch.buildRow();
65
- ok($.isjQuery($tr), "buildCol4 should return an instance of jQuery");
66
-
67
- equals(4, $tr.find('td').length, 'buildRow should have 4 td elements');
68
-
69
- ok($tr.find('select.col1').attr('name'), 'buildRow should have select.col1 with attribute name');
70
- ok($tr.find('select.col2').attr('name'), 'buildRow should have select.col1 with attribute name');
71
- ok($tr.find('input.col3').attr('name'), 'buildRow should have input.col1 with attribute name');
72
-
73
- equals('adv_search[100_row][col1]', $tr.find('select.col1').attr('name'), 'select.col1 should have right name');
74
- equals('adv_search[100_row][col2]', $tr.find('select.col2').attr('name'), 'select.col2 should have right name');
75
- equals('adv_search[100_row][col3]', $tr.find('input.col3').attr('name'), 'input.col3 should have right name');
76
-
77
- });
78
-
79
- });
80
-
@@ -1,29 +0,0 @@
1
- module('ajaxify advance search', {
2
- teardown: function() {
3
- $('#results').remove();
4
- $('#advance_search_form').remove();
5
- },
6
- setup: function() {
7
- $(document.body).append($('<div />', {
8
- id: 'results'
9
- }));
10
- $(document.body).append($('<div />', {
11
- id: 'advance_search_form'
12
- }));
13
- }
14
- });
15
-
16
- test('successCallback', function() {
17
- expect(1);
18
- AdminData.ajaxifyAdvanceSearch.successCallback('hello world');
19
- equals('hello world', $('#results').text(), '#results should have text hello world');
20
- });
21
-
22
- test('beforeSubmitCallback', function() {
23
- expect(1);
24
- AdminData.ajaxifyAdvanceSearch.beforeSubmitCallback(['1', '2'], null);
25
-
26
- var $results = $('#results');
27
- equals('searching...', $('#results').text(), '#results should have text searching');
28
- });
29
-
@@ -1,10 +0,0 @@
1
- module('build_first_row');
2
-
3
- test('table structure', function() {
4
- expect(1);
5
-
6
- var tableStructure = $('#advance_search_table').data('table_structure');
7
- ok(tableStructure, 'tableStructure should not be blank');
8
-
9
- });
10
-
@@ -1,100 +0,0 @@
1
- module('event_bindings');
2
-
3
- test('live click on a.add_row_link', function() {
4
- expect(3);
5
-
6
- $('#advance_search_table').html('');
7
- equals(0, $('#advance_search_table tr').length, 'there should be no row in the table');
8
-
9
- AdminData.advanceSearch.buildFirstRow();
10
- equals(1, $('#advance_search_table tr').length, 'there should be only first row in the table');
11
-
12
- $('#advance_search_table a.add_row_link').trigger('click');
13
- equals(2, $('#advance_search_table tr').length, 'additional row should be added to the table');
14
- });
15
-
16
- test('live click on a.remove_row link', function() {
17
- expect(5);
18
-
19
- $('#advance_search_table').html('');
20
- equals(0, $('#advance_search_table tr').length, 'there should be no row in the table');
21
-
22
- AdminData.advanceSearch.buildFirstRow();
23
- equals(1, $('#advance_search_table tr').length, 'there should be only first row in the table');
24
-
25
- $('#advance_search_table').append(AdminData.advanceSearch.buildRow());
26
- equals(2, $('#advance_search_table tr').length, 'there should be two rows in the table');
27
-
28
- var $a = $('#advance_search_table a.remove_row');
29
- equals(1, $a.length, 'there should be one anchor element with class remove_row');
30
-
31
- $('#advance_search_table a.remove_row').trigger('click');
32
- equals(1, $('#advance_search_table tr').length, 'there should be only one row in the table');
33
- });
34
-
35
- test('live select.col1 change', function() {
36
- expect(10);
37
-
38
- $('#advance_search_table').html('');
39
- equals(0, $('#advance_search_table tr').length, 'there should be no row in the table');
40
-
41
- AdminData.advanceSearch.buildFirstRow();
42
- equals(1, $('#advance_search_table tr').length, 'there should be only first row in the table');
43
-
44
- ok($('#advance_search_table select.col2').is(':disabled'), 'second column should be disabled');
45
-
46
- $('#advance_search_table select.col1').val('first_name');
47
- $('#advance_search_table select.col1').trigger('change');
48
-
49
- ok(!$('#advance_search_table select.col2').is(':disabled'), 'second column should be enabled');
50
-
51
- var s = $('#advance_search_table select.col2 option').eq(0).text();
52
- equals('', s, 'empty value should be the first option');
53
-
54
- s = $('#advance_search_table select.col2 option').eq(1).text();
55
- equals('is null', s, 'is null should be the second option');
56
-
57
- s = $('#advance_search_table select.col2 option').eq(2).text();
58
- equals('is not null', s, 'is null should be the third option');
59
-
60
- s = $('#advance_search_table select.col2 option').eq(3).text();
61
- equals('contains', s, 'contains should be the fourth option');
62
-
63
- s = $('#advance_search_table select.col2 option').eq(4).text();
64
- equals('is exactly', s, 'contains should be the fifth option');
65
-
66
- s = $('#advance_search_table select.col2 option').eq(5).text();
67
- equals("doesn't contain", s, 'does not contain should be the sixth option');
68
- });
69
-
70
- test('live select.col2 change', function() {
71
- expect(2);
72
-
73
- $('#advance_search_table').html('');
74
- AdminData.advanceSearch.buildFirstRow();
75
- ok($('#advance_search_table input.col3').is(':disabled'), 'third column should be disabled');
76
-
77
- $('#advance_search_table select.col1').val('first_name');
78
- $('#advance_search_table select.col1').trigger('change');
79
- $('#advance_search_table select.col2').val('contains');
80
- $('#advance_search_table select.col2').trigger('change');
81
-
82
- ok($('#advance_search_table input.col3').is(':enabled'), 'third column should be enabled');
83
- });
84
-
85
-
86
- test('live select.col2 change for is_null input', function() {
87
- expect(2);
88
-
89
- $('#advance_search_table').html('');
90
- AdminData.advanceSearch.buildFirstRow();
91
- ok($('#advance_search_table input.col3').is(':disabled'), 'third column should be disabled');
92
-
93
- $('#advance_search_table select.col1').val('first_name');
94
- $('#advance_search_table select.col1').trigger('change');
95
- $('#advance_search_table select.col2').val('is_null');
96
- $('#advance_search_table select.col2').trigger('change');
97
-
98
- ok($('#advance_search_table input.col3').is(':disabled'), 'third column should be disabled');
99
- });
100
-
@@ -1,903 +0,0 @@
1
- /**
2
- *
3
- * JACK :: JavaScript Mocking.
4
- * Version: $Id$
5
- *
6
- */
7
-
8
-
9
- function jack() {} // This needs to be here to make error reporting work correctly in IE.
10
-
11
- (function (){ // START HIDING FROM GLOBAL SCOPE
12
- /** EXPORT JACK **/
13
- window.jack = new Jack();
14
- window.jack.matchers = new Matchers();
15
- window.jack.util = new Util();
16
- window.jack.FunctionSpecification = FunctionSpecification;
17
- window.jack.FunctionGrab = FunctionGrab;
18
- return;
19
-
20
-
21
- /**
22
- * Constructor for object that will be exposed as the global jack
23
- */
24
- function Jack() {
25
- var functionGrabs = {};
26
- var objectGrabs = {};
27
- var environment = new Environment();
28
- var reportMessages = [];
29
- var currentExpectation = null;
30
- var publicApi = createPublicApi();
31
- return publicApi;
32
-
33
- function createPublicApi() {
34
- var api = jackFunction;
35
- api.grab = grab;
36
- api.create = create;
37
- api.inspect = inspect;
38
- api.expect = expect;
39
- api.verify = verify;
40
- api.report = report;
41
- api.reportAll = reportAll;
42
- api.env = environment;
43
- return api;
44
- }
45
- function jackFunction(delegate) {
46
- before();
47
- firstPass(delegate);
48
- // secondPass(delegate);
49
- after();
50
- }
51
- function before() {
52
- functionGrabs = {};
53
- objectGrabs = {};
54
- environment.reset();
55
- }
56
- function firstPass(delegate) {
57
- delegate();
58
- }
59
- function secondPass(delegate) {
60
- var oldExpect = publicApi.expect;
61
- publicApi.expect = function(name) {
62
- var fakeEx = {};
63
- var grab = findGrab(name);
64
- if(grab._beenThroughSecondPass) {
65
- var ex = grab.expect();
66
- for(prop in ex) {
67
- if(typeof ex[prop] == "function") {
68
- fakeEx[prop] = function() { return fakeEx; }
69
- }
70
- }
71
- }
72
- grab._beenThroughSecondPass = true;
73
- return fakeEx;
74
- };
75
- var findMore = true;
76
- for(var i=0; findMore && i<10; i++) {
77
- try {
78
- delegate();
79
- findMore = false;
80
- } catch(exception) {
81
- var line = -1;
82
- if(exception.lineNumber != null) {
83
- line = exception.lineNumber;
84
- } else if(exception['opera#sourceloc'] != null) {
85
- line = exception['opera#sourceloc'];
86
- }
87
- currentExpectation._lineNumber = line;
88
- }
89
- }
90
- publicApi.expect = oldExpect;
91
- }
92
- function after() {
93
- var reports = getTextReports();
94
- resetGrabs();
95
- if(reports.length > 0) {
96
- environment.report(reports[0]);
97
- }
98
- }
99
- function getTextReports() {
100
- var failedReports = [];
101
- for(var name in functionGrabs) {
102
- var reports = functionGrabs[name].reportAll(name);
103
- for(var i=0; i<reports.length; i++) {
104
- if(reports[i].fail) {
105
- failedReports.push(reports[i].message);
106
- }
107
- }
108
- }
109
- for(var name in objectGrabs) {
110
- var reports = objectGrabs[name].report(name);
111
- for(var i=0; i<reports.length; i++) {
112
- if(reports[i].fail) {
113
- failedReports.push(reports[i].message);
114
- }
115
- }
116
- }
117
- return failedReports;
118
- }
119
- function grab() {
120
- if("object" == typeof arguments[0] && "string" == typeof arguments[1]) {
121
- var parentObject = arguments[0];
122
- var name = arguments[1];
123
- var fullName = "[local]." + name;
124
- return grabFunction(fullName, parentObject[name], parentObject);
125
- } else {
126
- var grabbed = null;
127
- eval("grabbed = " + arguments[0]);
128
- if("function" == typeof grabbed) {
129
- var functionGrab = grabFunction(arguments[0], grabbed);
130
- eval("grabbed = " + arguments[0]);
131
- grabObject(arguments[0], grabbed);
132
- return functionGrab;
133
- } else if("object" == typeof grabbed) {
134
- return grabObject(arguments[0], grabbed);
135
- }
136
- return null;
137
- }
138
- }
139
- function grabFunction(fullName, grabbed, parentObject) {
140
- if(parentObject == null) {
141
- parentObject = window;
142
- }
143
- var functionName = fullName;
144
- var nameParts = fullName.split(".");
145
- if(nameParts[0] == "[local]") {
146
- functionName = nameParts[1];
147
- } else if(nameParts.length > 1) {
148
- functionName = nameParts.pop();
149
- if(parentObject == window) {
150
- var parentName = nameParts.join(".");
151
- eval("parentObject = " + parentName);
152
- }
153
- }
154
- functionGrabs[fullName] = new FunctionGrab(functionName, grabbed, parentObject);
155
- return functionGrabs[fullName];
156
- }
157
- function grabObject(name, grabbed) {
158
- objectGrabs[name] = new ObjectGrab(name, grabbed);
159
- return objectGrabs[name];
160
- }
161
- function create(objectName, functionNames) {
162
- var mockObject = {};
163
- for(var i=0; i<functionNames.length; i++) {
164
- mockObject[functionNames[i]] = function() {};
165
- var fullName = objectName+"."+functionNames[i];
166
- grabFunction(fullName, mockObject[functionNames[i]], mockObject);
167
- }
168
- return mockObject;
169
- }
170
- function inspect(name) {
171
- return findGrab(name);
172
- }
173
- function expect(name) {
174
- if(findGrab(name) == null) {
175
- grab(name);
176
- }
177
- currentExpectation = findGrab(name).expect().once();
178
- return currentExpectation;
179
- }
180
- function verify(name) {
181
- if(findGrab(name) == null) {
182
- grab(name);
183
- }
184
- currentExpectation = findGrab(name).expect().once();
185
- return currentExpectation;
186
- }
187
- function report(name, expectation) {
188
- return findGrab(name).report(expectation, name);
189
- }
190
- function reportAll(name) {
191
- return findGrab(name).reportAll(name);
192
- }
193
- function findGrab(name) {
194
- var parts = name.split(".");
195
- if(parts.length == 1 && functionGrabs[name] != null) {
196
- return functionGrabs[name];
197
- } else if(parts.length == 1 && objectGrabs[name] != null) {
198
- return objectGrabs[name];
199
- } else {
200
- if(functionGrabs[name] != null) {
201
- return functionGrabs[name];
202
- }
203
- if(objectGrabs[name] != null) {
204
- return objectGrabs[name];
205
- }
206
- if(objectGrabs[parts[0]] != null) {
207
- return objectGrabs[parts[0]].examine(parts[1]);
208
- }
209
- return undefined;
210
- }
211
- }
212
- function resetGrabs() {
213
- for(var g in functionGrabs) {
214
- functionGrabs[g].reset();
215
- }
216
- for(var g in objectGrabs) {
217
- objectGrabs[g].reset();
218
- }
219
- }
220
- } // END Jack()
221
-
222
-
223
- /**
224
- * @functionName Name of grabbed function
225
- * @grabbedFunction Reference to grabbed function
226
- * @parentObject The object the function was grabbed from
227
- */
228
- function FunctionGrab(functionName, grabbedFunction, parentObject) {
229
- var invocations = [];
230
- var specifications = [];
231
- var emptyFunction = function(){};
232
-
233
- init();
234
- return {
235
- 'times': function() { return invocations.length; },
236
- 'reset': reset,
237
- 'expect': expect,
238
- 'specify': specify,
239
- 'report': report,
240
- 'reportAll': reportAll,
241
- 'mock': mock,
242
- 'stub': stub,
243
- 'arguments': getArguments,
244
- 'name': function() { return functionName }
245
- };
246
-
247
- function init() {
248
- var original = parentObject[functionName];
249
- var handler = function() {
250
- return handleInvocation.apply(this,arguments);
251
- }
252
- for(var prop in original) {
253
- handler[prop] = original[prop];
254
- }
255
- parentObject[functionName] = handler;
256
- }
257
- function handleInvocation() {
258
- var invocation = new FunctionSpecification();
259
- for(var i=0; i<arguments.length; i++) {
260
- invocation.whereArgument(i).is(arguments[i]);
261
- }
262
- invocations.push(invocation);
263
- var specification = findSpecificationFor(invocation);
264
- if(specification == null) {
265
- return grabbedFunction.apply(this, arguments);
266
- } else if(specification.hasMockImplementation()) {
267
- return specification.invoke.apply(this, arguments);
268
- } else {
269
- specification.invoke.apply(this, arguments);
270
- return grabbedFunction.apply(this, arguments);
271
- }
272
- }
273
- function matchInvocationsToSpecifications() {
274
- for(var i=0; i<invocations.length; i++) {
275
- var spec = findSpecificationFor(invocations[i]);
276
- if(spec != null) {
277
-
278
- }
279
- }
280
- }
281
- function findSpecificationFor(invocation) {
282
- for(var i=0; i<specifications.length; i++) {
283
- var specification = specifications[i];
284
- if(invocation.satisfies(specification)) {
285
- return specification;
286
- }
287
- }
288
- return null;
289
- }
290
- function isArgumentContstraintsMatching(invocation, expectation) {
291
- var constr = expectation._argumentConstraints;
292
- var arg = invocation.arguments;
293
- if(constr == null) {
294
- return true;
295
- } else if(constr.length != arg.length) {
296
- return false;
297
- } else {
298
- for(var i=0; i<constr.length; i++) {
299
- if(!constr[i]) { continue; }
300
- for(var j=0; j<constr[i].length; j++) {
301
- if(typeof constr[i][j] == "function" && !constr[i][j](arg[i])) {
302
- return false;
303
- }
304
- }
305
- }
306
- return true;
307
- }
308
- }
309
- function reset() {
310
- parentObject[functionName] = grabbedFunction;
311
- }
312
- function specify() {
313
- var spec = new FunctionSpecification();
314
- spec._id = specifications.length;
315
- specifications.push(spec);
316
- return spec;
317
- }
318
- function verify() {
319
-
320
- }
321
- function expect() {
322
- return specify();
323
- }
324
- function mock(implementation) {
325
- return expect().mock(implementation);
326
- }
327
- function stub() {
328
- return expect();
329
- }
330
- function parseTimes(expression) {
331
- var result = 0;
332
- if("number" == typeof expression) {
333
- result = expression;
334
- } else if("string" == typeof expression) {
335
- var parts = expression.split(" ");
336
- result = parseInt(parts[0]);
337
- }
338
- return result;
339
- }
340
- function reportAll(fullName) {
341
- var reports = [];
342
- for(var i=0; i<specifications.length; i++) {
343
- reports.push(report(specifications[i], fullName));
344
- }
345
- return reports;
346
- }
347
- function report(specification, fullName) {
348
- if(specification == null) {
349
- if(specifications.length == 0) {
350
- var spec = specify().never();
351
- for(var i=0; i<invocations.length; i++) {
352
- spec.invoke();
353
- }
354
- }
355
- specification = specifications[0];
356
- }
357
- var report = {};
358
- report.expected = specification.invocations().expected;
359
- report.actual = specification.invocations().actual;
360
- report.success = specification.testTimes(report.actual);
361
- report.fail = !report.success;
362
- if(report.fail) {
363
- report.message = "Expectation failed: " + specification.describe(fullName);
364
- }
365
- return report;
366
- }
367
- function generateReportMessage(report, fullName, argumentsDisplay) {
368
- return report.messageParts.template
369
- .replace("{name}",fullName)
370
- .replace("{arguments}",argumentsDisplay)
371
- .replace("{quantifier}",report.messageParts.quantifier)
372
- .replace("{expected}",report.expected)
373
- .replace("{actual}",report.actual);
374
- }
375
- function getArgumentsDisplay(expectation) {
376
- if(expectation == null) {
377
- return "";
378
- }
379
- var displayValues = [];
380
- var constraints = expectation._argumentConstraints;
381
- if(constraints == null) {
382
- return "";
383
- } else {
384
- for(var i=0; i<constraints.length; i++) {
385
- if(constraints[i] != null) {
386
- displayValues.push(constraints[i][0].display);
387
- } else {
388
- displayValues.push('[any]');
389
- }
390
- }
391
- return displayValues.join(', ');
392
- }
393
- }
394
- function getArguments() {
395
- return invocations[0].getArgumentValues();
396
- }
397
- } // END FunctionGrab()
398
-
399
-
400
- /**
401
- *
402
- */
403
- function ObjectGrab(objectName, grabbedObject) {
404
- var grabs = {};
405
-
406
- init();
407
- return {
408
- 'examine': getGrab,
409
- 'report': report,
410
- 'getGrab': getGrab,
411
- 'getGrabs': function() { return grabs },
412
- 'reset': reset
413
- };
414
-
415
- function init() {
416
- for(key in grabbedObject) {
417
- var property = grabbedObject[key];
418
- if("function" == typeof property) {
419
- grabs[key] = new FunctionGrab(key, property, grabbedObject);
420
- }
421
- }
422
- }
423
- function report(name) {
424
- var allReports = [];
425
- for(var g in grabs) {
426
- var reports = grabs[g].reportAll(name+"."+grabs[g].name());
427
- for(var i=0; i<reports.length; i++) {
428
- allReports.push(reports[i]);
429
- }
430
- }
431
- return allReports;
432
- }
433
- function getGrab(name) {
434
- return grabs[name];
435
- }
436
- function reset() {
437
- for(var g in grabs) {
438
- grabs[g].reset();
439
- }
440
- }
441
- }
442
-
443
-
444
- /**
445
- *
446
- */
447
- function Environment() {
448
- var reportingEnabled = true;
449
- init();
450
- return {
451
- 'isJSSpec': isJSSpec,
452
- 'isScriptaculous': isScriptaculous,
453
- 'isQunit': isQunit,
454
- 'isJsTestDriver': isJsTestDriver,
455
- 'isYuiTest': isYuiTest,
456
- 'report': report,
457
- 'disableReporting': function() { reportingEnabled = false; },
458
- 'enableReporting': function() { reportingEnabled = true; },
459
- 'reset': function() {}
460
- }
461
- function init() {
462
-
463
- }
464
- function isJSSpec() {
465
- return window.JSSpec != null;
466
- }
467
- function isScriptaculous() {
468
- return window.Test != null && window.Test.Unit != null && window.Test.Unit.Runner != null;
469
- }
470
- function isQunit() {
471
- return window.QUnit != null;
472
- }
473
- function isJsTestDriver() {
474
- return window.jstestdriver != null;
475
- }
476
- function isYuiTest() {
477
- var y = window.YAHOO;
478
- return y != null && y.tool != null && y.tool.TestCase != null;
479
- }
480
- function report(message) {
481
- if(!reportingEnabled) { return; }
482
- if(isYuiTest()) {
483
- YAHOO.util.Assert.fail(message);
484
- } else if(isJsTestDriver()) {
485
- fail(message);
486
- } else if(isScriptaculous()) {
487
- throw new Error(message);
488
- } else if(isQunit()) {
489
- ok(false, message);
490
- } else if(isJSSpec()) {
491
- throw new Error(message);
492
- }
493
- }
494
- }
495
-
496
- /**
497
- *
498
- */
499
- function Util() {
500
- return {
501
- 'displayValue': displayValue
502
- }
503
-
504
- function displayValue() {
505
- var value = arguments[0];
506
- var prefix = "";
507
- if(arguments.length > 1) {
508
- value = arguments[1];
509
- prefix = arguments[0];
510
- }
511
- if(value == undefined) {
512
- return displayValueNullOrUndefined(value);
513
- }
514
- var display = displayValueDefault(value);
515
- if('string' == typeof value) {
516
- display = displayValueString(value);
517
- } else if(value.constructor == Array) {
518
- display = displayValueArray(value);
519
- } else if(value.constructor == RegExp) {
520
- display = displayValueRegExp(value);
521
- } else if('object' == typeof value) {
522
- display = displayValueObject(value);
523
- }
524
- return prefix + display;
525
- }
526
- function displayValueDefault(value) {
527
- return value.toString();
528
- }
529
- function displayValueString(value) {
530
- return "'" + value + "'";
531
- }
532
- function displayValueArray(value) {
533
- var displayValues = [];
534
- for(var i=0; i<value.length; i++) {
535
- displayValues.push(displayValue(value[i]));
536
- }
537
- return "[" + displayValues.join(",") + "]";
538
- }
539
- function displayValueNullOrUndefined(value) {
540
- if(value === undefined) {
541
- return "undefined";
542
- } else if(value === null) {
543
- return "null";
544
- }
545
- }
546
- function displayValueRegExp(value) {
547
- return value.toString();
548
- }
549
- function displayValueObject(value) {
550
- var keyValues = [];
551
- for(var p in value) {
552
- keyValues.push(p + ':' + displayValue(value[p]));
553
- }
554
- return '{' + keyValues.join(',') + '}';
555
- }
556
- }
557
-
558
- /**
559
- *
560
- */
561
- function FunctionSpecification() {
562
- var constraints = null;
563
- var argumentValues = [];
564
- var mockImplementation = null;
565
- var timing = {actual: 0, expected: 1, modifier: 0};
566
-
567
- var api = createApi();
568
- return api;
569
-
570
- function createApi() {
571
- var api = {};
572
- mixinMatchers(api);
573
- mixinTiming(api);
574
- api.test = test;
575
- api.testTimes = testTimes;
576
- api.satisfies = satisfies;
577
- api.invoke = invoke;
578
- api.mock = mock;
579
- api.stub = stub;
580
- api.returnValue = returnValue;
581
- api.returnValues = returnValues;
582
- api.describe = describe;
583
- api.invocations = invocations;
584
- api.getArgumentValues = getArgumentValues;
585
- api.hasMockImplementation = hasMockImplementation;
586
- return api;
587
- }
588
- function mixinMatchers(api) {
589
- api.whereArgument = function(argIndex) {
590
- var collected = {};
591
- for(var name in jack.matchers) {
592
- addMatcher(argIndex, name, collected)
593
- }
594
- return collected;
595
- }
596
- api.withArguments = function() {
597
- for(var i=0; i<arguments.length; i++) {
598
- api.whereArgument(i).is(arguments[i]);
599
- }
600
- return api;
601
- }
602
- api.withNoArguments = function() { constraints = []; return api; }
603
- return api;
604
-
605
- function addMatcher(argIndex, name, collection) {
606
- collection[name] = function() {
607
- addConstraint(argIndex, jack.matchers[name], arguments);
608
- if(name == "is") {
609
- addArgumentValue(argIndex, arguments[0]);
610
- }
611
- return api;
612
- }
613
- }
614
- }
615
- function mixinTiming(api) {
616
- api.exactly = function(times) {
617
- timing.expected = parseTimes(times);
618
- return api;
619
- }
620
- api.once = function() {
621
- timing.expected = 1;
622
- return api;
623
- }
624
- api.atLeast = function(times) {
625
- timing.expected = parseTimes(times);
626
- timing.modifier = 1;
627
- return api;
628
- }
629
- api.atMost = function(times) {
630
- timing.expected = parseTimes(times);
631
- timing.modifier = -1;
632
- return api;
633
- }
634
- api.never = function() {
635
- timing.expected = 0;
636
- return api;
637
- }
638
-
639
- function parseTimes(times) {
640
- return parseInt(times);
641
- }
642
- }
643
- function addArgumentValue(index, value) {
644
- argumentValues[index] = value;
645
- }
646
- function addConstraint(argIndex, matcher, matcherArguments) {
647
- createConstraintsArrayIfNull(argIndex);
648
- var constraint = function(value) {
649
- var allArguments = [value];
650
- for(var i=0; i<matcherArguments.length; i++) {
651
- allArguments.push(matcherArguments[i]);
652
- }
653
- var test = matcher.apply(null, allArguments);
654
- return test.result;
655
- }
656
- constraints[argIndex].push(constraint);
657
- constraints[argIndex].describe = function() {
658
- var allArguments = [""];
659
- for(var i=0; i<matcherArguments.length; i++) {
660
- allArguments.push(matcherArguments[i]);
661
- }
662
- return matcher.apply(null, allArguments).expected;
663
- }
664
- }
665
- function createConstraintsArrayIfNull(argIndex) {
666
- if(constraints == null) {
667
- constraints = [];
668
- }
669
- if(constraints[argIndex] == null) {
670
- constraints[argIndex] = [];
671
- }
672
- }
673
- function test() {
674
- var result = true;
675
- if(constraints != null) {
676
- if(constraints.length != arguments.length) {
677
- result = false;
678
- } else {
679
- for (var i = 0; i < constraints.length; i++) {
680
- var oneArgumentsConstraints = constraints[i];
681
- if (oneArgumentsConstraints != null) {
682
- for (var j = 0; j < oneArgumentsConstraints.length; j++) {
683
- var constraint = oneArgumentsConstraints[j];
684
- if (constraint && !constraint(arguments[i])) {
685
- result = false;
686
- }
687
- }
688
- }
689
- }
690
- }
691
- }
692
- return result;
693
- }
694
- function testTimes(times) {
695
- if(timing.modifier == 0) {
696
- return times == timing.expected;
697
- } else if(timing.modifier == 1) {
698
- return times >= timing.expected;
699
- } else if(timing.modifier == -1) {
700
- return times <= timing.expected;
701
- }
702
- }
703
- function satisfies(other) {
704
- return other.test.apply(this, argumentValues);
705
- }
706
- function invoke() {
707
- timing.actual++;
708
- if(mockImplementation != null) {
709
- return mockImplementation.apply(this, arguments);
710
- }
711
- }
712
- function mock(implementation) {
713
- mockImplementation = implementation;
714
- return api;
715
- }
716
- function stub() {
717
- mockImplementation = function() {};
718
- return api;
719
- }
720
- function returnValue(value) {
721
- mockImplementation = function() {
722
- return value;
723
- }
724
- }
725
- function returnValues() {
726
- var values = [], orig = this;
727
- for (var i = 0, len = arguments.length; i < len; i++) { values.push(arguments[i]); }
728
- mockImplementation = function() {
729
- return values.shift();
730
- };
731
- }
732
- function hasMockImplementation() {
733
- return mockImplementation != null;
734
- }
735
- function invocations() {
736
- return {
737
- actual: timing.actual,
738
- expected: timing.expected
739
- };
740
- }
741
- function getArgumentValues() {
742
- return argumentValues;
743
- }
744
- function describe(name) {
745
- return name +"(" + describeConstraints() + ") " + describeTimes();
746
- }
747
- function describeConstraints() {
748
- if(constraints == null) {
749
- return "";
750
- }
751
- var descriptions = [];
752
- for(var i=0; i<constraints.length; i++) {
753
- if(constraints[i] != null) {
754
- descriptions.push(constraints[i].describe());
755
- } else {
756
- descriptions.push("[any]");
757
- }
758
- }
759
- return descriptions.join(", ");
760
- }
761
- function describeTimes() {
762
- var description = timing.expected;
763
- if(timing.expected == 1) {
764
- description += " time";
765
- } else {
766
- description += " times";
767
- }
768
- if(timing.modifier == 0) {
769
- description = "expected exactly " + description;
770
- } else if(timing.modifier > 0) {
771
- description = "expected at least " + description;
772
- } else if(timing.modifier < 0) {
773
- description = "expected at most " + description;
774
- }
775
- description += ", called " + timing.actual + " time";
776
- if(timing.actual != 1) {
777
- description += "s";
778
- }
779
- return description;
780
- }
781
- }
782
-
783
-
784
- /**
785
- *
786
- */
787
- function Matchers() {
788
- return {
789
- 'is':
790
- function(a, b) {
791
- return result(a==b, a, '', b);
792
- },
793
- 'isNot':
794
- function(a, b) {
795
- return result(a!=b, a, 'not:', b);
796
- },
797
- 'isType':
798
- function(a, b) {
799
- return result(b == typeof a, a, 'type:', b);
800
- },
801
- 'matches':
802
- function(a, b) {
803
- return result(b.test(a), a, 'matching:', b)
804
- },
805
- 'hasProperty':
806
- function(a, b, c) {
807
- var match = c ? a[b]==c : a[b]!=undefined;
808
- var bDisplay = b;
809
- if(c != null) {
810
- bDisplay = {};
811
- bDisplay[b] = c;
812
- }
813
- return result(match, a, 'property:', bDisplay)
814
- },
815
- 'hasProperties':
816
- function(a, b) {
817
- var match = true;
818
- for(var p in b) {
819
- if(a[p] != b[p]) {
820
- match = false;
821
- }
822
- }
823
- return result(match, a, 'properties:', b);
824
- },
825
- 'isGreaterThan':
826
- function(a, b) {
827
- return result(b < a, a, '>', b);
828
- },
829
- 'isLessThan':
830
- function(a, b) {
831
- return result(b > a, a, '<', b);
832
- },
833
- 'isOneOf':
834
- function() {
835
- var a = arguments[0];
836
- var b = [];
837
- for(var i=1; i<arguments.length; i++) {
838
- b.push(arguments[i]);
839
- }
840
- var match = false;
841
- for(var i=0; i<b.length; i++) {
842
- if(b[i] == a) {
843
- match = true;
844
- }
845
- }
846
- return result(match, a, 'oneOf:', b);
847
- }
848
- }
849
-
850
- function result(match, actual, prefix, expected) {
851
- return {
852
- result: match,
853
- actual: jack.util.displayValue(actual),
854
- expected: jack.util.displayValue(prefix, expected)
855
- }
856
- }
857
- }
858
-
859
- })(); // END HIDING FROM GLOBAL SCOPE
860
-
861
-
862
-
863
-
864
-
865
-
866
-
867
-
868
-
869
-
870
-
871
-
872
-
873
-
874
-
875
-
876
-
877
-
878
-
879
-
880
-
881
-
882
-
883
-
884
-
885
-
886
-
887
-
888
-
889
-
890
-
891
-
892
-
893
-
894
-
895
-
896
-
897
-
898
-
899
-
900
-
901
-
902
-
903
-