Mailspring/packages/client-app/docs/guides/WritingSpecs.html

1472 lines
41 KiB
HTML

<!DOCTYPE HTML>
<html lang="" >
<head>
<meta charset="UTF-8">
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>Writing Tests · Nylas Mail Plugin SDK</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="description" content="">
<meta name="generator" content="GitBook 3.2.2">
<link rel="stylesheet" href="../gitbook/style.css">
<link rel="stylesheet" href="../gitbook/gitbook-plugin-search/search.css">
<link rel="stylesheet" href="../gitbook/gitbook-plugin-anchors/plugin.css">
<link rel="stylesheet" href="../gitbook/gitbook-plugin-highlight/website.css">
<link rel="stylesheet" href="../styles/website.css">
<meta name="HandheldFriendly" content="true"/>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="apple-touch-icon-precomposed" sizes="152x152" href="../gitbook/images/apple-touch-icon-precomposed-152.png">
<link rel="shortcut icon" href="../gitbook/images/favicon.ico" type="image/x-icon">
<link rel="next" href="IntegrationTesting.html" />
<link rel="prev" href="ComposerExtensions.html" />
<link rel="shortcut icon" href='../img/favicon.png' type="image/x-icon">
</head>
<body>
<div class="book">
<div class="book-summary">
<div id="book-search-input" role="search">
<input type="text" placeholder="Type to search" />
</div>
<nav role="navigation">
<ul class="summary">
<li class="chapter " data-level="1.1" >
<span>
Nylas Mail SDK Guides
</span>
</li>
<li class="chapter " data-level="1.2" data-path="../">
<a href="../">
Introduction
</a>
</li>
<li class="chapter " data-level="1.3" data-path="GettingStarted.html">
<a href="GettingStarted.html">
Getting Started
</a>
</li>
<li class="chapter " data-level="1.4" data-path="GettingStarted-2.html">
<a href="GettingStarted-2.html">
Getting Started Part 2
</a>
</li>
<li class="chapter " data-level="1.5" data-path="PackageOverview.html">
<a href="PackageOverview.html">
Building a Package
</a>
</li>
<li class="chapter " data-level="1.6" data-path="InterfaceConcepts.html">
<a href="InterfaceConcepts.html">
Interface Concepts
</a>
</li>
<li class="chapter " data-level="1.7" data-path="React.html">
<a href="React.html">
UI Components
</a>
</li>
<li class="chapter " data-level="1.8" data-path="Architecture.html">
<a href="Architecture.html">
Application Architecture
</a>
</li>
<li class="chapter " data-level="1.9" data-path="Debugging.html">
<a href="Debugging.html">
Debugging Nylas Mail
</a>
</li>
<li class="chapter " data-level="1.10" data-path="Database.html">
<a href="Database.html">
Accessing the Database
</a>
</li>
<li class="chapter " data-level="1.11" data-path="ComposerExtensions.html">
<a href="ComposerExtensions.html">
Extending the Composer
</a>
</li>
<li class="chapter active" data-level="1.12" data-path="WritingSpecs.html">
<a href="WritingSpecs.html">
Writing Tests
</a>
</li>
<li class="chapter " data-level="1.13" data-path="IntegrationTesting.html">
<a href="IntegrationTesting.html">
Integration Testing
</a>
</li>
<li class="chapter " data-level="1.14" data-path="Windows.html">
<a href="Windows.html">
Developing on Windows
</a>
</li>
<li class="chapter " data-level="1.15" data-path="FAQ.html">
<a href="FAQ.html">
FAQ
</a>
</li>
<li class="header">Full Class Reference</li>
<li class="chapter " data-level="2.1" >
<span>
General
</span>
<ul class="articles">
<li class="chapter " data-level="2.1.1" data-path="../classes/Actions.html">
<a href="../classes/Actions.html">
Actions
</a>
</li>
<li class="chapter " data-level="2.1.2" data-path="../classes/BufferedProcess.html">
<a href="../classes/BufferedProcess.html">
BufferedProcess
</a>
</li>
<li class="chapter " data-level="2.1.3" data-path="../classes/ChangeFolderTask.html">
<a href="../classes/ChangeFolderTask.html">
ChangeFolderTask
</a>
</li>
<li class="chapter " data-level="2.1.4" data-path="../classes/ChangeLabelsTask.html">
<a href="../classes/ChangeLabelsTask.html">
ChangeLabelsTask
</a>
</li>
<li class="chapter " data-level="2.1.5" data-path="../classes/ChangeMailTask.html">
<a href="../classes/ChangeMailTask.html">
ChangeMailTask
</a>
</li>
<li class="chapter " data-level="2.1.6" data-path="../classes/Color.html">
<a href="../classes/Color.html">
Color
</a>
</li>
<li class="chapter " data-level="2.1.7" data-path="../classes/Config.html">
<a href="../classes/Config.html">
Config
</a>
</li>
<li class="chapter " data-level="2.1.8" data-path="../classes/Contenteditable.html">
<a href="../classes/Contenteditable.html">
Contenteditable
</a>
</li>
<li class="chapter " data-level="2.1.9" data-path="../classes/KeyCommandsRegion.html">
<a href="../classes/KeyCommandsRegion.html">
KeyCommandsRegion
</a>
</li>
<li class="chapter " data-level="2.1.10" data-path="../classes/NylasEnvConstructor.html">
<a href="../classes/NylasEnvConstructor.html">
NylasEnvConstructor
</a>
</li>
<li class="chapter " data-level="2.1.11" data-path="../classes/QueryResultSet.html">
<a href="../classes/QueryResultSet.html">
QueryResultSet
</a>
</li>
<li class="chapter " data-level="2.1.12" data-path="../classes/QuerySubscriptionPool.html">
<a href="../classes/QuerySubscriptionPool.html">
QuerySubscriptionPool
</a>
</li>
<li class="chapter " data-level="2.1.13" data-path="../classes/StyleManager.html">
<a href="../classes/StyleManager.html">
StyleManager
</a>
</li>
<li class="chapter " data-level="2.1.14" data-path="../classes/Task.html">
<a href="../classes/Task.html">
Task
</a>
</li>
<li class="chapter " data-level="2.1.15" data-path="../classes/TaskQueueStatusStore.html">
<a href="../classes/TaskQueueStatusStore.html">
TaskQueueStatusStore
</a>
</li>
<li class="chapter " data-level="2.1.16" data-path="../classes/ThemeManager.html">
<a href="../classes/ThemeManager.html">
ThemeManager
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="2.2" >
<span>
Component Kit
</span>
<ul class="articles">
<li class="chapter " data-level="2.2.1" data-path="../classes/EventedIFrame.html">
<a href="../classes/EventedIFrame.html">
EventedIFrame
</a>
</li>
<li class="chapter " data-level="2.2.2" data-path="../classes/Flexbox.html">
<a href="../classes/Flexbox.html">
Flexbox
</a>
</li>
<li class="chapter " data-level="2.2.3" data-path="../classes/InjectedComponent.html">
<a href="../classes/InjectedComponent.html">
InjectedComponent
</a>
</li>
<li class="chapter " data-level="2.2.4" data-path="../classes/InjectedComponentSet.html">
<a href="../classes/InjectedComponentSet.html">
InjectedComponentSet
</a>
</li>
<li class="chapter " data-level="2.2.5" data-path="../classes/Menu.html">
<a href="../classes/Menu.html">
Menu
</a>
</li>
<li class="chapter " data-level="2.2.6" data-path="../classes/MenuItem.html">
<a href="../classes/MenuItem.html">
MenuItem
</a>
</li>
<li class="chapter " data-level="2.2.7" data-path="../classes/MenuNameEmailItem.html">
<a href="../classes/MenuNameEmailItem.html">
MenuNameEmailItem
</a>
</li>
<li class="chapter " data-level="2.2.8" data-path="../classes/MultiselectActionBar.html">
<a href="../classes/MultiselectActionBar.html">
MultiselectActionBar
</a>
</li>
<li class="chapter " data-level="2.2.9" data-path="../classes/MultiselectList.html">
<a href="../classes/MultiselectList.html">
MultiselectList
</a>
</li>
<li class="chapter " data-level="2.2.10" data-path="../classes/ResizableRegion.html">
<a href="../classes/ResizableRegion.html">
ResizableRegion
</a>
</li>
<li class="chapter " data-level="2.2.11" data-path="../classes/RetinaImg.html">
<a href="../classes/RetinaImg.html">
RetinaImg
</a>
</li>
<li class="chapter " data-level="2.2.12" data-path="../classes/Spinner.html">
<a href="../classes/Spinner.html">
Spinner
</a>
</li>
<li class="chapter " data-level="2.2.13" data-path="../classes/UnsafeComponent.html">
<a href="../classes/UnsafeComponent.html">
UnsafeComponent
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="2.3" >
<span>
Extensions
</span>
<ul class="articles">
<li class="chapter " data-level="2.3.1" data-path="../classes/ComposerExtension.html">
<a href="../classes/ComposerExtension.html">
ComposerExtension
</a>
</li>
<li class="chapter " data-level="2.3.2" data-path="../classes/ContenteditableExtension.html">
<a href="../classes/ContenteditableExtension.html">
ContenteditableExtension
</a>
</li>
<li class="chapter " data-level="2.3.3" data-path="../classes/DraftStoreExtension.html">
<a href="../classes/DraftStoreExtension.html">
DraftStoreExtension
</a>
</li>
<li class="chapter " data-level="2.3.4" data-path="../classes/MessageStoreExtension.html">
<a href="../classes/MessageStoreExtension.html">
MessageStoreExtension
</a>
</li>
<li class="chapter " data-level="2.3.5" data-path="../classes/MessageViewExtension.html">
<a href="../classes/MessageViewExtension.html">
MessageViewExtension
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="2.4" >
<span>
Models
</span>
<ul class="articles">
<li class="chapter " data-level="2.4.1" data-path="../classes/Contact.html">
<a href="../classes/Contact.html">
Contact
</a>
</li>
<li class="chapter " data-level="2.4.2" data-path="../classes/Message.html">
<a href="../classes/Message.html">
Message
</a>
</li>
<li class="chapter " data-level="2.4.3" data-path="../classes/Model.html">
<a href="../classes/Model.html">
Model
</a>
</li>
<li class="chapter " data-level="2.4.4" data-path="../classes/Thread.html">
<a href="../classes/Thread.html">
Thread
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="2.5" >
<span>
Stores
</span>
<ul class="articles">
<li class="chapter " data-level="2.5.1" data-path="../classes/AccountStore.html">
<a href="../classes/AccountStore.html">
AccountStore
</a>
</li>
<li class="chapter " data-level="2.5.2" data-path="../classes/ComponentRegistry.html">
<a href="../classes/ComponentRegistry.html">
ComponentRegistry
</a>
</li>
<li class="chapter " data-level="2.5.3" data-path="../classes/ContactStore.html">
<a href="../classes/ContactStore.html">
ContactStore
</a>
</li>
<li class="chapter " data-level="2.5.4" data-path="../classes/FocusedContentStore.html">
<a href="../classes/FocusedContentStore.html">
FocusedContentStore
</a>
</li>
<li class="chapter " data-level="2.5.5" data-path="../classes/TaskQueue.html">
<a href="../classes/TaskQueue.html">
TaskQueue
</a>
</li>
<li class="chapter " data-level="2.5.6" data-path="../classes/WorkspaceStore.html">
<a href="../classes/WorkspaceStore.html">
WorkspaceStore
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="2.6" >
<span>
Database
</span>
<ul class="articles">
<li class="chapter " data-level="2.6.1" data-path="../classes/Attribute.html">
<a href="../classes/Attribute.html">
Attribute
</a>
</li>
<li class="chapter " data-level="2.6.2" data-path="../classes/AttributeBoolean.html">
<a href="../classes/AttributeBoolean.html">
AttributeBoolean
</a>
</li>
<li class="chapter " data-level="2.6.3" data-path="../classes/AttributeCollection.html">
<a href="../classes/AttributeCollection.html">
AttributeCollection
</a>
</li>
<li class="chapter " data-level="2.6.4" data-path="../classes/AttributeDateTime.html">
<a href="../classes/AttributeDateTime.html">
AttributeDateTime
</a>
</li>
<li class="chapter " data-level="2.6.5" data-path="../classes/AttributeJoinedData.html">
<a href="../classes/AttributeJoinedData.html">
AttributeJoinedData
</a>
</li>
<li class="chapter " data-level="2.6.6" data-path="../classes/AttributeNumber.html">
<a href="../classes/AttributeNumber.html">
AttributeNumber
</a>
</li>
<li class="chapter " data-level="2.6.7" data-path="../classes/AttributeObject.html">
<a href="../classes/AttributeObject.html">
AttributeObject
</a>
</li>
<li class="chapter " data-level="2.6.8" data-path="../classes/AttributeServerId.html">
<a href="../classes/AttributeServerId.html">
AttributeServerId
</a>
</li>
<li class="chapter " data-level="2.6.9" data-path="../classes/AttributeString.html">
<a href="../classes/AttributeString.html">
AttributeString
</a>
</li>
<li class="chapter " data-level="2.6.10" data-path="../classes/DatabaseStore.html">
<a href="../classes/DatabaseStore.html">
DatabaseStore
</a>
</li>
<li class="chapter " data-level="2.6.11" data-path="../classes/Matcher.html">
<a href="../classes/Matcher.html">
Matcher
</a>
</li>
<li class="chapter " data-level="2.6.12" data-path="../classes/ModelQuery.html">
<a href="../classes/ModelQuery.html">
ModelQuery
</a>
</li>
<li class="chapter " data-level="2.6.13" data-path="../classes/SortOrder.html">
<a href="../classes/SortOrder.html">
SortOrder
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="2.7" >
<span>
Drafts
</span>
<ul class="articles">
<li class="chapter " data-level="2.7.1" data-path="../classes/DraftChangeSet.html">
<a href="../classes/DraftChangeSet.html">
DraftChangeSet
</a>
</li>
<li class="chapter " data-level="2.7.2" data-path="../classes/DraftEditingSession.html">
<a href="../classes/DraftEditingSession.html">
DraftEditingSession
</a>
</li>
<li class="chapter " data-level="2.7.3" data-path="../classes/DraftStore.html">
<a href="../classes/DraftStore.html">
DraftStore
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="2.8" >
<span>
NylasEnv
</span>
<ul class="articles">
<li class="chapter " data-level="2.8.1" data-path="../classes/PackageManager.html">
<a href="../classes/PackageManager.html">
PackageManager
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="2.9" >
<span>
Atom
</span>
</li>
<li class="divider"></li>
<li>
<a href="https://www.gitbook.com" target="blank" class="gitbook-link">
Published with GitBook
</a>
</li>
</ul>
</nav>
</div>
<div class="book-body">
<div class="body-inner">
<div class="book-header" role="navigation">
<!-- Title -->
<h1>
<i class="fa fa-circle-o-notch fa-spin"></i>
<a href=".." >Writing Tests</a>
</h1>
</div>
<div class="page-wrapper" tabindex="-1" role="main">
<div class="page-inner">
<div id="book-search-results">
<div class="search-noresults">
<section class="normal markdown-section">
<h1 id="writing-specs"><a name="writing-specs" class="plugin-anchor" href="#writing-specs"><i class="fa fa-link" aria-hidden="true"></i></a>Writing Specs</h1>
<p>Nylas uses <a href="http://jasmine.github.io/1.3/introduction.html" target="_blank">Jasmine</a> as its spec framework. As a package developer, you can write specs using Jasmine 1.3 and get some quick wins. Jasmine specs can be run in Nylas Mail directly from the Developer menu, and the test environment provides you with helpful stubs. You can also require your own test framework, or use Jasmine for integration tests and your own framework for your existing business logic.</p>
<p>This documentation describes using <a href="http://jasmine.github.io/1.3/introduction.html" target="_blank">Jasmine 1.3</a> to write specs for a Nylas package.</p>
<h3 id="running-specs"><a name="running-specs" class="plugin-anchor" href="#running-specs"><i class="fa fa-link" aria-hidden="true"></i></a>Running Specs</h3>
<p>You can run your package specs from <code>Developer &gt; Run Plugin Specs...</code>. Once you&apos;ve opened the spec window, you can see output and re-run your specs by clicking <code>Reload Specs</code>.</p>
<h3 id="writing-specs"><a name="writing-specs" class="plugin-anchor" href="#writing-specs"><i class="fa fa-link" aria-hidden="true"></i></a>Writing Specs</h3>
<p>To create specs, place <code>js</code>, <code>coffee</code>, or <code>cjsx</code> files in the <code>spec</code> directory of your package. Spec files must end with the <code>-spec</code> suffix.</p>
<p>Here&apos;s an annotated look at a typical Jasmine spec:</p>
<pre><code class="lang-coffee"><span class="hljs-comment"># The `describe` method takes two arguments, a description and a function. If the description</span>
<span class="hljs-comment"># explains a behavior it typically begins with `when`; if it is more like a unit test it begins</span>
<span class="hljs-comment"># with the method name.</span>
describe <span class="hljs-string">&quot;when a test is written&quot;</span>, <span class="hljs-function">-&gt;</span>
<span class="hljs-comment"># The `it` method also takes two arguments, a description and a function. Try and make the</span>
<span class="hljs-comment"># description flow with the `it` method. For example, a description of `this should work`</span>
<span class="hljs-comment"># doesn&apos;t read well as `it this should work`. But a description of `should work` sounds</span>
<span class="hljs-comment"># great as `it should work`.</span>
it <span class="hljs-string">&quot;has some expectations that should pass&quot;</span>, <span class="hljs-function">-&gt;</span>
<span class="hljs-comment"># The best way to learn about expectations is to read the Jasmine documentation:</span>
<span class="hljs-comment"># http://jasmine.github.io/1.3/introduction.html#section-Expectations</span>
<span class="hljs-comment"># Below is a simple example.</span>
expect(<span class="hljs-string">&quot;apples&quot;</span>).toEqual(<span class="hljs-string">&quot;apples&quot;</span>)
expect(<span class="hljs-string">&quot;oranges&quot;</span>).<span class="hljs-keyword">not</span>.toEqual(<span class="hljs-string">&quot;apples&quot;</span>)
describe <span class="hljs-string">&quot;Editor::moveUp&quot;</span>, <span class="hljs-function">-&gt;</span>
...
</code></pre>
<h4 id="asynchronous-spcs"><a name="asynchronous-spcs" class="plugin-anchor" href="#asynchronous-spcs"><i class="fa fa-link" aria-hidden="true"></i></a>Asynchronous Spcs</h4>
<p>Writing Asynchronous specs can be tricky at first, but a combination of spec helpers can make things easy. Here are a few quick examples:</p>
<h5 id="promises"><a name="promises" class="plugin-anchor" href="#promises"><i class="fa fa-link" aria-hidden="true"></i></a>Promises</h5>
<p>You can use the global <code>waitsForPromise</code> function to make sure that the test does not complete until the returned promise has finished, and run your expectations in a chained promise.</p>
<pre><code class="lang-coffee"> describe <span class="hljs-string">&quot;when requesting a Draft Session&quot;</span>, <span class="hljs-function">-&gt;</span>
it <span class="hljs-string">&quot;a session with the correct ID is returned&quot;</span>, <span class="hljs-function">-&gt;</span>
waitsForPromise -&gt;
DraftStore.sessionForLocalId(<span class="hljs-string">&apos;123&apos;</span>).<span class="hljs-keyword">then</span> (session) -&gt;
expect(session.id).toBe(<span class="hljs-string">&apos;123&apos;</span>)
</code></pre>
<p>This method can be used in the <code>describe</code>, <code>it</code>, <code>beforeEach</code> and <code>afterEach</code> functions.</p>
<pre><code class="lang-coffee">describe <span class="hljs-string">&quot;when we open a file&quot;</span>, <span class="hljs-function">-&gt;</span>
beforeEach -&gt;
waitsForPromise -&gt;
NylasEnv.workspace.open <span class="hljs-string">&apos;c.coffee&apos;</span>
it <span class="hljs-string">&quot;should be opened in an editor&quot;</span>, <span class="hljs-function">-&gt;</span>
expect(NylasEnv.workspace.getActiveTextEditor().getPath()).toContain <span class="hljs-string">&apos;c.coffee&apos;</span>
</code></pre>
<p>If you need to wait for multiple promises use a new <code>waitsForPromise</code> function for each promise. (Caution: Without <code>beforeEach</code> this example will fail!)</p>
<pre><code class="lang-coffee">describe <span class="hljs-string">&quot;waiting for the packages to load&quot;</span>, <span class="hljs-function">-&gt;</span>
beforeEach -&gt;
waitsForPromise -&gt;
NylasEnv.workspace.open(<span class="hljs-string">&apos;sample.js&apos;</span>)
waitsForPromise -&gt;
NylasEnv.packages.activatePackage(<span class="hljs-string">&apos;tabs&apos;</span>)
waitsForPromise -&gt;
NylasEnv.packages.activatePackage(<span class="hljs-string">&apos;tree-view&apos;</span>)
it <span class="hljs-string">&apos;should have waited long enough&apos;</span>, <span class="hljs-function">-&gt;</span>
expect(NylasEnv.packages.isPackageActive(<span class="hljs-string">&apos;tabs&apos;</span>)).toBe <span class="hljs-literal">true</span>
expect(NylasEnv.packages.isPackageActive(<span class="hljs-string">&apos;tree-view&apos;</span>)).toBe <span class="hljs-literal">true</span>
</code></pre>
<h4 id="asynchronous-functions-with-callbacks"><a name="asynchronous-functions-with-callbacks" class="plugin-anchor" href="#asynchronous-functions-with-callbacks"><i class="fa fa-link" aria-hidden="true"></i></a>Asynchronous functions with callbacks</h4>
<p>Specs for asynchronous functions can be done using the <code>waitsFor</code> and <code>runs</code> functions. A simple example.</p>
<pre><code class="lang-coffee">describe <span class="hljs-string">&quot;fs.readdir(path, cb)&quot;</span>, <span class="hljs-function">-&gt;</span>
it <span class="hljs-string">&quot;is async&quot;</span>, <span class="hljs-function">-&gt;</span>
spy = jasmine.createSpy(<span class="hljs-string">&apos;fs.readdirSpy&apos;</span>)
fs.readdir(<span class="hljs-string">&apos;/tmp/example&apos;</span>, spy)
waitsFor -&gt;
spy.callCount &gt; <span class="hljs-number">0</span>
runs -&gt;
exp = [<span class="hljs-literal">null</span>, [<span class="hljs-string">&apos;example.coffee&apos;</span>]]
expect(spy.mostRecentCall.args).toEqual exp
expect(spy).toHaveBeenCalledWith(<span class="hljs-literal">null</span>, [<span class="hljs-string">&apos;example.coffee&apos;</span>])
</code></pre>
<p>For a more detailed documentation on asynchronous tests please visit the <a href="http://jasmine.github.io/1.3/introduction.html#section-Asynchronous_Support" target="_blank">Jasmine documentation</a>.</p>
<h4 id="tips-for-debugging-specs"><a name="tips-for-debugging-specs" class="plugin-anchor" href="#tips-for-debugging-specs"><i class="fa fa-link" aria-hidden="true"></i></a>Tips for Debugging Specs</h4>
<p>To run a limited subset of specs use the <code>fdescribe</code> or <code>fit</code> methods. You can use those to focus a single spec or several specs. In the example above, focusing an individual spec looks like this:</p>
<pre><code class="lang-coffee">describe <span class="hljs-string">&quot;when a test is written&quot;</span>, <span class="hljs-function">-&gt;</span>
fit <span class="hljs-string">&quot;has some expectations that should pass&quot;</span>, <span class="hljs-function">-&gt;</span>
expect(<span class="hljs-string">&quot;apples&quot;</span>).toEqual(<span class="hljs-string">&quot;apples&quot;</span>)
expect(<span class="hljs-string">&quot;oranges&quot;</span>).<span class="hljs-keyword">not</span>.toEqual(<span class="hljs-string">&quot;apples&quot;</span>)
</code></pre>
</section>
</div>
<div class="search-results">
<div class="has-results">
<h1 class="search-results-title"><span class='search-results-count'></span> results matching "<span class='search-query'></span>"</h1>
<ul class="search-results-list"></ul>
</div>
<div class="no-results">
<h1 class="search-results-title">No results matching "<span class='search-query'></span>"</h1>
</div>
</div>
</div>
</div>
</div>
</div>
<a href="ComposerExtensions.html" class="navigation navigation-prev " aria-label="Previous page: Extending the Composer">
<i class="fa fa-angle-left"></i>
</a>
<a href="IntegrationTesting.html" class="navigation navigation-next " aria-label="Next page: Integration Testing">
<i class="fa fa-angle-right"></i>
</a>
</div>
<script>
var gitbook = gitbook || [];
gitbook.push(function() {
gitbook.page.hasChanged({"page":{"title":"Writing Tests","level":"1.12","depth":1,"next":{"title":"Integration Testing","level":"1.13","depth":1,"path":"guides/IntegrationTesting.md","ref":"guides/IntegrationTesting.md","articles":[]},"previous":{"title":"Extending the Composer","level":"1.11","depth":1,"path":"guides/ComposerExtensions.md","ref":"guides/ComposerExtensions.md","articles":[]},"dir":"ltr"},"config":{"plugins":["search","lunr","-fontsettings","-sharing","anchors","github","editlink","favicon"],"root":"./docs_src","styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"pluginsConfig":{"editlink":{"label":"Edit This Page","multilingual":false,"base":"https://github.com/nylas/nylas-mail-docs/tree/master"},"github":{"url":"https://github.com/nylas/nylas-mail-docs"},"favicon":{"shortcut":"/img/favicon.png"},"search":{},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"anchors":{},"highlight":{},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"theme":"default","pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"variables":{},"title":"Nylas Mail Plugin SDK","links":{"sharing":{"facebook":false,"twitter":false}},"gitbook":"3.2.2"},"file":{"path":"guides/WritingSpecs.md","mtime":"2017-01-30T09:55:21.000Z","type":"markdown"},"gitbook":{"version":"3.2.2","time":"2017-01-30T10:28:53.038Z"},"basePath":"..","book":{"language":""}});
});
</script>
</div>
<script src="../gitbook/gitbook.js"></script>
<script src="../gitbook/theme.js"></script>
<script src="../gitbook/gitbook-plugin-search/search-engine.js"></script>
<script src="../gitbook/gitbook-plugin-search/search.js"></script>
<script src="../gitbook/gitbook-plugin-lunr/lunr.min.js"></script>
<script src="../gitbook/gitbook-plugin-lunr/search-lunr.js"></script>
<script src="../gitbook/gitbook-plugin-github/plugin.js"></script>
<script src="../gitbook/gitbook-plugin-editlink/plugin.js"></script>
</body>
</html>