jasmine-core 2.0.0 → 2.1.0

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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/lib/console/console.js +54 -24
  3. data/lib/jasmine-core/__init__.py +1 -0
  4. data/lib/jasmine-core/boot/boot.js +2 -63
  5. data/lib/jasmine-core/boot/node_boot.js +19 -0
  6. data/lib/jasmine-core/boot.js +3 -64
  7. data/lib/jasmine-core/core.py +60 -0
  8. data/lib/jasmine-core/example/node_example/spec/PlayerSpec.js +60 -0
  9. data/lib/jasmine-core/example/node_example/spec/SpecHelper.js +15 -0
  10. data/lib/jasmine-core/example/node_example/src/Player.js +24 -0
  11. data/lib/jasmine-core/example/node_example/src/Song.js +9 -0
  12. data/lib/jasmine-core/jasmine-html.js +119 -74
  13. data/lib/jasmine-core/jasmine.css +61 -54
  14. data/lib/jasmine-core/jasmine.js +961 -456
  15. data/lib/jasmine-core/json2.js +73 -62
  16. data/lib/jasmine-core/node_boot.js +41 -0
  17. data/lib/jasmine-core/spec/console/ConsoleReporterSpec.js +52 -8
  18. data/lib/jasmine-core/spec/core/AnySpec.js +1 -0
  19. data/lib/jasmine-core/spec/core/ClockSpec.js +122 -18
  20. data/lib/jasmine-core/spec/core/DelayedFunctionSchedulerSpec.js +14 -1
  21. data/lib/jasmine-core/spec/core/EnvSpec.js +0 -63
  22. data/lib/jasmine-core/spec/core/ExceptionFormatterSpec.js +7 -0
  23. data/lib/jasmine-core/spec/core/ExceptionsSpec.js +2 -2
  24. data/lib/jasmine-core/spec/core/ExpectationSpec.js +46 -50
  25. data/lib/jasmine-core/spec/core/JsApiReporterSpec.js +37 -0
  26. data/lib/jasmine-core/spec/core/MockDateSpec.js +200 -0
  27. data/lib/jasmine-core/spec/core/ObjectContainingSpec.js +6 -0
  28. data/lib/jasmine-core/spec/core/PrettyPrintSpec.js +49 -12
  29. data/lib/jasmine-core/spec/core/QueueRunnerSpec.js +184 -60
  30. data/lib/jasmine-core/spec/core/SpecSpec.js +46 -108
  31. data/lib/jasmine-core/spec/core/SpyRegistrySpec.js +55 -0
  32. data/lib/jasmine-core/spec/core/SpySpec.js +10 -0
  33. data/lib/jasmine-core/spec/core/SpyStrategySpec.js +13 -0
  34. data/lib/jasmine-core/spec/core/SuiteSpec.js +143 -11
  35. data/lib/jasmine-core/spec/core/TimerSpec.js +18 -0
  36. data/lib/jasmine-core/spec/core/integration/CustomMatchersSpec.js +34 -32
  37. data/lib/jasmine-core/spec/core/integration/EnvSpec.js +969 -36
  38. data/lib/jasmine-core/spec/core/integration/SpecRunningSpec.js +279 -3
  39. data/lib/jasmine-core/spec/core/matchers/matchersUtilSpec.js +18 -1
  40. data/lib/jasmine-core/spec/core/matchers/toBeGreaterThanSpec.js +2 -1
  41. data/lib/jasmine-core/spec/core/matchers/toBeNaNSpec.js +3 -2
  42. data/lib/jasmine-core/spec/core/matchers/toBeUndefinedSpec.js +2 -1
  43. data/lib/jasmine-core/spec/core/matchers/toContainSpec.js +4 -2
  44. data/lib/jasmine-core/spec/core/matchers/toHaveBeenCalledSpec.js +2 -1
  45. data/lib/jasmine-core/spec/core/matchers/toHaveBeenCalledWithSpec.js +17 -3
  46. data/lib/jasmine-core/spec/core/matchers/toThrowErrorSpec.js +14 -14
  47. data/lib/jasmine-core/spec/core/matchers/toThrowSpec.js +5 -5
  48. data/lib/jasmine-core/spec/helpers/defineJasmineUnderTest.js +7 -0
  49. data/lib/jasmine-core/spec/helpers/nodeDefineJasmineUnderTest.js +33 -0
  50. data/lib/jasmine-core/spec/html/HtmlReporterSpec.js +183 -35
  51. data/lib/jasmine-core/spec/html/PrettyPrintHtmlSpec.js +1 -1
  52. data/lib/jasmine-core/spec/node_suite.js +9 -1
  53. data/lib/jasmine-core/spec/npmPackage/npmPackageSpec.js +104 -0
  54. data/lib/jasmine-core/spec/performance/large_object_test.js +36 -0
  55. data/lib/jasmine-core/version.rb +1 -1
  56. data/lib/jasmine-core.js +37 -0
  57. data/lib/jasmine-core.rb +6 -2
  58. metadata +23 -9
  59. data/lib/jasmine-core/spec/support/dev_boot.js +0 -124
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 64fc08a60b942909e10f43cd7568374e95e0ccda
4
- data.tar.gz: f6cc9a58eeb24163496fb22903321b73d97cd3fd
3
+ metadata.gz: b3c55f40da8c8da5e3d89ae36a5aaae867bd50ea
4
+ data.tar.gz: 3d48a8581f0ca9decccbb8fe75ae82f22bd99e40
5
5
  SHA512:
