-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathunit-testing-javascript.html
More file actions
207 lines (162 loc) · 50.3 KB
/
unit-testing-javascript.html
File metadata and controls
207 lines (162 loc) · 50.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>JavsScript - Unit Testing Javascript</title>
<meta name="generator" content="VuePress 1.8.2">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
<meta name="description" content="Unit Testing Promises with Mocha, Sinon, Chai and Proxyquire, Basic Assertion">
<meta property="og:site_name" content="DevTut">
<meta property="og:title" content="JavsScript - Unit Testing Javascript">
<meta property="og:description" content="Unit Testing Promises with Mocha, Sinon, Chai and Proxyquire, Basic Assertion">
<meta property="og:type" content="article">
<meta property="og:url" content="/javascript/unit-testing-javascript.html">
<meta property="og:image" content="/logo.png">
<meta name="twitter:title" content="JavsScript - Unit Testing Javascript">
<meta name="twitter:description" content="Unit Testing Promises with Mocha, Sinon, Chai and Proxyquire, Basic Assertion">
<meta name="twitter:url" content="/javascript/unit-testing-javascript.html">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="/logo.png">
<meta name="theme-color" content="#ffffff">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="msapplication-TileImage" content="/mstile-150x150.png">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="google-site-verification" content="76_rKXgwMVIjd-axJC_1zPV9OS4mEjvtgjYOWVkAdnQ">
<link rel="preload" href="/assets/css/0.styles.60619e34.css" as="style"><link rel="preload" href="/assets/js/app.1779e102.js" as="script"><link rel="preload" href="/assets/js/3.2cfa8016.js" as="script"><link rel="preload" href="/assets/js/1796.02097aae.js" as="script">
<link rel="stylesheet" href="/assets/css/0.styles.60619e34.css">
</head>
<body>
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">DevTut</span></a> <div class="links"><form id="search-form" role="search" class="algolia-search-wrapper search-box"><input id="algolia-search-input" class="search-query"></form> <nav class="nav-links can-hide"> <a href="https://github.com/devtut/generate" target="_blank" rel="noopener noreferrer" class="repo-link">
GitHub
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"> <a href="https://github.com/devtut/generate" target="_blank" rel="noopener noreferrer" class="repo-link">
GitHub
<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav> <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>JavaScript</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/javascript/" aria-current="page" class="sidebar-link">Disclaimer</a></li><li><a href="/javascript/getting-started-with-javascript.html" class="sidebar-link">Getting started with JavaScript</a></li><li><a href="/javascript/javascript-variables.html" class="sidebar-link">JavaScript Variables</a></li><li><a href="/javascript/built-in-constants.html" class="sidebar-link">Built-in Constants</a></li><li><a href="/javascript/comments.html" class="sidebar-link">Comments</a></li><li><a href="/javascript/console.html" class="sidebar-link">Console</a></li><li><a href="/javascript/datatypes-in-javascript.html" class="sidebar-link">Datatypes in Javascript</a></li><li><a href="/javascript/strings.html" class="sidebar-link">Strings</a></li><li><a href="/javascript/date.html" class="sidebar-link">Date</a></li><li><a href="/javascript/date-comparison.html" class="sidebar-link">Date Comparison</a></li><li><a href="/javascript/comparison-operations.html" class="sidebar-link">Comparison Operations</a></li><li><a href="/javascript/conditions.html" class="sidebar-link">Conditions</a></li><li><a href="/javascript/arrays.html" class="sidebar-link">Arrays</a></li><li><a href="/javascript/objects.html" class="sidebar-link">Objects</a></li><li><a href="/javascript/arithmetic-math.html" class="sidebar-link">Arithmetic (Math)</a></li><li><a href="/javascript/bitwise-operators.html" class="sidebar-link">Bitwise operators</a></li><li><a href="/javascript/constructor-functions.html" class="sidebar-link">Constructor functions</a></li><li><a href="/javascript/declarations-and-assignments.html" class="sidebar-link">Declarations and Assignments</a></li><li><a href="/javascript/loops.html" class="sidebar-link">Loops</a></li><li><a href="/javascript/functions.html" class="sidebar-link">Functions</a></li><li><a href="/javascript/functional-javascript.html" class="sidebar-link">Functional JavaScript</a></li><li><a href="/javascript/prototypes-objects.html" class="sidebar-link">Prototypes, objects</a></li><li><a href="/javascript/classes.html" class="sidebar-link">Classes</a></li><li><a href="/javascript/namespacing.html" class="sidebar-link">Namespacing</a></li><li><a href="/javascript/context-this.html" class="sidebar-link">Context (this)</a></li><li><a href="/javascript/setters-and-getters.html" class="sidebar-link">Setters and Getters</a></li><li><a href="/javascript/events.html" class="sidebar-link">Events</a></li><li><a href="/javascript/inheritance.html" class="sidebar-link">Inheritance</a></li><li><a href="/javascript/method-chaining.html" class="sidebar-link">Method Chaining</a></li><li><a href="/javascript/callbacks.html" class="sidebar-link">Callbacks</a></li><li><a href="/javascript/intervals-and-timeouts.html" class="sidebar-link">Intervals and Timeouts</a></li><li><a href="/javascript/regular-expressions.html" class="sidebar-link">Regular expressions</a></li><li><a href="/javascript/cookies.html" class="sidebar-link">Cookies</a></li><li><a href="/javascript/web-storage.html" class="sidebar-link">Web Storage</a></li><li><a href="/javascript/data-attributes.html" class="sidebar-link">Data attributes</a></li><li><a href="/javascript/json.html" class="sidebar-link">JSON</a></li><li><a href="/javascript/ajax.html" class="sidebar-link">AJAX</a></li><li><a href="/javascript/enumerations.html" class="sidebar-link">Enumerations</a></li><li><a href="/javascript/map.html" class="sidebar-link">Map</a></li><li><a href="/javascript/timestamps.html" class="sidebar-link">Timestamps</a></li><li><a href="/javascript/unary-operators.html" class="sidebar-link">Unary Operators</a></li><li><a href="/javascript/generators.html" class="sidebar-link">Generators</a></li><li><a href="/javascript/promises.html" class="sidebar-link">Promises</a></li><li><a href="/javascript/set.html" class="sidebar-link">Set</a></li><li><a href="/javascript/modals-prompts.html" class="sidebar-link">Modals - Prompts</a></li><li><a href="/javascript/execcommand-and-contenteditable.html" class="sidebar-link">execCommand and contenteditable</a></li><li><a href="/javascript/history.html" class="sidebar-link">History</a></li><li><a href="/javascript/navigator-object.html" class="sidebar-link">Navigator Object</a></li><li><a href="/javascript/bom-browser-object-model.html" class="sidebar-link">BOM (Browser Object Model)</a></li><li><a href="/javascript/the-event-loop.html" class="sidebar-link">The Event Loop</a></li><li><a href="/javascript/strict-mode.html" class="sidebar-link">Strict mode</a></li><li><a href="/javascript/custom-elements.html" class="sidebar-link">Custom Elements</a></li><li><a href="/javascript/data-manipulation.html" class="sidebar-link">Data Manipulation</a></li><li><a href="/javascript/binary-data.html" class="sidebar-link">Binary Data</a></li><li><a href="/javascript/template-literals.html" class="sidebar-link">Template Literals</a></li><li><a href="/javascript/fetch.html" class="sidebar-link">Fetch</a></li><li><a href="/javascript/scope.html" class="sidebar-link">Scope</a></li><li><a href="/javascript/modules.html" class="sidebar-link">Modules</a></li><li><a href="/javascript/screen.html" class="sidebar-link">Screen</a></li><li><a href="/javascript/variable-coercion-conversion.html" class="sidebar-link">Variable coercion/conversion</a></li><li><a href="/javascript/destructuring-assignment.html" class="sidebar-link">Destructuring assignment</a></li><li><a href="/javascript/websockets.html" class="sidebar-link">WebSockets</a></li><li><a href="/javascript/arrow-functions.html" class="sidebar-link">Arrow Functions</a></li><li><a href="/javascript/workers.html" class="sidebar-link">Workers</a></li><li><a href="/javascript/requestanimationframe.html" class="sidebar-link">requestAnimationFrame</a></li><li><a href="/javascript/creational-design-patterns.html" class="sidebar-link">Creational Design Patterns</a></li><li><a href="/javascript/detecting-browser.html" class="sidebar-link">Detecting browser</a></li><li><a href="/javascript/symbols.html" class="sidebar-link">Symbols</a></li><li><a href="/javascript/transpiling.html" class="sidebar-link">Transpiling</a></li><li><a href="/javascript/automatic-semicolon-insertion-asi.html" class="sidebar-link">Automatic Semicolon Insertion - ASI</a></li><li><a href="/javascript/localization.html" class="sidebar-link">Localization</a></li><li><a href="/javascript/geolocation.html" class="sidebar-link">Geolocation</a></li><li><a href="/javascript/indexeddb.html" class="sidebar-link">IndexedDB</a></li><li><a href="/javascript/modularization-techniques.html" class="sidebar-link">Modularization Techniques</a></li><li><a href="/javascript/proxy.html" class="sidebar-link">Proxy</a></li><li><a href="/javascript/postmessage-and-messageevent.html" class="sidebar-link">.postMessage() and MessageEvent</a></li><li><a href="/javascript/weakmap.html" class="sidebar-link">WeakMap</a></li><li><a href="/javascript/weakset.html" class="sidebar-link">WeakSet</a></li><li><a href="/javascript/escape-sequences.html" class="sidebar-link">Escape Sequences</a></li><li><a href="/javascript/behavioral-design-patterns.html" class="sidebar-link">Behavioral Design Patterns</a></li><li><a href="/javascript/server-sent-events.html" class="sidebar-link">Server-sent events</a></li><li><a href="/javascript/async-functions-async-await.html" class="sidebar-link">Async functions (async/await)</a></li><li><a href="/javascript/async-iterators.html" class="sidebar-link">Async Iterators</a></li><li><a href="/javascript/how-to-make-iterator-usable-inside-async-callback-function.html" class="sidebar-link">How to make iterator usable inside async callback function</a></li><li><a href="/javascript/tail-call-optimization.html" class="sidebar-link">Tail Call Optimization</a></li><li><a href="/javascript/bitwise-operators-real-world-examples-snippets.html" class="sidebar-link">Bitwise Operators - Real World Examples (snippets)</a></li><li><a href="/javascript/tilde.html" class="sidebar-link">Tilde ~</a></li><li><a href="/javascript/using-javascript-to-get-set-css-custom-variables.html" class="sidebar-link">Using javascript to get/set CSS custom variables</a></li><li><a href="/javascript/selection-api.html" class="sidebar-link">Selection API</a></li><li><a href="/javascript/file-api-blobs-and-filereaders.html" class="sidebar-link">File API, Blobs and FileReaders</a></li><li><a href="/javascript/notifications-api.html" class="sidebar-link">Notifications API</a></li><li><a href="/javascript/vibration-api.html" class="sidebar-link">Vibration API</a></li><li><a href="/javascript/battery-status-api.html" class="sidebar-link">Battery Status API</a></li><li><a href="/javascript/fluent-api.html" class="sidebar-link">Fluent API</a></li><li><a href="/javascript/web-cryptography-api.html" class="sidebar-link">Web Cryptography API</a></li><li><a href="/javascript/security-issues.html" class="sidebar-link">Security issues</a></li><li><a href="/javascript/same-origin-policy-cross-origin-communication.html" class="sidebar-link">Same Origin Policy & Cross-Origin Communication</a></li><li><a href="/javascript/error-handling.html" class="sidebar-link">Error Handling</a></li><li><a href="/javascript/global-error-handling-in-browsers.html" class="sidebar-link">Global error handling in browsers</a></li><li><a href="/javascript/debugging.html" class="sidebar-link">Debugging</a></li><li><a href="/javascript/unit-testing-javascript.html" aria-current="page" class="active sidebar-link">Unit Testing Javascript</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/javascript/unit-testing-javascript.html#unit-testing-promises-with-mocha-sinon-chai-and-proxyquire" class="sidebar-link">Unit Testing Promises with Mocha, Sinon, Chai and Proxyquire</a></li><li class="sidebar-sub-header"><a href="/javascript/unit-testing-javascript.html#basic-assertion" class="sidebar-link">Basic Assertion</a></li></ul></li><li><a href="/javascript/evaluating-javascript.html" class="sidebar-link">Evaluating JavaScript</a></li><li><a href="/javascript/linters-ensuring-code-quality.html" class="sidebar-link">Linters - Ensuring code quality</a></li><li><a href="/javascript/anti-patterns.html" class="sidebar-link">Anti-patterns</a></li><li><a href="/javascript/performance-tips.html" class="sidebar-link">Performance Tips</a></li><li><a href="/javascript/memory-efficiency.html" class="sidebar-link">Memory efficiency</a></li><li><a href="/javascript/reserved-keywords.html" class="sidebar-link">Reserved Keywords</a></li><li><a href="/javascript/contributors.html" class="sidebar-link">The Contributors</a></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="unit-testing-javascript"><a href="#unit-testing-javascript" class="header-anchor">#</a> Unit Testing Javascript</h1> <h2 id="unit-testing-promises-with-mocha-sinon-chai-and-proxyquire"><a href="#unit-testing-promises-with-mocha-sinon-chai-and-proxyquire" class="header-anchor">#</a> Unit Testing Promises with Mocha, Sinon, Chai and Proxyquire</h2> <p>Here we have a simple class to be tested that returns a <code>Promise</code> based on the results of an external <code>ResponseProcessor</code> that takes time to execute.</p> <p>For simplicty we'll assume that the <code>processResponse</code> method won't ever fail.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> <span class="token punctuation">{</span>processResponse<span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'../utils/response_processor'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">ping</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span> _reject</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> response <span class="token operator">=</span> <span class="token function">processResponse</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">resolve</span><span class="token punctuation">(</span>response<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> ping<span class="token punctuation">;</span>
</code></pre></div><p>To test this we can leverage the following tools.</p> <ol><li><a href="https://mochajs.org" target="_blank" rel="noopener noreferrer"><code>mocha</code><span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="http://chaijs.com" target="_blank" rel="noopener noreferrer"><code>chai</code><span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="http://sinonjs.org" target="_blank" rel="noopener noreferrer"><code>sinon</code><span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://github.com/thlorenz/proxyquire" target="_blank" rel="noopener noreferrer"><code>proxyquire</code><span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://github.com/domenic/chai-as-promised" target="_blank" rel="noopener noreferrer"><code>chai-as-promised</code><span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ol> <p>I use the following <code>test</code> script in my <code>package.json</code> file.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token string">"test"</span><span class="token operator">:</span> <span class="token string">"NODE_ENV=test mocha --compilers js:babel-core/register --require ./test/unit/test_helper.js --recursive test/**/*_spec.js"</span>
</code></pre></div><p>This allows me to use <code>es6</code> syntax. It references a <code>test_helper</code> that will look like</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> chai <span class="token keyword">from</span> <span class="token string">'chai'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> sinon <span class="token keyword">from</span> <span class="token string">'sinon'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> sinonChai <span class="token keyword">from</span> <span class="token string">'sinon-chai'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> chaiAsPromised <span class="token keyword">from</span> <span class="token string">'chai-as-promised'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> sinonStubPromise <span class="token keyword">from</span> <span class="token string">'sinon-stub-promise'</span><span class="token punctuation">;</span>
chai<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>sinonChai<span class="token punctuation">)</span><span class="token punctuation">;</span>
chai<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>chaiAsPromised<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">sinonStubPromise</span><span class="token punctuation">(</span>sinon<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p><code>Proxyquire</code> allows us to inject our own stub in the place of the external <code>ResponseProcessor</code>. We can then use <code>sinon</code> to spy on that stub's methods. We use the extensions to <code>chai</code> that <code>chai-as-promised</code> injects to check that the <code>ping()</code> method's promise is <code>fullfilled</code>, and that it <code>eventually</code> returns the required response.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> <span class="token punctuation">{</span>expect<span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'chai'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> sinon <span class="token keyword">from</span> <span class="token string">'sinon'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> proxyquire <span class="token keyword">from</span> <span class="token string">'proxyquire'</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> formattingStub <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token function-variable function">wrapResponse</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">let</span> ping <span class="token operator">=</span> <span class="token function">proxyquire</span><span class="token punctuation">(</span><span class="token string">'../../../src/api/ping'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
<span class="token string">'../utils/formatting'</span><span class="token operator">:</span> formattingStub
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">'ping'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> wrapResponseSpy<span class="token punctuation">,</span> pingResult<span class="token punctuation">;</span>
<span class="token keyword">const</span> response <span class="token operator">=</span> <span class="token string">'some response'</span><span class="token punctuation">;</span>
<span class="token function">beforeEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
wrapResponseSpy <span class="token operator">=</span> sinon<span class="token punctuation">.</span><span class="token function">stub</span><span class="token punctuation">(</span>formattingStub<span class="token punctuation">,</span> <span class="token string">'wrapResponse'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">returns</span><span class="token punctuation">(</span>response<span class="token punctuation">)</span><span class="token punctuation">;</span>
pingResult <span class="token operator">=</span> <span class="token function">ping</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token function">afterEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
formattingStub<span class="token punctuation">.</span>wrapResponse<span class="token punctuation">.</span><span class="token function">restore</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token function">it</span><span class="token punctuation">(</span><span class="token string">'returns a fullfilled promise'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token function">expect</span><span class="token punctuation">(</span>pingResult<span class="token punctuation">)</span><span class="token punctuation">.</span>to<span class="token punctuation">.</span>be<span class="token punctuation">.</span>fulfilled<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token function">it</span><span class="token punctuation">(</span><span class="token string">'eventually returns the correct response'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token function">expect</span><span class="token punctuation">(</span>pingResult<span class="token punctuation">)</span><span class="token punctuation">.</span>to<span class="token punctuation">.</span>eventually<span class="token punctuation">.</span><span class="token function">equal</span><span class="token punctuation">(</span>response<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>Now instead let's assume you wish to test something that uses the response from <code>ping</code>.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> <span class="token punctuation">{</span>ping<span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'./ping'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> <span class="token function-variable function">pingWrapper</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
ping<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">response</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token comment">// do something with the response</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> pingWrapper<span class="token punctuation">;</span>
</code></pre></div><p>To test the <code>pingWrapper</code> we leverage</p> <ol><li><a href="http://sinonjs.org" target="_blank" rel="noopener noreferrer"><code>sinon</code><span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://github.com/thlorenz/proxyquire" target="_blank" rel="noopener noreferrer"><code>proxyquire</code><span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li> <li><a href="https://github.com/substantial/sinon-stub-promise" target="_blank" rel="noopener noreferrer"><code>sinon-stub-promise</code><span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ol> <p>As before, <code>Proxyquire</code> allows us to inject our own stub in the place of the external dependency, in this case the <code>ping</code> method we tested previously. We can then use <code>sinon</code> to spy on that stub's methods and leverage <code>sinon-stub-promise</code> to allow us to <code>returnsPromise</code>. This promise can then be resolved or rejected as we wish in the test, in order to test the wrapper's response to that.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">import</span> <span class="token punctuation">{</span>expect<span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'chai'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> sinon <span class="token keyword">from</span> <span class="token string">'sinon'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> proxyquire <span class="token keyword">from</span> <span class="token string">'proxyquire'</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> pingStub <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token function-variable function">ping</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> pingWrapper <span class="token operator">=</span> <span class="token function">proxyquire</span><span class="token punctuation">(</span><span class="token string">'../src/pingWrapper'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
<span class="token string">'./ping'</span><span class="token operator">:</span> pingStub
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">'pingWrapper'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">let</span> pingSpy<span class="token punctuation">;</span>
<span class="token keyword">const</span> response <span class="token operator">=</span> <span class="token string">'some response'</span><span class="token punctuation">;</span>
<span class="token function">beforeEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
pingSpy <span class="token operator">=</span> sinon<span class="token punctuation">.</span><span class="token function">stub</span><span class="token punctuation">(</span>pingStub<span class="token punctuation">,</span> <span class="token string">'ping'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">returnsPromise</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
pingSpy<span class="token punctuation">.</span><span class="token function">resolves</span><span class="token punctuation">(</span>response<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">pingWrapper</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">afterEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
pingStub<span class="token punctuation">.</span>wrapResponse<span class="token punctuation">.</span><span class="token function">restore</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">it</span><span class="token punctuation">(</span><span class="token string">'wraps the ping'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token function">expect</span><span class="token punctuation">(</span>pingSpy<span class="token punctuation">)</span><span class="token punctuation">.</span>to<span class="token punctuation">.</span>have<span class="token punctuation">.</span>been<span class="token punctuation">.</span><span class="token function">calledWith</span><span class="token punctuation">(</span>response<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><h2 id="basic-assertion"><a href="#basic-assertion" class="header-anchor">#</a> Basic Assertion</h2> <p>At its most basic level, Unit Testing in any language provides assertions against some known or expected output.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">assert</span><span class="token punctuation">(</span> <span class="token parameter">outcome<span class="token punctuation">,</span> description</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">var</span> passFail <span class="token operator">=</span> outcome <span class="token operator">?</span> <span class="token string">'pass'</span> <span class="token operator">:</span> <span class="token string">'fail'</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>passFail<span class="token punctuation">,</span> <span class="token string">': '</span><span class="token punctuation">,</span> description<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> outcome<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre></div><p>The popular assertion method above shows us one quick and easy way to assert a value in most web browsers and interpreters like Node.js with virtually any version of ECMAScript.</p> <p>A good unit test is designed to test a discreet unit of code; usually a function.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">add</span><span class="token punctuation">(</span><span class="token parameter">num1<span class="token punctuation">,</span> num2</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> num1 <span class="token operator">+</span> num2<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">var</span> result <span class="token operator">=</span> <span class="token function">add</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assert</span><span class="token punctuation">(</span> result <span class="token operator">==</span> <span class="token number">24</span><span class="token punctuation">,</span> <span class="token string">'add(5, 20) should return 25...'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>In the example above, the return value from the function <code>add(x, y)</code> or <code>5 + 20</code> is clearly <code>25</code>, so our assertion of <code>24</code> should fail, and the assert method will log a "fail" line.</p> <p>If we simply modify our expected assertion outcome, the test will succeed and the resulting output would look something like this.</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">assert</span><span class="token punctuation">(</span> result <span class="token operator">==</span> <span class="token number">25</span><span class="token punctuation">,</span> <span class="token string">'add(5, 20) should return 25...'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console output<span class="token operator">:</span>
<span class="token operator">></span> pass<span class="token operator">:</span> should <span class="token keyword">return</span> <span class="token number">25.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
</code></pre></div><p>This simple assertion can assure that in many different cases, your "add" function will always return the expected result and requires no additional frameworks or libraries to work.</p> <p>A more rigorous set of assertions would look like this (using <code>var result = add(x,y)</code> for each assertion):</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">assert</span><span class="token punctuation">(</span> result <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token string">'add(0, 0) should return 0...'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assert</span><span class="token punctuation">(</span> result <span class="token operator">==</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'add(0, -1) should return -1...'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assert</span><span class="token punctuation">(</span> result <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'add(0, 1) should return 1...'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>And console output would be this:</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token operator">></span> pass<span class="token operator">:</span> should <span class="token keyword">return</span> <span class="token number">0.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token operator">></span> pass<span class="token operator">:</span> should <span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token operator">></span> pass<span class="token operator">:</span> should <span class="token keyword">return</span> <span class="token number">1.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
</code></pre></div><p>We can now safely say that <strong><code>add(x,y)</code>… should return the sum of two integers</strong>. We can roll these up into something like this:</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">test__addsIntegers</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// expect a number of passed assertions</span>
<span class="token keyword">var</span> passed <span class="token operator">=</span> <span class="token number">3</span><span class="token punctuation">;</span>
<span class="token comment">// number of assertions to be reduced and added as Booleans</span>
<span class="token keyword">var</span> assertions <span class="token operator">=</span> <span class="token punctuation">[</span>
<span class="token function">assert</span><span class="token punctuation">(</span> <span class="token function">add</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token string">'add(0, 0) should return 0...'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token function">assert</span><span class="token punctuation">(</span> <span class="token function">add</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'add(0, -1) should return -1...'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token function">assert</span><span class="token punctuation">(</span> <span class="token function">add</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'add(0, 1) should return 1...'</span><span class="token punctuation">)</span>
<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">reduce</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">previousValue<span class="token punctuation">,</span> currentValue</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
<span class="token keyword">return</span> previousValue <span class="token operator">+</span> current<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>assertions <span class="token operator">===</span> passed<span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"add(x,y)... did return the sum of two integers"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"add(x,y)... does not reliably return the sum of two integers"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/devtut/generate/edit/master/docs/javascript/unit-testing-javascript.md" target="_blank" rel="noopener noreferrer">Edit this page on GitHub</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <!----></footer> <div class="page-nav"><p class="inner"><span class="prev">
←
<a href="/javascript/debugging.html" class="prev">
Debugging
</a></span> <span class="next"><a href="/javascript/evaluating-javascript.html">
Evaluating JavaScript
</a>
→
</span></p></div> </main></div><div class="global-ui"><!----></div></div>
<script src="/assets/js/app.1779e102.js" defer></script><script src="/assets/js/3.2cfa8016.js" defer></script><script src="/assets/js/1796.02097aae.js" defer></script>
</body>
</html>