6
- metadata.gz: 24d62c7f7aea8cc8b640f562a77ba219d25b203e587df68b2b29245d22e98e0475ca27fbf2f994f031b89b35b4c8e08c1ba402f1dc8eb81281c90ee27a909daf
7
- data.tar.gz: d2ee9eacc009ce20f427baf2a13d61b69abb814d1a40788986d393322ccad3347d2f00b57c5c2feb57ccb88231fa6d5e49049aa8c99c1268566a798ddb9aa60a
6
+ metadata.gz: e506e314ceeef5435bdd4ad916f93efe9c006cc71f5404c0376c2718fe10af4a83a4d51ffc3df7b143d9000484d6ae19013675e00cda8607db9cb0f3f27dbae9
7
+ data.tar.gz: d1856674ca87ce7da66ec763ba372bbc034631943f607ae4b1ece8ee395112cd2027feecb217c115a90de4e0201a614894ff25dff6fd6d6746954af075585113
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright (c) 2008-2013 Pivotal Labs
2
+ Copyright (c) 2008-2014 Pivotal Labs
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining
5
5
  a copy of this software and associated documentation files (the
@@ -21,7 +21,7 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
21
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  */
23
23
  function getJasmineRequireObj() {
24
- if (typeof module !== "undefined" && module.exports) {
24
+ if (typeof module !== 'undefined' && module.exports) {
25
25
  return exports;
26
26
  } else {
27
27
  window.jasmineRequire = window.jasmineRequire || {};
@@ -54,13 +54,16 @@ getJasmineRequireObj().ConsoleReporter = function() {
54
54
  red: '\x1B[31m',
55
55
  yellow: '\x1B[33m',
56
56
  none: '\x1B[0m'
57
- };
57
+ },
58
+ failedSuites = [];
59
+
60
+ print('ConsoleReporter is deprecated and will be removed in a future version.');
58
61
 
59
62
  this.jasmineStarted = function() {
60
63
  specCount = 0;
61
64
  failureCount = 0;
62
65
  pendingCount = 0;
63
- print("Started");
66
+ print('Started');
64
67
  printNewline();
65
68
  timer.start();
66
69
  };
@@ -71,50 +74,65 @@ getJasmineRequireObj().ConsoleReporter = function() {
71
74
  specFailureDetails(failedSpecs[i]);
72
75
  }
73
76
 
74
- printNewline();
75
- var specCounts = specCount + " " + plural("spec", specCount) + ", " +
76
- failureCount + " " + plural("failure", failureCount);
77
+ if(specCount > 0) {
78
+ printNewline();
77
79
 
78
- if (pendingCount) {
79
- specCounts += ", " + pendingCount + " pending " + plural("spec", pendingCount);
80
- }
80
+ var specCounts = specCount + ' ' + plural('spec', specCount) + ', ' +
81
+ failureCount + ' ' + plural('failure', failureCount);
82
+
83
+ if (pendingCount) {
84
+ specCounts += ', ' + pendingCount + ' pending ' + plural('spec', pendingCount);
85
+ }
81
86
 
82
- print(specCounts);
87
+ print(specCounts);
88
+ } else {
89
+ print('No specs found');
90
+ }
83
91
 
84
92
  printNewline();
85
93
  var seconds = timer.elapsed() / 1000;
86
- print("Finished in " + seconds + " " + plural("second", seconds));
87
-
94
+ print('Finished in ' + seconds + ' ' + plural('second', seconds));
88
95
  printNewline();
89
96
 
97
+ for(i = 0; i < failedSuites.length; i++) {
98
+ suiteFailureDetails(failedSuites[i]);
99
+ }
100
+
90
101
  onComplete(failureCount === 0);
91
102
  };
92
103
 
93
104
  this.specDone = function(result) {
94
105
  specCount++;
95
106
 
96
- if (result.status == "pending") {
107
+ if (result.status == 'pending') {
97
108
  pendingCount++;
98
- print(colored("yellow", "*"));
109
+ print(colored('yellow', '*'));
99
110
  return;
100
111
  }
101
112
 
102
- if (result.status == "passed") {
103
- print(colored("green", '.'));
113
+ if (result.status == 'passed') {
114
+ print(colored('green', '.'));
104
115
  return;
105
116
  }
106
117
 
107
- if (result.status == "failed") {
118
+ if (result.status == 'failed') {
108
119
  failureCount++;
109
120
  failedSpecs.push(result);
110
- print(colored("red", 'F'));
121
+ print(colored('red', 'F'));
122
+ }
123
+ };
124
+
125
+ this.suiteDone = function(result) {
126
+ if (result.failedExpectations && result.failedExpectations.length > 0) {
127
+ failureCount++;
128
+ failedSuites.push(result);
111
129
  }
112
130
  };
113
131
 
114
132
  return this;
115
133
 
116
134
  function printNewline() {
117
- print("\n");
135
+ print('\n');
118
136
  }
119
137
 
120
138
  function colored(color, str) {
@@ -122,7 +140,7 @@ getJasmineRequireObj().ConsoleReporter = function() {
122
140
  }
123
141
 
124
142
  function plural(str, count) {
125
- return count == 1 ? str : str + "s";
143
+ return count == 1 ? str : str + 's';
126
144
  }
127
145
 
128
146
  function repeat(thing, times) {
@@ -134,12 +152,12 @@ getJasmineRequireObj().ConsoleReporter = function() {
134
152
  }
135
153
 
136
154
  function indent(str, spaces) {
137
- var lines = (str || '').split("\n");
155
+ var lines = (str || '').split('\n');
138
156
  var newArr = [];
139
157
  for (var i = 0; i < lines.length; i++) {
140
- newArr.push(repeat(" ", spaces).join("") + lines[i]);
158
+ newArr.push(repeat(' ', spaces).join('') + lines[i]);
141
159
  }
142
- return newArr.join("\n");
160
+ return newArr.join('\n');
143
161
  }
144
162
 
145
163
  function specFailureDetails(result) {
@@ -149,11 +167,23 @@ getJasmineRequireObj().ConsoleReporter = function() {
149
167
  for (var i = 0; i < result.failedExpectations.length; i++) {
150
168
  var failedExpectation = result.failedExpectations[i];
151
169
  printNewline();
170
+ print(indent(failedExpectation.message, 2));
152
171
  print(indent(failedExpectation.stack, 2));
153
172
  }
154
173
 
155
174
  printNewline();
156
175
  }
176
+
177
+ function suiteFailureDetails(result) {
178
+ for (var i = 0; i < result.failedExpectations.length; i++) {
179
+ printNewline();
180
+ print(colored('red', 'An error was thrown in an afterAll'));
181
+ printNewline();
182
+ print(colored('red', 'AfterAll ' + result.failedExpectations[i].message));
183
+
184
+ }
185
+ printNewline();
186
+ }
157
187
  }
158
188
 
159
189
  return ConsoleReporter;
@@ -0,0 +1 @@
1
+ from .core import Core
@@ -1,5 +1,5 @@
1
1
  /**
2
- Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
2
+ Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js` and `jasmine_html.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
3
3
 
4
4
  If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms.
5
5
 
@@ -32,47 +32,7 @@
32
32
  *
33
33
  * Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged.
34
34
  */
35
- var jasmineInterface = {
36
- describe: function(description, specDefinitions) {
37
- return env.describe(description, specDefinitions);
38
- },
39
-
40
- xdescribe: function(description, specDefinitions) {
41
- return env.xdescribe(description, specDefinitions);
42
- },
43
-
44
- it: function(desc, func) {
45
- return env.it(desc, func);
46
- },
47
-
48
- xit: function(desc, func) {
49
- return env.xit(desc, func);
50
- },
51
-
52
- beforeEach: function(beforeEachFunction) {
53
- return env.beforeEach(beforeEachFunction);
54
- },
55
-
56
- afterEach: function(afterEachFunction) {
57
- return env.afterEach(afterEachFunction);
58
- },
59
-
60
- expect: function(actual) {
61
- return env.expect(actual);
62
- },
63
-
64
- pending: function() {
65
- return env.pending();
66
- },
67
-
68
- spyOn: function(obj, methodName) {
69
- return env.spyOn(obj, methodName);
70
- },
71
-
72
- jsApiReporter: new jasmine.JsApiReporter({
73
- timer: new jasmine.Timer()
74
- })
75
- };
35
+ var jasmineInterface = jasmineRequire.interface(jasmine, env);
76
36
 
77
37
  /**
78
38
  * Add all of the Jasmine global/public interface to the proper global, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
@@ -83,27 +43,6 @@
83
43
  extend(window, jasmineInterface);
84
44
  }
85
45
 
86
- /**
87
- * Expose the interface for adding custom equality testers.
88
- */
89
- jasmine.addCustomEqualityTester = function(tester) {
90
- env.addCustomEqualityTester(tester);
91
- };
92
-
93
- /**
94
- * Expose the interface for adding custom expectation matchers
95
- */
96
- jasmine.addMatchers = function(matchers) {
97
- return env.addMatchers(matchers);
98
- };
99
-
100
- /**
101
- * Expose the mock interface for the JavaScript timeout functions
102
- */
103
- jasmine.clock = function() {
104
- return env.clock;
105
- };
106
-
107
46
  /**
108
47
  * ## Runner Parameters
109
48
  *
@@ -0,0 +1,19 @@
1
+ module.exports = function(jasmineRequire) {
2
+ var jasmine = jasmineRequire.core(jasmineRequire);
3
+
4
+ var consoleFns = require('../console/console.js');
5
+ consoleFns.console(consoleFns, jasmine);
6
+
7
+ var env = jasmine.getEnv();
8
+
9
+ var jasmineInterface = jasmineRequire.interface(jasmine, env);
10
+
11
+ extend(global, jasmineInterface);
12
+
13
+ function extend(destination, source) {
14
+ for (var property in source) destination[property] = source[property];
15
+ return destination;
16
+ }
17
+
18
+ return jasmine;
19
+ };
@@ -1,5 +1,5 @@
1
1
  /*
2
- Copyright (c) 2008-2013 Pivotal Labs
2
+ Copyright (c) 2008-2014 Pivotal Labs
3
3
 
4
4
  Permission is hereby granted, free of charge, to any person obtaining
5
5
  a copy of this software and associated documentation files (the
@@ -21,7 +21,7 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
21
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  */
23
23
  /**
24
- Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
24
+ Starting with version 2.0, this file "boots" Jasmine, performing all of the necessary initialization before executing the loaded environment and all of a project's specs. This file should be loaded after `jasmine.js` and `jasmine_html.js`, but before any project source files or spec files are loaded. Thus this file can also be used to customize Jasmine for a project.
25
25
 
26
26
  If a project is using Jasmine via the standalone distribution, this file can be customized directly. If a project is using Jasmine via the [Ruby gem][jasmine-gem], this file can be copied into the support directory via `jasmine copy_boot_js`. Other environments (e.g., Python) will have different mechanisms.
27
27
 
@@ -54,47 +54,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
54
54
  *
55
55
  * Build up the functions that will be exposed as the Jasmine public interface. A project can customize, rename or alias any of these functions as desired, provided the implementation remains unchanged.
56
56
  */
57
- var jasmineInterface = {
58
- describe: function(description, specDefinitions) {
59
- return env.describe(description, specDefinitions);
60
- },
61
-
62
- xdescribe: function(description, specDefinitions) {
63
- return env.xdescribe(description, specDefinitions);
64
- },
65
-
66
- it: function(desc, func) {
67
- return env.it(desc, func);
68
- },
69
-
70
- xit: function(desc, func) {
71
- return env.xit(desc, func);
72
- },
73
-
74
- beforeEach: function(beforeEachFunction) {
75
- return env.beforeEach(beforeEachFunction);
76
- },
77
-
78
- afterEach: function(afterEachFunction) {
79
- return env.afterEach(afterEachFunction);
80
- },
81
-
82
- expect: function(actual) {
83
- return env.expect(actual);
84
- },
85
-
86
- pending: function() {
87
- return env.pending();
88
- },
89
-
90
- spyOn: function(obj, methodName) {
91
- return env.spyOn(obj, methodName);
92
- },
93
-
94
- jsApiReporter: new jasmine.JsApiReporter({
95
- timer: new jasmine.Timer()
96
- })
97
- };
57
+ var jasmineInterface = jasmineRequire.interface(jasmine, env);
98
58
 
99
59
  /**
100
60
  * Add all of the Jasmine global/public interface to the proper global, so a project can use the public interface directly. For example, calling `describe` in specs instead of `jasmine.getEnv().describe`.
@@ -105,27 +65,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
105
65
  extend(window, jasmineInterface);
106
66
  }
107
67
 
108
- /**
109
- * Expose the interface for adding custom equality testers.
110
- */
111
- jasmine.addCustomEqualityTester = function(tester) {
112
- env.addCustomEqualityTester(tester);
113
- };
114
-
115
- /**
116
- * Expose the interface for adding custom expectation matchers
117
- */
118
- jasmine.addMatchers = function(matchers) {
119
- return env.addMatchers(matchers);
120
- };
121
-
122
- /**
123
- * Expose the mock interface for the JavaScript timeout functions
124
- */
125
- jasmine.clock = function() {
126
- return env.clock;
127
- };
128
-
129
68
  /**
130
69
  * ## Runner Parameters
131
70
  *
@@ -0,0 +1,60 @@
1
+ import pkg_resources
2
+
3
+ try:
4
+ from collections import OrderedDict
5
+ except ImportError:
6
+ from ordereddict import OrderedDict
7
+
8
+ class Core(object):
9
+ @classmethod
10
+ def js_package(cls):
11
+ return __package__
12
+
13
+ @classmethod
14
+ def css_package(cls):
15
+ return __package__
16
+
17
+ @classmethod
18
+ def image_package(cls):
19
+ return __package__ + ".images"
20
+
21
+ @classmethod
22
+ def js_files(cls):
23
+ js_files = sorted(list(filter(lambda x: '.js' in x, pkg_resources.resource_listdir(cls.js_package(), '.'))))
24
+
25
+ # jasmine.js needs to be first
26
+ js_files.insert(0, 'jasmine.js')
27
+
28
+ # boot needs to be last
29
+ js_files.remove('boot.js')
30
+ js_files.append('boot.js')
31
+
32
+ return cls._uniq(js_files)
33
+
34
+ @classmethod
35
+ def css_files(cls):
36
+ return cls._uniq(sorted(filter(lambda x: '.css' in x, pkg_resources.resource_listdir(cls.css_package(), '.'))))
37
+
38
+ @classmethod
39
+ def favicon(cls):
40
+ return 'jasmine_favicon.png'
41
+
42
+ @classmethod
43
+ def _uniq(self, items, idfun=None):
44
+ # order preserving
45
+
46
+ if idfun is None:
47
+ def idfun(x): return x
48
+ seen = {}
49
+ result = []
50
+ for item in items:
51
+ marker = idfun(item)
52
+ # in old Python versions:
53
+ # if seen.has_key(marker)
54
+ # but in new ones:
55
+ if marker in seen:
56
+ continue
57
+
58
+ seen[marker] = 1
59
+ result.append(item)
60
+ return result
@@ -0,0 +1,60 @@
1
+ describe("Player", function() {
2
+ var Player = require('../src/Player.js');
3
+ var Song = require('../src/Song.js');
4
+ var player;
5
+ var song;
6
+
7
+ beforeEach(function() {
8
+ player = new Player();
9
+ song = new Song();
10
+ });
11
+
12
+ it("should be able to play a Song", function() {
13
+ player.play(song);
14
+ expect(player.currentlyPlayingSong).toEqual(song);
15
+
16
+ //demonstrates use of custom matcher
17
+ expect(player).toBePlaying(song);
18
+ });
19
+
20
+ describe("when song has been paused", function() {
21
+ beforeEach(function() {
22
+ player.play(song);
23
+ player.pause();
24
+ });
25
+
26
+ it("should indicate that the song is currently paused", function() {
27
+ expect(player.isPlaying).toBeFalsy();
28
+
29
+ // demonstrates use of 'not' with a custom matcher
30
+ expect(player).not.toBePlaying(song);
31
+ });
32
+
33
+ it("should be possible to resume", function() {
34
+ player.resume();
35
+ expect(player.isPlaying).toBeTruthy();
36
+ expect(player.currentlyPlayingSong).toEqual(song);
37
+ });
38
+ });
39
+
40
+ // demonstrates use of spies to intercept and test method calls
41
+ it("tells the current song if the user has made it a favorite", function() {
42
+ spyOn(song, 'persistFavoriteStatus');
43
+
44
+ player.play(song);
45
+ player.makeFavorite();
46
+
47
+ expect(song.persistFavoriteStatus).toHaveBeenCalledWith(true);
48
+ });
49
+
50
+ //demonstrates use of expected exceptions
51
+ describe("#resume", function() {
52
+ it("should throw an exception if song is already playing", function() {
53
+ player.play(song);
54
+
55
+ expect(function() {
56
+ player.resume();
57
+ }).toThrowError("song is already playing");
58
+ });
59
+ });
60
+ });
@@ -0,0 +1,15 @@
1
+ beforeEach(function () {
2
+ jasmine.addMatchers({
3
+ toBePlaying: function () {
4
+ return {
5
+ compare: function (actual, expected) {
6
+ var player = actual;
7
+
8
+ return {
9
+ pass: player.currentlyPlayingSong === expected && player.isPlaying
10
+ }
11
+ }
12
+ };
13
+ }
14
+ });
15
+ });
@@ -0,0 +1,24 @@
1
+ function Player() {
2
+ }
3
+ Player.prototype.play = function(song) {
4
+ this.currentlyPlayingSong = song;
5
+ this.isPlaying = true;
6
+ };
7
+
8
+ Player.prototype.pause = function() {
9
+ this.isPlaying = false;
10
+ };
11
+
12
+ Player.prototype.resume = function() {
13
+ if (this.isPlaying) {
14
+ throw new Error("song is already playing");
15
+ }
16
+
17
+ this.isPlaying = true;
18
+ };
19
+
20
+ Player.prototype.makeFavorite = function() {
21
+ this.currentlyPlayingSong.persistFavoriteStatus(true);
22
+ };
23
+
24
+ module.exports = Player;
@@ -0,0 +1,9 @@
1
+ function Song() {
2
+ }
3
+
4
+ Song.prototype.persistFavoriteStatus = function(value) {
5
+ // something complicated
6
+ throw new Error("not yet implemented");
7
+ };
8
+
9
+ module.exports = Song;