feat(spec): add config dir to integration specs

Summary:
- You can now pass `--config-dir-path=/some/custom/path` to `./N1.sh`
- `main.coffee` cleaned up a bit. A lot of unused params from legacy Atom
  stuff were still being used
- Integration specs now set the config dir before booting.
- New spec to check for the autoupdater in the app and make sure it's
  pointing at the right place.

Test Plan: script/grunt run-integration-tests

Reviewers: juan, bengotow

Reviewed By: bengotow

Differential Revision: https://phab.nylas.com/D2331
This commit is contained in:
Evan Morikawa 2015-12-10 10:52:20 -05:00
parent 7000a1c71b
commit 4014b4e187
49 changed files with 1726 additions and 360 deletions

1
.gitignore vendored
View file

@ -20,6 +20,7 @@ yoursway-create-dmg
*nylas-private-*
/_site
/.sass-cache
.integration-test-config
!spec/fixtures/packages/package-with-incompatible-native-module/node_modules

View file

@ -4,13 +4,13 @@ compiler:
matrix:
include:
- os: linux
env: NODE_VERSION=0.10 CC=gcc-4.8 CXX=g++-4.8 NYLAS_HOME=/home/travis/.nylas
env: NODE_VERSION=0.10 CC=gcc-4.8 CXX=g++-4.8
- os: linux
env: NODE_VERSION=0.12 CC=gcc-4.8 CXX=g++-4.8 NYLAS_HOME=/home/travis/.nylas
env: NODE_VERSION=0.12 CC=gcc-4.8 CXX=g++-4.8
- os: linux
env: NODE_VERSION=4.2 CC=gcc-4.8 CXX=g++-4.8 NYLAS_HOME=/home/travis/.nylas PUBLISH_BUILD=true
env: NODE_VERSION=4.2 CC=gcc-4.8 CXX=g++-4.8 PUBLISH_BUILD=true
- os: linux
env: NODE_VERSION=5 CC=gcc-4.8 CXX=g++-4.8 NYLAS_HOME=/home/travis/.nylas
env: NODE_VERSION=5 CC=gcc-4.8 CXX=g++-4.8
- os: osx
env: NODE_VERSION=0.10
- os: osx

View file

@ -27,6 +27,7 @@
"event-kit": "^1.0.2",
"fs-plus": "^2.3.2",
"fstream": "0.1.24",
"fswin": "2.15.1031",
"grim": "1.5.0",
"guid": "0.0.10",
"immutable": "3.7.5",

View file

@ -12,7 +12,6 @@ global.Promise = require 'bluebird'
try
require '../src/window'
NylasEnvConstructor = require '../src/nylas-env'
NylasEnvConstructor.configDirPath = fs.absolute('~/.nylas-spec')
window.NylasEnv = window.atom = NylasEnvConstructor.loadOrCreate()
global.Promise.longStackTraces() if NylasEnv.inDevMode()

View file

@ -1,53 +0,0 @@
import {N1Launcher} from './integration-helper'
describe('Nylas Prod Bootup Tests', function() {
beforeAll((done)=>{
// Boot in dev mode with no arguments
this.app = new N1Launcher(["--dev"]);
this.app.mainWindowReady().finally(done);
});
afterAll((done)=> {
if (this.app && this.app.isRunning()) {
this.app.stop().then(done);
} else {
done()
}
});
it("has main window visible", (done)=> {
this.app.client.isWindowVisible()
.then((result)=>{ expect(result).toBe(true) })
.finally(done)
});
it("has main window focused", (done)=> {
this.app.client.isWindowFocused()
.then((result)=>{ expect(result).toBe(true) })
.finally(done)
});
it("isn't minimized", (done)=> {
this.app.client.isWindowMinimized()
.then((result)=>{ expect(result).toBe(false) })
.finally(done)
});
it("doesn't have the dev tools open", (done)=> {
this.app.client.isWindowDevToolsOpened()
.then((result)=>{ expect(result).toBe(false) })
.finally(done)
});
it("has width", (done)=> {
this.app.client.getWindowWidth()
.then((result)=>{ expect(result).toBeGreaterThan(0) })
.finally(done)
});
it("has height", (done)=> {
this.app.client.getWindowHeight()
.then((result)=>{ expect(result).toBeGreaterThan(0) })
.finally(done)
});
});

View file

@ -0,0 +1,51 @@
import N1Launcher from './helpers/n1-launcher'
import {currentConfig} from './helpers/config-helper'
import {assertBasicWindow} from './helpers/shared-assertions'
describe('Clean app boot', function() {
beforeAll((done)=>{
// Boot in dev mode with no arguments
this.app = new N1Launcher(["--dev"], N1Launcher.CLEAR_CONFIG);
this.app.onboardingWindowReady().finally(done);
});
afterAll((done)=> {
if (this.app && this.app.isRunning()) {
this.app.stop().finally(done);
} else {
done()
}
});
it("has the autoupdater pointing to the correct url when there's no config loaded", () => {
this.app.client.execute(()=>{
app = require('remote').getGlobal('application')
return {
platform: process.platform,
arch: process.arch,
feedUrl: app.autoUpdateManager.feedURL
}
}).then(({value})=>{
base = "https://edgehill.nylas.com/update-check"
config = currentConfig()
// NOTE: Since there's no loaded config yet (we haven't logged in),
// a random id will be sent with no emails
url = `${base}?platform=${value.platform}&arch=${value.arch}&version=${config.version}`
expect(value.feedUrl.indexOf(url)).toBe(0)
})
});
assertBasicWindow.call(this)
it("has width", (done)=> {
this.app.client.getWindowWidth()
.then((result)=>{ expect(result).toBeGreaterThan(0) })
.finally(done)
});
it("has height", (done)=> {
this.app.client.getWindowHeight()
.then((result)=>{ expect(result).toBeGreaterThan(0) })
.finally(done)
});
});

View file

@ -1,5 +1,5 @@
import {N1Launcher} from './integration-helper'
import ContenteditableTestHarness from './contenteditable-test-harness.es6'
import N1Launcher from './helpers/n1-launcher'
import ContenteditableTestHarness from './helpers/contenteditable-test-harness.es6'
describe('Contenteditable Integration Spec', function() {
beforeAll((done)=>{

View file

@ -0,0 +1,25 @@
"*":
updateIdentity: "00000000-0000-0000-0000-000000000000"
env: "production"
nylas:
accounts: [
{
client_id: "local-00000000-0000"
server_id: "fake-server-id"
object: "account"
account_id: "accountid1234"
name: "Nylas Test"
provider: "eas"
email_address: "test@nylas.com"
organization_unit: "folder"
id: "accountid1234"
}
]
currentAccountIndex: 1
accountTokens:
accountid1234: "fake-token"
accountid1234:
cursor: "fake-cursor"
core:
workspace:
mode: "split"

View file

@ -0,0 +1 @@
{"version":1,"windowDimensions":{"x":11,"y":22,"width":1234,"height":789,"maximized":true},"packageStates":{"attachments":{},"composer":{},"composer-signature":{},"composer-spellcheck":{},"events":{},"message-autoload-images":{},"message-list":{},"notification-mailto":{},"notifications":{},"nylas-private-analytics":{},"sidebar-fullcontact":{},"tooltip":{},"undo-redo":{}}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,87 @@
[
{
"account_id": "1nqpfzd0l7djj2xhega8i3iyc",
"bcc": [],
"body": "<div dir=\"ltr\">We had a great time this weekend!</div>",
"cc": [],
"date": 1443818787,
"events": [],
"files": [
{
"content_type": "image/jpeg",
"filename": "2015-09-19 13.27.43.jpg",
"id": "2yciz0fv6eki05e3tadq4r39n",
"size": 951329
},
{
"content_type": "image/jpeg",
"filename": "DSC00147.JPG",
"id": "x93vconbilqoks499kg4mjhm",
"size": 1287660
},
{
"content_type": "image/jpeg",
"filename": "DSC00148.JPG",
"id": "i8888ig7vdob2j6o2turz4dn",
"size": 1260993
},
{
"content_type": "image/jpeg",
"filename": "DSC00156.JPG",
"id": "4ufyb9bccvhdg75hh5jhmarf1",
"size": 948713
}
],
"from": [
{
"email": "nylanaut@gmail.com",
"name": "Benjamin Nylas"
}
],
"id": "4gn270rwbp2d005jhp8i1pqpl",
"labels": [
{
"display_name": "Inbox",
"id": "88i72euk07ody1d0c8m8c7qk7",
"name": "inbox"
},
{
"display_name": "All Mail",
"id": "er7ed7zo00k3itzn5f39hmlnr",
"name": "all"
},
{
"display_name": "Important",
"id": "cpimvyt4yhzgif0vxjytvafy4",
"name": "important"
},
{
"display_name": "Photos",
"id": "cpimvyt4yhzgif0vxjytvafy1",
"name": null
},
{
"display_name": "Nylas Team",
"id": "cpimvyt4yhzgif0vxjytzzzzz",
"name": null
}
],
"object": "message",
"reply_to": [],
"snippet": "We had a great time this weekend!",
"starred": true,
"subject": "Team Photos - Russian River Trip",
"thread_id": "3oaxnicxfbsjrn9lsc9ls03c8",
"to": [
{
"email": "ben@nylas.com",
"name": ""
},
{
"email": "matt.murdock@gmail.com",
"name": ""
}
],
"unread": false
}
]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,48 @@
[
{
"account_id": "1nqpfzd0l7djj2xhega8i3iyc",
"bcc": [],
"body": "<p>Hey there, we\u2019re just writing to let you know that you\u2019ve been automatically subscribed to a repository on GitHub.</p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;nylas/N1 created by emorikawa<br>&nbsp;&nbsp;&nbsp;&nbsp;The full-featured production version of N1<br>&nbsp;&nbsp;&nbsp;&nbsp;https://github.com/nylas/N1</p>\n<p>You\u2019ll receive notifications for all issues, pull requests, and comments that happen inside the repository. If you would like to stop watching this repository, you can manage your settings here:</p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;https://github.com/nylas/N1/subscription</p>\n<p>You can unwatch this repository immediately by clicking here:</p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;https://github.com/nylas/N1/unsubscribe_via_email/ACmlr4l1V2j_CJ3lA4XY4t_dz9t_WMm7ks5o3b1OgaJpZM4Cl_EK</p>\n<p>You were automatically subscribed because you\u2019ve been given push access to the repository.</p>\n<p>Thanks!</p>",
"cc": [],
"date": 1443743182,
"events": [],
"files": [],
"from": [
{
"email": "noreply@github.com",
"name": "GitHub"
}
],
"id": "21sssm6ixp8otdxttjdd60yag",
"labels": [
{
"display_name": "Inbox",
"id": "88i72euk07ody1d0c8m8c7qk7",
"name": "inbox"
},
{
"display_name": "All Mail",
"id": "er7ed7zo00k3itzn5f39hmlnr",
"name": "all"
},
{
"display_name": "Nylas Team",
"id": "cpimvyt4yhzgif0vxjytzzzzz",
"name": null
}
],
"object": "message",
"reply_to": [],
"snippet": "Hey there, we\u2019re just writing to let you know that you\u2019ve been automatically subscribed to a repository on GitHub. nylas/N1 created by emorikawa The full-featured production version of ",
"starred": false,
"subject": "[GitHub] Subscribed to nylas/N1 notifications",
"thread_id": "7mxu9jo8wdpkzav2uukv17xlf",
"to": [
{
"email": "matt.murdock@gmail.com",
"name": ""
}
],
"unread": false
}
]

View file

@ -0,0 +1,67 @@
[
{
"account_id": "1nqpfzd0l7djj2xhega8i3iyc",
"bcc": [],
"body": "<div dir=\"ltr\"><div class=\"gmail_quote\"><div>She is so cute!</div></div></div>",
"cc": [],
"date": 1443817302,
"events": [],
"files": [
{
"content_type": "image/jpeg",
"filename": "IMG_0119.JPG",
"id": "dc751g7p89zwtstsrq2g0c2mx",
"size": 465045
},
{
"content_type": "image/jpeg",
"filename": "IMG_0120.JPG",
"id": "dypphoivy3v09hfucxxg6qbio",
"size": 513108
},
{
"content_type": "image/jpeg",
"filename": "IMG_0121.JPG",
"id": "4778h9y5yy4khljbiabmzfilh",
"size": 514459
}
],
"from": [
{
"email": "nylanaut@gmail.com",
"name": "Nyla S."
}
],
"id": "50d9o70vcezbd2820moyzjc8c",
"labels": [
{
"display_name": "Important",
"id": "cpimvyt4yhzgif0vxjytvafy4",
"name": "important"
},
{
"display_name": "Inbox",
"id": "88i72euk07ody1d0c8m8c7qk7",
"name": "inbox"
},
{
"display_name": "All Mail",
"id": "er7ed7zo00k3itzn5f39hmlnr",
"name": "all"
}
],
"object": "message",
"reply_to": [],
"snippet": "She is so cute!",
"starred": false,
"subject": "My cat likes wine",
"thread_id": "8szbk9hudeak1jmzkfc7wr2x5",
"to": [
{
"email": "matt.murdock@gmail.com",
"name": ""
}
],
"unread": false
}
]

View file

@ -0,0 +1,165 @@
[
{
"account_id": "1nqpfzd0l7djj2xhega8i3iyc",
"bcc": [],
"body": "<div dir=\"ltr\">I see my house!</div><div class=\"gmail_extra\"><br><div class=\"gmail_quote\">On Fri, Oct 2, 2015 at 1:55 PM, Ben Bitdiddle <span dir=\"ltr\">&lt;<a href=\"mailto:matt.murdock@gmail.com\" target=\"_blank\">matt.murdock@gmail.com</a>&gt;</span> wrote:<br><blockquote class=\"gmail_quote\" style=\"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex\"><div dir=\"ltr\">That is epic.</div><div class=\"HOEnZb\"><div class=\"h5\"><div class=\"gmail_extra\"><br><div class=\"gmail_quote\">On Fri, Oct 2, 2015 at 1:54 PM, Ben Bitdiddle <span dir=\"ltr\">&lt;<a href=\"mailto:ben@nylas.com\" target=\"_blank\">ben@nylas.com</a>&gt;</span> wrote:<br><blockquote class=\"gmail_quote\" style=\"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex\">\n\n\n\n<div>\nFor those of you not here, you&#39;re missing out!\n<div><br>\n</div>\n<div>Only San Francisco has sunsets like this.</div>\n</div>\n\n</blockquote></div><br></div>\n</div></div></blockquote></div><br></div>",
"cc": [],
"date": 1443819336,
"events": [],
"files": [],
"from": [
{
"email": "nylanaut@gmail.com",
"name": "Nyla S."
}
],
"id": "1cl0z0aluk8lc36ggf76bla7j",
"labels": [
{
"display_name": "Important",
"id": "cpimvyt4yhzgif0vxjytvafy4",
"name": "important"
},
{
"display_name": "Inbox",
"id": "88i72euk07ody1d0c8m8c7qk7",
"name": "inbox"
},
{
"display_name": "All Mail",
"id": "er7ed7zo00k3itzn5f39hmlnr",
"name": "all"
}
],
"object": "message",
"reply_to": [],
"snippet": "I see my house! On Fri, Oct 2, 2015 at 1:55 PM, Ben Bitdiddle <matt.murdock@gmail.com> wrote: That is epic. On Fri, Oct 2, 2015 at 1:54 PM, Ben Bitdiddle <ben@nylas.com> wrote: For those of you n",
"starred": false,
"subject": "Re: Sunset on the roof",
"thread_id": "9ozbcu4wge7bpv6b8o2vo76g8",
"to": [
{
"email": "matt.murdock@gmail.com",
"name": "Ben Bitdiddle"
}
],
"unread": false
},
{
"account_id": "1nqpfzd0l7djj2xhega8i3iyc",
"bcc": [],
"body": "<div dir=\"ltr\">That is epic.</div><div class=\"gmail_extra\"><br><div class=\"gmail_quote\">On Fri, Oct 2, 2015 at 1:54 PM, Ben Bitdiddle <span dir=\"ltr\">&lt;<a href=\"mailto:ben@nylas.com\" target=\"_blank\">ben@nylas.com</a>&gt;</span> wrote:<br><blockquote class=\"gmail_quote\" style=\"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex\">\n\n\n\n<div>\nFor those of you not here, you&#39;re missing out!\n<div><br>\n</div>\n<div>Only San Francisco has sunsets like this.</div>\n</div>\n\n</blockquote></div><br></div>",
"cc": [
{
"email": "nylanaut@gmail.com",
"name": "Nyla S."
}
],
"date": 1443819324,
"events": [],
"files": [],
"from": [
{
"email": "matt.murdock@gmail.com",
"name": "Ben Bitdiddle"
}
],
"id": "bjp8wy7rm8dtltz4hc0f22209",
"labels": [
{
"display_name": "All Mail",
"id": "er7ed7zo00k3itzn5f39hmlnr",
"name": "all"
},
{
"display_name": "Sent Mail",
"id": "2j6ppmtwcwnedo56rzqsesty",
"name": "sent"
},
{
"display_name": "Important",
"id": "cpimvyt4yhzgif0vxjytvafy4",
"name": "important"
}
],
"object": "message",
"reply_to": [],
"snippet": "That is epic. On Fri, Oct 2, 2015 at 1:54 PM, Ben Bitdiddle <ben@nylas.com> wrote: For those of you not here, you're missing out! Only San Francisco has sunsets like this.",
"starred": false,
"subject": "Re: Sunset on the roof",
"thread_id": "9ozbcu4wge7bpv6b8o2vo76g8",
"to": [
{
"email": "ben@nylas.com",
"name": "Ben Bitdiddle"
}
],
"unread": true
},
{
"account_id": "1nqpfzd0l7djj2xhega8i3iyc",
"bcc": [],
"body": "<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=us-ascii\">\n</head>\n<body>\nFor those of you not here, you're missing out!\n<div><br>\n</div>\n<div>Only San Francisco has sunsets like this.</div>\n</body>\n</html>",
"cc": [
{
"email": "matt.murdock@gmail.com",
"name": "Ben Bitdiddle"
}
],
"date": 1443819282,
"events": [],
"files": [
{
"content_id": "AB1F96D93F07B14AB10E1B34D264CA0F@nylas.com",
"content_type": "image/jpeg",
"filename": "IMG_0112.JPG",
"id": "dsap6c1llryrmmnioy3s96sxf",
"size": 359605
},
{
"content_id": "EC9038D05158514FB4D8EA053D1D0B15@nylas.com",
"content_type": "image/jpeg",
"filename": "IMG_0113.JPG",
"id": "5l5awsc35ul7a8su2pq3jiz64",
"size": 1965621
}
],
"from": [
{
"email": "ben@nylas.com",
"name": "Ben Bitdiddle"
}
],
"id": "3lobjkxwk4ydo66it73vvjolw",
"labels": [
{
"display_name": "All Mail",
"id": "er7ed7zo00k3itzn5f39hmlnr",
"name": "all"
},
{
"display_name": "Inbox",
"id": "88i72euk07ody1d0c8m8c7qk7",
"name": "inbox"
},
{
"display_name": "Important",
"id": "cpimvyt4yhzgif0vxjytvafy4",
"name": "important"
}
],
"object": "message",
"reply_to": [],
"snippet": "For those of you not here, you're missing out! Only San Francisco has sunsets like this.",
"starred": false,
"subject": "Sunset on the roof",
"thread_id": "9ozbcu4wge7bpv6b8o2vo76g8",
"to": [
{
"email": "nylanaut@gmail.com",
"name": "Nyla S."
}
],
"unread": false
}
]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,191 @@
[
{
"account_id": "1nqpfzd0l7djj2xhega8i3iyc",
"bcc": [],
"body": "<head></head><body>Where are the Iceland photos?! \ud83d\udc11\ud83c\udf0b\ud83d\udc34\ud83d\udc26\ud83d\udc11</body>",
"cc": [],
"date": 1443842821,
"events": [],
"files": [],
"labels": [
{
"display_name": "Inbox",
"id": "88i72euk07ody1d0c8m8c7qk7",
"name": "inbox"
},
{
"display_name": "All Mail",
"id": "er7ed7zo00k3itzn5f39hmlnr",
"name": "all"
},
{
"display_name": "Important",
"id": "cpimvyt4yhzgif0vxjytvafy4",
"name": "important"
},
{
"display_name": "Photos",
"id": "cpimvyt4yhzgif0vxjytvafy1",
"name": null
},
{
"display_name": "Iceland",
"id": "cpimvyt4yhzgif0vxjytzzzzz",
"name": null
}
],
"from": [
{
"email": "nora@nylas.com",
"name": "Nora Goldman"
}
],
"id": "3rn37t6ybk6v1w4nyhleufu4f",
"object": "message",
"reply_to": [],
"snippet": "Where are the Iceland photos?! \ud83d\udc11\ud83c\udf0b\ud83d\udc34\ud83d\udc26\ud83d\udc11",
"starred": false,
"subject": "Iceland and all the \u00feings!!",
"thread_id": "arhpub0jn27hk7c3lj1zd5b39",
"to": [
{
"email": "evan@evanmorikawa.com",
"name": "Evan Morikawa"
},
{
"email": "lana@lingboli.com",
"name": "Lana Li"
}
],
"unread": false
},
{
"account_id": "1nqpfzd0l7djj2xhega8i3iyc",
"bcc": [],
"body": "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"><div dir=\"ltr\">Here's one! More coming soon.</div><blockquote class=\"gmail_quote\" style=\"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex\">\n\n\n\n<div>\nDo you have the Iceland photos? \ud83d\udc11\ud83c\udf0b\ud83d\udc34\ud83d\udc26\ud83d\udc11\n</div>\n\n</blockquote></div>",
"cc": [
{
"email": "lana@lingboli.com",
"name": "Lana Li"
}
],
"date": 1443842822,
"events": [],
"files": [
{
"content_type": "image/jpeg",
"filename": "111-IMG_6000.jpg",
"id": "1pznqhlxvxyjrmrs7vktai029",
"size": 8821534
}
],
"labels": [
{
"display_name": "Inbox",
"id": "88i72euk07ody1d0c8m8c7qk7",
"name": "inbox"
},
{
"display_name": "All Mail",
"id": "er7ed7zo00k3itzn5f39hmlnr",
"name": "all"
},
{
"display_name": "Important",
"id": "cpimvyt4yhzgif0vxjytvafy4",
"name": "important"
},
{
"display_name": "Photos",
"id": "cpimvyt4yhzgif0vxjytvafy1",
"name": null
},
{
"display_name": "Iceland",
"id": "cpimvyt4yhzgif0vxjytzzzzz",
"name": null
}
],
"from": [
{
"email": "evan@evanmorikawa.com",
"name": "Evan Morikawa"
}
],
"id": "5xrug792jvb9tsj1ig8edjduz",
"object": "message",
"reply_to": [],
"snippet": "Yeah! Here's one. More coming soon. On Sat, Oct 3, 2015 at 6:21 PM, Evan Morikawa <evan@evanmorikawa.com> wrote: Do you have the Iceland photos? \ud83d\udc11\ud83c\udf0b\ud83d\udc34\ud83d\udc26\ud83d\udc11",
"starred": false,
"subject": "Re: Iceland and all the \u00feings!!",
"thread_id": "arhpub0jn27hk7c3lj1zd5b39",
"to": [
{
"email": "nora@nylas.com",
"name": "Nora Goldman"
}
],
"unread": false
},
{
"account_id": "1nqpfzd0l7djj2xhega8i3iyc",
"bcc": [],
"body": "Wow! Iceland looks awesome. <blockquote><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"><div dir=\"ltr\">Here's one! More coming soon.</div><blockquote class=\"gmail_quote\" style=\"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex\">\n\n\n\n<div>\nDo you have the Iceland photos? \ud83d\udc11\ud83c\udf0b\ud83d\udc34\ud83d\udc26\ud83d\udc11\n</div>\n\n</blockquote></div></blockquote>",
"cc": [
{
"email": "lana@lingboli.com",
"name": "Lana Li"
}
],
"date": 1443999694,
"events": [],
"files": [],
"labels": [
{
"display_name": "Inbox",
"id": "88i72euk07ody1d0c8m8c7qk7",
"name": "inbox"
},
{
"display_name": "All Mail",
"id": "er7ed7zo00k3itzn5f39hmlnr",
"name": "all"
},
{
"display_name": "Important",
"id": "cpimvyt4yhzgif0vxjytvafy4",
"name": "important"
},
{
"display_name": "Photos",
"id": "cpimvyt4yhzgif0vxjytvafy1",
"name": null
},
{
"display_name": "Iceland",
"id": "cpimvyt4yhzgif0vxjytzzzzz",
"name": null
}
],
"from": [
{
"email": "nora@nylas.com",
"name": "Nora Goldman"
}
],
"id": "6xrug792jvb9tsj1ig8edjdua",
"object": "message",
"reply_to": [],
"snippet": "Wow! Iceland looks awesome. On Sat Oct 3, 2015 at 6:23 PM, Yeah! Here's one. More coming soon. On Sat, Oct 3, 2015 at 6:21 PM, Evan Morikawa <evan@evanmorikawa.com> wrote: Do you have the Iceland photos? \ud83d\udc11\ud83c\udf0b\ud83d\udc34\ud83d\udc26\ud83d\udc11",
"starred": false,
"subject": "Re: Iceland and all the \u00feings!!",
"thread_id": "arhpub0jn27hk7c3lj1zd5b39",
"to": [
{
"email": "evan@evanmorikawa.com",
"name": "Evan Morikawa"
}
],
"unread": false
}
]

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,56 @@
[
{
"account_id": "743w8dzcwkpc0rkfnxmo7y6rn",
"bcc": [],
"body": "<div dir=\"ltr\">Hi All!<div><br></div><div>Steffi and I were talking tonight about how it would be great to get everyone together for some sort of BBQ or picnic in Golden Gate Park this long weekend.</div><div><br></div><div>BBQ == if we can reserve a grill.&nbsp;</div><div>Picnic == if we can&#39;t get a grill.</div><div><br></div><div>Either way, <a href=\"http://sfrecpark.org/destination/golden-gate-park/ggp-helman-hollow-picnic-area/\" target=\"_blank\">Hellman&#39;s Hollow</a>&nbsp;is a great spot for us to congregate for this said event.&nbsp;</div><div><br></div><div>Now, we just need to figure out what day people want to do this BBQ or Picnic thing (Sat? Sun? Mon?).&nbsp;</div><div><br></div><div>Please fill out the doodle: <a href=\"http://doodle.com/prbvazr6sdzcgnvm\" target=\"_blank\">http://doodle.com/prbvazr6sdzcgnvm</a></div><div><div><br></div><div>The sooner the better so we can call to try to reserve a grill.</div><span class=\"HOEnZb\"><font color=\"#888888\">-- <br><div><font color=\"#666666\" face=\"arial, helvetica, sans-serif\">Christie&nbsp;</font></div>\n</font></span></div></div>\n</div><br></div>",
"cc": [],
"date": 1443843359,
"events": [],
"files": [],
"from": [
{
"email": "christie@gmail.com",
"name": "Christie Zhao"
}
],
"id": "1ftt9yiowviw5ywge7fm4m2ow",
"labels": [
{
"display_name": "Important",
"id": "cpimvyt4yhzgif0vxjytvafy4",
"name": "important"
},
{
"display_name": "Inbox",
"id": "88i72euk07ody1d0c8m8c7qk7",
"name": "inbox"
},
{
"display_name": "All Mail",
"id": "er7ed7zo00k3itzn5f39hmlnr",
"name": "all"
}
],
"object": "message",
"reply_to": [],
"starred": false,
"snippet": "Hi All! - Steffi and I were talking tonight about how it would be great to get everyone together for some sort of BBQ or picnic in Golden Gate Park this long weekend.",
"subject": "Labor Day (potential) BBQ or Picnic",
"thread_id": "czylw25z2q2y9zy93hl9hcv4k",
"to": [
{
"email": "nora@nylas.com",
"name": "Nora Goldman"
},
{
"email": "ben@gmail.com",
"name": "Ben"
},
{
"email": "kevin@nylas.com",
"name": "Kevin"
}
],
"unread": true
}
]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,27 @@
import fs from 'fs-plus'
import path from 'path'
import CSON from 'season'
var root = path.resolve(path.dirname(__dirname))
const DEFAULT_CONFIG_DIR = path.join(root, "fixtures", "default_test_config")
export const CONFIG_DIR_PATH = path.join(root, ".integration-test-config")
export const FAKE_DATA_PATH = path.join(root, "fixtures", "test_account_data")
export function setupDefaultConfig() {
if (fs.existsSync(CONFIG_DIR_PATH)) fs.removeSync(CONFIG_DIR_PATH);
fs.copySync(DEFAULT_CONFIG_DIR, CONFIG_DIR_PATH)
}
export function clearConfig() {
if (fs.existsSync(CONFIG_DIR_PATH)) fs.removeSync(CONFIG_DIR_PATH);
}
export function currentConfig(){
version = JSON.parse(fs.readFileSync(path.join(root, '..', 'package.json'))).version;
config = CSON.readFileSync(path.join(DEFAULT_CONFIG_DIR, 'config.cson'))["*"]
id = config.updateIdentity
email = config.nylas.accounts[0].email_address
return {id, email, version}
}

View file

@ -1,23 +1,45 @@
import path from 'path'
import {Application} from 'spectron';
import {clearConfig,
setupDefaultConfig,
FAKE_DATA_PATH,
CONFIG_DIR_PATH} from './config-helper';
export default class N1Launcher extends Application {
constructor(launchArgs = [], configOpts) {
if (configOpts === N1Launcher.CLEAR_CONFIG) {
clearConfig()
} else {
setupDefaultConfig()
}
class N1Launcher extends Application {
constructor(launchArgs = []) {
super({
path: N1Launcher.electronPath(),
args: [jasmine.NYLAS_ROOT_PATH].concat(N1Launcher.defaultNylasArgs()).concat(launchArgs)
})
}
onboardingWindowReady() {
return this.windowReady(N1Launcher.secondaryWindowLoadedMatcher)
}
mainWindowReady() {
return this.windowReady(N1Launcher.mainWindowMatcher)
return this.windowReady(N1Launcher.mainWindowLoadedMatcher).then(() => {
return this.client
.timeoutsAsyncScript(5000)
.executeAsync((FAKE_DATA_PATH, done) => {
$n.AccountStore._importFakeData(FAKE_DATA_PATH).then(done);
}, FAKE_DATA_PATH)
});
}
popoutComposerWindowReady() {
return this.windowReady(N1Launcher.mainWindowMatcher).then(() => {
return this.client.execute(()=>{
require('nylas-exports').Actions.composeNewBlankDraft();
})
return this.windowReady(N1Launcher.mainWindowLoadedMatcher).then(() => {
return this.client.execute((FAKE_DATA_PATH)=>{
$n.AccountStore._importFakeData(FAKE_DATA_PATH)
$n.Actions.composeNewBlankDraft();
}, FAKE_DATA_PATH)
}).then(()=>{
return N1Launcher.waitUntilMatchingWindowLoaded(this.client, N1Launcher.composerWindowMatcher).then((windowId)=>{
return this.client.window(windowId)
@ -26,16 +48,20 @@ class N1Launcher extends Application {
}
windowReady(matcher) {
// Wrap in a Bluebird promise so we have `.finally on the return`
return Promise.resolve(this.start().then(()=>{
return this.start().then(()=>{
return N1Launcher.waitUntilMatchingWindowLoaded(this.client, matcher).then((windowId)=>{
return this.client.window(windowId)
})
}));
});
}
static mainWindowMatcher(client) {
return client.isExisting(".main-window-loaded").then((exists)=>{
static secondaryWindowLoadedMatcher(client) {
// The last thing secondary windows do once they boot is call "show"
return client.isWindowVisible()
}
static mainWindowLoadedMatcher(client) {
return client.isExisting(".window-loaded").then((exists)=>{
if (exists) {return true} else {return false}
})
}
@ -53,7 +79,9 @@ class N1Launcher extends Application {
}
static defaultNylasArgs() {
return ["--enable-logging", `--resource-path=${jasmine.NYLAS_ROOT_PATH}`]
return ["--enable-logging",
`--resource-path=${jasmine.NYLAS_ROOT_PATH}`,
`--config-dir-path=${CONFIG_DIR_PATH}`]
}
static electronPath() {
@ -83,7 +111,7 @@ class N1Launcher extends Application {
static waitUntilMatchingWindowLoaded(client, matcher, lastCheck=0) {
var CHECK_EVERY = 500
return new Promise((resolve, reject) => {
client.windowHandles().then(({value}) => {
return client.windowHandles().then(({value}) => {
return Promise.mapSeries(value, (windowId)=>{
return N1Launcher.switchAndCheckForMatch(client, windowId, matcher)
})
@ -95,10 +123,12 @@ class N1Launcher extends Application {
var now = Date.now();
var delay = Math.max(CHECK_EVERY - (now - lastCheck), 0)
setTimeout(()=>{
N1Launcher.waitUntilMatchingWindowLoaded(client, matcher, now).then(resolve)
return N1Launcher.waitUntilMatchingWindowLoaded(client, matcher, now).then(resolve)
}, delay)
return null
}).catch((err) => {
console.error(err);
return null
});
});
}
@ -113,5 +143,4 @@ class N1Launcher extends Application {
})
}
}
module.exports = {N1Launcher}
N1Launcher.CLEAR_CONFIG = "CLEAR_CONFIG"

View file

@ -0,0 +1,25 @@
export function assertBasicWindow() {
it("has main window visible", (done)=> {
this.app.client.isWindowVisible()
.then((result)=>{ expect(result).toBe(true) })
.finally(done)
});
it("has main window focused", (done)=> {
this.app.client.isWindowFocused()
.then((result)=>{ expect(result).toBe(true) })
.finally(done)
});
it("isn't minimized", (done)=> {
this.app.client.isWindowMinimized()
.then((result)=>{ expect(result).toBe(false) })
.finally(done)
});
it("doesn't have the dev tools open", (done)=> {
this.app.client.isWindowDevToolsOpened()
.then((result)=>{ expect(result).toBe(false) })
.finally(done)
});
}

View file

@ -1,8 +1,8 @@
// argv[0] = node
// argv[1] = jasmine
// argv[2] = JASMINE_CONFIG_PATH=./config.json
// argv[2] = JASMINE_CONFIG_PATH=./jasmine/config.json
// argv[3] = NYLAS_ROOT_PATH=/path/to/nylas/root
var babelOptions = require('../static/babelrc.json');
var babelOptions = require('../../static/babelrc.json');
require('babel-core/register')(babelOptions);
var chalk = require('chalk')
@ -36,4 +36,3 @@ process.on("unhandledRejection", function(reason, promise) {
if (reason.stack) { console.errorColor(reason.stack); }
console.errorColor(promise);
});

View file

@ -4,6 +4,6 @@
"**/*-spec.{js,es6,es,jsx}"
],
"helpers": [
"bootstrap.js"
"jasmine/bootstrap.js"
]
}

View file

@ -0,0 +1,50 @@
import N1Launcher from './helpers/n1-launcher'
import {currentConfig} from './helpers/config-helper'
import {assertBasicWindow} from './helpers/shared-assertions'
describe('Logged in app boot', () => {
beforeAll((done)=>{
// Boot in dev mode with no arguments
this.app = new N1Launcher(["--dev"]);
this.app.mainWindowReady().finally(done);
});
afterAll((done)=> {
if (this.app && this.app.isRunning()) {
this.app.stop().finally(done);
} else {
done()
}
});
it("has the autoupdater pointing to the correct url", () => {
this.app.client.execute(()=>{
app = require('remote').getGlobal('application')
return {
platform: process.platform,
arch: process.arch,
feedUrl: app.autoUpdateManager.feedURL
}
}).then(({value})=>{
base = "https://edgehill.nylas.com/update-check"
config = currentConfig()
email = encodeURIComponent(config.email)
url = `${base}?platform=${value.platform}&arch=${value.arch}&version=${config.version}&id=${config.id}&emails=${email}`
expect(value.feedUrl).toEqual(url)
})
});
assertBasicWindow.call(this)
it("restored its width from file", (done)=> {
this.app.client.getWindowWidth()
.then((result)=>{ expect(result).toBe(1234) })
.finally(done)
});
it("restored its height from file", (done)=> {
this.app.client.getWindowHeight()
.then((result)=>{ expect(result).toBe(789) })
.finally(done)
});
});

View file

@ -6,7 +6,7 @@
"url": "https://github.com/nylas/N1.git"
},
"scripts": {
"test": "jasmine JASMINE_CONFIG_PATH=./config.json"
"test": "jasmine JASMINE_CONFIG_PATH=./jasmine/config.json"
},
"license": "GPL-3.0",
"dependencies": {

View file

@ -23,8 +23,6 @@ socketPath =
else
path.join(os.tmpdir(), 'edgehill.sock')
configDirPath = fs.absolute('~/.nylas')
# The application's singleton class.
#
# It's the entry point into the N1 application and maintains the global state
@ -42,7 +40,7 @@ class Application
# take a few seconds to trigger 'error' event, it could be a bug of node
# or electron, before it's fixed we check the existence of socketPath to
# speedup startup.
if (process.platform isnt 'win32' and not fs.existsSync socketPath) or options.test
if (process.platform isnt 'win32' and not fs.existsSync socketPath) or options.specMode
createApplication()
return
@ -62,8 +60,7 @@ class Application
exit: (status) -> app.exit(status)
constructor: (options) ->
{@resourcePath, @devResourcePath, @version, @devMode, test, @safeMode} = options
@specMode = test
{@resourcePath, @configDirPath, @version, @devMode, @specMode, @safeMode} = options
# Normalize to make sure drive letter case is consistent on Windows
@resourcePath = path.normalize(@resourcePath) if @resourcePath
@ -74,7 +71,7 @@ class Application
@nylasProtocolHandler = new NylasProtocolHandler(@resourcePath, @safeMode)
Config = require '../config'
@config = new Config({configDirPath, @resourcePath})
@config = new Config({@configDirPath, @resourcePath})
@config.load()
# Normally, you enter dev mode by passing the --dev command line flag.
@ -83,7 +80,7 @@ class Application
if @config.get('devMode')
@devMode = true
@windowManager = new WindowManager({@resourcePath, @config, @devMode, @safeMode})
@windowManager = new WindowManager({@resourcePath, @configDirPath, @config, @devMode, @safeMode})
@autoUpdateManager = new AutoUpdateManager(@version, @config, @specMode)
@applicationMenu = new ApplicationMenu(@version)
@_databasePhase = 'setup'
@ -95,8 +92,8 @@ class Application
@launchWithOptions(options)
# Opens a new window based on the options provided.
launchWithOptions: ({urlsToOpen, test, devMode, safeMode, specDirectory, specFilePattern, logFile, showSpecsInWindow}) ->
if test
launchWithOptions: ({urlsToOpen, specMode, devMode, safeMode, specDirectory, specFilePattern, logFile, showSpecsInWindow}) ->
if specMode
exitWhenDone = true
@runSpecs({exitWhenDone, showSpecsInWindow, @resourcePath, specDirectory, specFilePattern, logFile})
else
@ -176,9 +173,9 @@ class Application
@windowManager.ensureOnboardingWindow(welcome: true)
_deleteDatabase: (callback) ->
@deleteFileWithRetry path.join(configDirPath,'edgehill.db'), callback
@deleteFileWithRetry path.join(configDirPath,'edgehill.db-wal')
@deleteFileWithRetry path.join(configDirPath,'edgehill.db-shm')
@deleteFileWithRetry path.join(@configDirPath,'edgehill.db'), callback
@deleteFileWithRetry path.join(@configDirPath,'edgehill.db-wal')
@deleteFileWithRetry path.join(@configDirPath,'edgehill.db-shm')
databasePhase: ->
@_databasePhase
@ -219,7 +216,7 @@ class Application
@on 'application:run-package-specs', ->
dialog.showOpenDialog {
title: 'Choose a Package Directory'
defaultPath: configDirPath,
defaultPath: @configDirPath,
properties: ['openDirectory']
}, (filenames) =>
return if not filenames or filenames.length is 0
@ -486,11 +483,11 @@ class Application
resourcePath = @resourcePath
try
bootstrapScript = require.resolve(path.resolve(@devResourcePath, 'spec', 'spec-bootstrap'))
bootstrapScript = require.resolve(path.resolve(@resourcePath, 'spec', 'spec-bootstrap'))
catch error
bootstrapScript = require.resolve(path.resolve(__dirname, '..', '..', 'spec', 'spec-bootstrap'))
isSpec = true
devMode = true
safeMode ?= false
new NylasWindow({bootstrapScript, resourcePath, exitWhenDone, isSpec, devMode, specDirectory, specFilePattern, logFile, safeMode, showSpecsInWindow})
new NylasWindow({bootstrapScript, @configDirPath, resourcePath, exitWhenDone, isSpec, devMode, specDirectory, specFilePattern, logFile, safeMode, showSpecsInWindow})

View file

@ -7,51 +7,52 @@ process.on 'uncaughtException', (error={}) ->
{app} = require 'electron'
fs = require 'fs-plus'
path = require 'path'
optimist = require 'optimist'
mkdirp = require 'mkdirp'
start = ->
args = parseCommandLine()
global.errorLogger = setupErrorLogger(args)
setupNylasHome(args)
setupCompileCache()
configDirPath = setupConfigDir(args)
args.configDirPath = configDirPath
setupCompileCache(configDirPath)
return if handleStartupEventWithSquirrel()
# This prevents Win10 from showing dupe items in the taskbar
app.setAppUserModelId('com.squirrel.nylas.nylas')
addPathToOpen = (event, pathToOpen) ->
event.preventDefault()
args.pathsToOpen.push(pathToOpen)
addUrlToOpen = (event, urlToOpen) ->
event.preventDefault()
args.urlsToOpen.push(urlToOpen)
app.on 'open-file', addPathToOpen
app.on 'open-url', addUrlToOpen
app.on 'will-finish-launching', ->
setupCrashReporter()
app.on 'ready', ->
app.removeListener 'open-file', addPathToOpen
app.removeListener 'open-url', addUrlToOpen
Application = require path.join(args.resourcePath, 'src', 'browser', 'application')
Application.open(args)
console.log("App load time: #{Date.now() - global.shellStartTime}ms") unless args.test
console.log("App load time: #{Date.now() - global.shellStartTime}ms") unless args.specMode
setupNylasHome = ->
return if process.env.NYLAS_HOME
atomHome = path.join(app.getPath('home'), '.nylas')
process.env.NYLAS_HOME = atomHome
normalizeDriveLetterName = (filePath) ->
if process.platform is 'win32'
filePath.replace /^([a-z]):/, ([driveLetter]) -> driveLetter.toUpperCase() + ":"
setupConfigDir = (args) ->
# https://github.com/atom/atom/issues/8281
if args.specMode
defaultConfigDir = path.join(app.getPath('home'), '.nylas-spec')
else
filePath
defaultConfigDir = path.join(app.getPath('home'), '.nylas')
configDirPath = args.configDirPath ?
process.env.NYLAS_HOME ?
defaultConfigDir
mkdirp.sync(configDirPath)
if process.platform is 'win32'
fsWin=require('fswin')
fsWin.setAttributesSync(pathToFileOrDir, {IS_HIDDEN: true})
process.env.NYLAS_HOME = configDirPath
return configDirPath
handleStartupEventWithSquirrel = ->
return false unless process.platform is 'win32'
@ -59,52 +60,63 @@ handleStartupEventWithSquirrel = ->
squirrelCommand = process.argv[1]
SquirrelUpdate.handleStartupEvent(app, squirrelCommand)
setupCompileCache = ->
setupCompileCache = (configDirPath) ->
compileCache = require('../compile-cache')
compileCache.setHomeDirectory(process.env.NYLAS_HOME)
compileCache.setHomeDirectory(configDirPath)
setupErrorLogger = (args={}) ->
ErrorLogger = require '../error-logger'
return new ErrorLogger
inSpecMode: args.test
inSpecMode: args.specMode
inDevMode: args.devMode
resourcePath: args.resourcePath
setupCrashReporter = ->
# In the future, we may want to collect actual native crash reports,
# but for now let's not send them to GitHub
# crashReporter.start(productName: "N1", companyName: "Nylas")
declareOptions = (argv) ->
optimist = require 'optimist'
options = optimist(argv)
options.usage """
Nylas N1 v#{app.getVersion()}
Usage: n1 [options]
Run N1: The open source extensible email client
`n1 --dev` to start the client in dev mode.
`n1 --test` to run unit tests.
"""
options.alias('d', 'dev').boolean('d')
.describe('d', 'Run in development mode.')
options.alias('t', 'test').boolean('t')
.describe('t', 'Run the specified specs and exit with error code on failures.')
options.boolean('safe')
.describe('safe', 'Do not load packages from ~/.nylas/packages or ~/.nylas/dev/packages.')
options.alias('h', 'help').boolean('h')
.describe('h', 'Print this usage message.')
options.alias('l', 'log-file').string('l')
.describe('l', 'Log all test output to file.')
options.alias('c', 'config-dir-path').string('c')
.describe('c', 'Override the path to the N1 configuration directory')
options.alias('s', 'spec-directory').string('s')
.describe('s', 'Override the directory from which to run package specs')
options.alias('f', 'spec-file-pattern').string('f')
.describe('f', 'Override the default file regex to determine which tests should run (defaults to "-spec\.(coffee|js|jsx|cjsx|es6|es)$" )')
options.alias('v', 'version').boolean('v')
.describe('v', 'Print the version.')
return options
parseCommandLine = ->
version = app.getVersion()
options = optimist(process.argv[1..])
options.usage """
N1 v#{version}
Usage: n1 [options] [path ...]
One or more paths to files or folders to open may be specified.
File paths will open in the current window.
Folder paths will open in an existing window if that folder has already been
opened or a new window if it hasn't.
Environment Variables:
N1_PATH The path from which N1 loads source code in dev mode.
Defaults to `cwd`.
"""
options.alias('d', 'dev').boolean('d').describe('d', 'Run in development mode.')
options.alias('f', 'foreground').boolean('f').describe('f', 'Keep the browser process in the foreground.')
options.alias('h', 'help').boolean('h').describe('h', 'Print this usage message.')
options.alias('l', 'log-file').string('l').describe('l', 'Log all output to file.')
options.alias('n', 'new-window').boolean('n').describe('n', 'Open a new window.')
options.alias('r', 'resource-path').string('r').describe('r', 'Set the path to the N1 source directory and enable dev-mode.')
options.alias('s', 'spec-directory').string('s').describe('s', 'Set the directory from which to run package specs (default: N1\'s spec directory).')
options.boolean('safe').describe('safe', 'Do not load packages from ~/.nylas/packages or ~/.nylas/dev/packages.')
options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.')
options.alias('v', 'version').boolean('v').describe('v', 'Print the version.')
options.alias('w', 'wait').boolean('w').describe('w', 'Wait for window to be closed before returning.')
options = declareOptions(process.argv[1..])
args = options.argv
if args.help
@ -115,59 +127,24 @@ parseCommandLine = ->
process.stdout.write("#{version}\n")
process.exit(0)
executedFrom = args['executed-from']?.toString() ? process.cwd()
devMode = args['dev']
safeMode = args['safe']
pathsToOpen = args._
pathsToOpen = [executedFrom] if executedFrom and pathsToOpen.length is 0
urlsToOpen = []
test = args['test']
specDirectory = args['spec-directory']
newWindow = args['new-window']
pidToKillWhenClosed = args['pid'] if args['wait']
devMode = args['dev'] || args['test']
logFile = args['log-file']
specFilePattern = args['file-pattern']
devResourcePath = process.env.N1_PATH ? process.cwd()
specMode = args['test']
safeMode = args['safe']
configDirPath = args['config-dir-path']
specDirectory = args['spec-directory']
specFilePattern = args['spec-file-pattern']
showSpecsInWindow = specMode is "window"
showSpecsInWindow = false
resourcePath = path.resolve(args['resource-path'] ?
path.dirname(path.dirname(__dirname)))
if args['resource-path']
devMode = true
resourcePath = args['resource-path']
else
# Set resourcePath based on the specDirectory if running specs on N1 core
if specDirectory?
packageDirectoryPath = path.resolve(specDirectory, '..')
packageManifestPath = path.join(packageDirectoryPath, 'package.json')
if fs.statSyncNoException(packageManifestPath)
try
packageManifest = JSON.parse(fs.readFileSync(packageManifestPath))
resourcePath = packageDirectoryPath if packageManifest.name is 'edgehill'
else
# EDGEHILL_CORE: if test is given a name, assume that's the package we
# want to test.
if test and toString.call(test) is "[object String]"
if test is "core"
specDirectory = path.join(devResourcePath, "spec")
else if test is "window"
specDirectory = path.join(devResourcePath, "spec")
showSpecsInWindow = true
else
specDirectory = path.resolve(path.join(devResourcePath, "internal_packages", test))
urlsToOpen = []
devMode = true if test
resourcePath ?= devResourcePath if devMode
unless fs.statSyncNoException(resourcePath)
resourcePath = path.dirname(path.dirname(__dirname))
# On Yosemite the $PATH is not inherited by the "open" command, so we have to
# explicitly pass it by command line, see http://git.io/YC8_Ew.
# On Yosemite the $PATH is not inherited by the "open" command, so we
# have to explicitly pass it by command line, see http://git.io/YC8_Ew.
process.env.PATH = args['path-environment'] if args['path-environment']
resourcePath = normalizeDriveLetterName(resourcePath)
devResourcePath = normalizeDriveLetterName(devResourcePath)
{resourcePath, pathsToOpen, urlsToOpen, executedFrom, test, version, pidToKillWhenClosed, devMode, safeMode, newWindow, specDirectory, showSpecsInWindow, logFile, specFilePattern}
return {version, devMode, logFile, specMode, safeMode, configDirPath, specDirectory, specFilePattern, showSpecsInWindow, resourcePath, urlsToOpen}
start()

View file

@ -1,6 +1,6 @@
// Generated by CoffeeScript 1.9.2
// Generated by CoffeeScript 1.10.0
(function() {
var app, fs, handleStartupEventWithSquirrel, normalizeDriveLetterName, optimist, parseCommandLine, path, setupCompileCache, setupCrashReporter, setupErrorLogger, setupNylasHome, start;
var app, declareOptions, fs, handleStartupEventWithSquirrel, mkdirp, parseCommandLine, path, setupCompileCache, setupConfigDir, setupErrorLogger, start;
global.shellStartTime = Date.now();
@ -16,68 +16,58 @@
}
});
app = require('app');
app = require('electron').app;
fs = require('fs-plus');
path = require('path');
optimist = require('optimist');
mkdirp = require('mkdirp');
start = function() {
var addPathToOpen, addUrlToOpen, args;
var addUrlToOpen, args, configDirPath;
args = parseCommandLine();
global.errorLogger = setupErrorLogger(args);
setupNylasHome(args);
setupCompileCache();
configDirPath = setupConfigDir(args);
args.configDirPath = configDirPath;
setupCompileCache(configDirPath);
if (handleStartupEventWithSquirrel()) {
return;
}
app.setAppUserModelId('com.squirrel.nylas.nylas');
addPathToOpen = function(event, pathToOpen) {
event.preventDefault();
return args.pathsToOpen.push(pathToOpen);
};
addUrlToOpen = function(event, urlToOpen) {
event.preventDefault();
return args.urlsToOpen.push(urlToOpen);
};
app.on('open-file', addPathToOpen);
app.on('open-url', addUrlToOpen);
app.on('will-finish-launching', function() {
return setupCrashReporter();
});
return app.on('ready', function() {
var Application;
app.removeListener('open-file', addPathToOpen);
app.removeListener('open-url', addUrlToOpen);
Application = require(path.join(args.resourcePath, 'src', 'browser', 'application'));
Application.open(args);
if (!args.test) {
if (!args.specMode) {
return console.log("App load time: " + (Date.now() - global.shellStartTime) + "ms");
}
});
};
setupNylasHome = function() {
var atomHome;
if (process.env.NYLAS_HOME) {
return;
}
atomHome = path.join(app.getPath('home'), '.nylas');
return process.env.NYLAS_HOME = atomHome;
};
normalizeDriveLetterName = function(filePath) {
if (process.platform === 'win32') {
return filePath.replace(/^([a-z]):/, function(arg) {
var driveLetter;
driveLetter = arg[0];
return driveLetter.toUpperCase() + ":";
});
setupConfigDir = function(args) {
var configDirPath, defaultConfigDir, fsWin, ref, ref1;
if (args.specMode) {
defaultConfigDir = path.join(app.getPath('home'), '.nylas-spec');
} else {
return filePath;
defaultConfigDir = path.join(app.getPath('home'), '.nylas');
}
configDirPath = (ref = (ref1 = args.configDirPath) != null ? ref1 : process.env.NYLAS_HOME) != null ? ref : defaultConfigDir;
mkdirp.sync(configDirPath);
if (process.platform === 'win32') {
fsWin = require('fswin');
fsWin.setAttributesSync(pathToFileOrDir, {
IS_HIDDEN: true
});
}
process.env.NYLAS_HOME = configDirPath;
return configDirPath;
};
handleStartupEventWithSquirrel = function() {
@ -90,10 +80,10 @@
return SquirrelUpdate.handleStartupEvent(app, squirrelCommand);
};
setupCompileCache = function() {
setupCompileCache = function(configDirPath) {
var compileCache;
compileCache = require('../compile-cache');
return compileCache.setHomeDirectory(process.env.NYLAS_HOME);
return compileCache.setHomeDirectory(configDirPath);
};
setupErrorLogger = function(args) {
@ -103,30 +93,33 @@
}
ErrorLogger = require('../error-logger');
return new ErrorLogger({
inSpecMode: args.test,
inSpecMode: args.specMode,
inDevMode: args.devMode,
resourcePath: args.resourcePath
});
};
setupCrashReporter = function() {};
declareOptions = function(argv) {
var optimist, options;
optimist = require('optimist');
options = optimist(argv);
options.usage("Nylas N1 v" + (app.getVersion()) + "\n\nUsage: n1 [options]\n\nRun N1: The open source extensible email client\n\n`n1 --dev` to start the client in dev mode.\n\n`n1 --test` to run unit tests.");
options.alias('d', 'dev').boolean('d').describe('d', 'Run in development mode.');
options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.');
options.boolean('safe').describe('safe', 'Do not load packages from ~/.nylas/packages or ~/.nylas/dev/packages.');
options.alias('h', 'help').boolean('h').describe('h', 'Print this usage message.');
options.alias('l', 'log-file').string('l').describe('l', 'Log all test output to file.');
options.alias('c', 'config-dir-path').string('c').describe('c', 'Override the path to the N1 configuration directory');
options.alias('s', 'spec-directory').string('s').describe('s', 'Override the directory from which to run package specs');
options.alias('f', 'spec-file-pattern').string('f').describe('f', 'Override the default file regex to determine which tests should run (defaults to "-spec\.(coffee|js|jsx|cjsx|es6|es)$" )');
options.alias('v', 'version').boolean('v').describe('v', 'Print the version.');
return options;
};
parseCommandLine = function() {
var args, devMode, devResourcePath, executedFrom, logFile, newWindow, options, packageDirectoryPath, packageManifest, packageManifestPath, pathsToOpen, pidToKillWhenClosed, ref, ref1, ref2, resourcePath, safeMode, showSpecsInWindow, specDirectory, specFilePattern, test, urlsToOpen, version;
var args, configDirPath, devMode, logFile, options, ref, resourcePath, safeMode, showSpecsInWindow, specDirectory, specFilePattern, specMode, urlsToOpen, version;
version = app.getVersion();
options = optimist(process.argv.slice(1));
options.usage("N1 v" + version + "\n\nUsage: n1 [options] [path ...]\n\nOne or more paths to files or folders to open may be specified.\n\nFile paths will open in the current window.\n\nFolder paths will open in an existing window if that folder has already been\nopened or a new window if it hasn't.\n\nEnvironment Variables:\nN1_PATH The path from which N1 loads source code in dev mode.\n Defaults to `cwd`.");
options.alias('d', 'dev').boolean('d').describe('d', 'Run in development mode.');
options.alias('f', 'foreground').boolean('f').describe('f', 'Keep the browser process in the foreground.');
options.alias('h', 'help').boolean('h').describe('h', 'Print this usage message.');
options.alias('l', 'log-file').string('l').describe('l', 'Log all output to file.');
options.alias('n', 'new-window').boolean('n').describe('n', 'Open a new window.');
options.alias('r', 'resource-path').string('r').describe('r', 'Set the path to the N1 source directory and enable dev-mode.');
options.alias('s', 'spec-directory').string('s').describe('s', 'Set the directory from which to run package specs (default: N1\'s spec directory).');
options.boolean('safe').describe('safe', 'Do not load packages from ~/.nylas/packages or ~/.nylas/dev/packages.');
options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.');
options.alias('v', 'version').boolean('v').describe('v', 'Print the version.');
options.alias('w', 'wait').boolean('w').describe('w', 'Wait for window to be closed before returning.');
options = declareOptions(process.argv.slice(1));
args = options.argv;
if (args.help) {
process.stdout.write(options.help());
@ -136,83 +129,31 @@
process.stdout.write(version + "\n");
process.exit(0);
}
executedFrom = (ref = (ref1 = args['executed-from']) != null ? ref1.toString() : void 0) != null ? ref : process.cwd();
devMode = args['dev'];
safeMode = args['safe'];
pathsToOpen = args._;
if (executedFrom && pathsToOpen.length === 0) {
pathsToOpen = [executedFrom];
}
urlsToOpen = [];
test = args['test'];
specDirectory = args['spec-directory'];
newWindow = args['new-window'];
if (args['wait']) {
pidToKillWhenClosed = args['pid'];
}
devMode = args['dev'] || args['test'];
logFile = args['log-file'];
specFilePattern = args['file-pattern'];
devResourcePath = (ref2 = process.env.N1_PATH) != null ? ref2 : process.cwd();
showSpecsInWindow = false;
if (args['resource-path']) {
devMode = true;
resourcePath = args['resource-path'];
} else {
if (specDirectory != null) {
packageDirectoryPath = path.resolve(specDirectory, '..');
packageManifestPath = path.join(packageDirectoryPath, 'package.json');
if (fs.statSyncNoException(packageManifestPath)) {
try {
packageManifest = JSON.parse(fs.readFileSync(packageManifestPath));
if (packageManifest.name === 'edgehill') {
resourcePath = packageDirectoryPath;
}
} catch (_error) {}
}
} else {
if (test && toString.call(test) === "[object String]") {
if (test === "core") {
specDirectory = path.join(devResourcePath, "spec");
} else if (test === "window") {
specDirectory = path.join(devResourcePath, "spec");
showSpecsInWindow = true;
} else {
specDirectory = path.resolve(path.join(devResourcePath, "internal_packages", test));
}
}
}
}
if (test) {
devMode = true;
}
if (devMode) {
if (resourcePath == null) {
resourcePath = devResourcePath;
}
}
if (!fs.statSyncNoException(resourcePath)) {
resourcePath = path.dirname(path.dirname(__dirname));
}
specMode = args['test'];
safeMode = args['safe'];
configDirPath = args['config-dir-path'];
specDirectory = args['spec-directory'];
specFilePattern = args['spec-file-pattern'];
showSpecsInWindow = specMode === "window";
resourcePath = path.resolve((ref = args['resource-path']) != null ? ref : path.dirname(path.dirname(__dirname)));
urlsToOpen = [];
if (args['path-environment']) {
process.env.PATH = args['path-environment'];
}
resourcePath = normalizeDriveLetterName(resourcePath);
devResourcePath = normalizeDriveLetterName(devResourcePath);
return {
resourcePath: resourcePath,
pathsToOpen: pathsToOpen,
urlsToOpen: urlsToOpen,
executedFrom: executedFrom,
test: test,
version: version,
pidToKillWhenClosed: pidToKillWhenClosed,
devMode: devMode,
safeMode: safeMode,
newWindow: newWindow,
specDirectory: specDirectory,
showSpecsInWindow: showSpecsInWindow,
logFile: logFile,
specFilePattern: specFilePattern
specMode: specMode,
safeMode: safeMode,
configDirPath: configDirPath,
specDirectory: specDirectory,
specFilePattern: specFilePattern,
showSpecsInWindow: showSpecsInWindow,
resourcePath: resourcePath,
urlsToOpen: urlsToOpen
};
};

View file

@ -30,7 +30,8 @@ class NylasWindow
@neverClose,
@mainWindow,
@resourcePath,
@exitWhenDone} = settings
@exitWhenDone,
@configDirPath} = settings
# Normalize to make sure drive letter case is consistent on Windows
@resourcePath = path.normalize(@resourcePath) if @resourcePath

View file

@ -6,7 +6,7 @@ NylasWindow = require './nylas-window'
class WindowManager
constructor: ({@devMode, @safeMode, @resourcePath, @config}) ->
constructor: ({@devMode, @safeMode, @resourcePath, @configDirPath, @config}) ->
@_windows = []
@_mainWindow = null
@_workWindow = null
@ -73,14 +73,12 @@ class WindowManager
bootstrapScript ?= require.resolve('../window-bootstrap')
resourcePath ?= @resourcePath
@_mainWindow = new NylasWindow
@_mainWindow = new NylasWindow _.extend {}, @defaultWindowOptions(),
loadingMessage: loadingMessage
bootstrapScript: bootstrapScript
resourcePath: resourcePath
devMode: @devMode
safeMode: @safeMode
neverClose: true
mainWindow: true
windowType: 'default'
# The position and resizable bit gets reset when the window
# finishes loading. This represents the state of our "loading"
# window.
@ -325,6 +323,7 @@ class WindowManager
safeMode: @safeMode
windowType: 'popout'
resourcePath: @resourcePath
configDirPath: @configDirPath
bootstrapScript: require.resolve("../window-secondary-bootstrap")
newColdWindow: (options={}) ->

View file

@ -211,8 +211,12 @@ class AccountStore
for filename in fs.readdirSync(downloadsDir)
fs.copySync(path.join(downloadsDir, filename), path.join(NylasEnv.getConfigDirPath(), 'downloads', filename))
DatabaseStore.persistModels(_.values(labels))
DatabaseStore.persistModels(messages)
DatabaseStore.persistModels(threads)
Promise.all([
DatabaseStore.persistModel(account),
DatabaseStore.persistModels(_.values(labels)),
DatabaseStore.persistModels(messages),
DatabaseStore.persistModels(threads)
]).then =>
Actions.selectAccountId account.id
module.exports = new AccountStore()

View file

@ -4,9 +4,7 @@ LessCache = require 'less-cache'
# {LessCache} wrapper used by {ThemeManager} to read stylesheets.
module.exports =
class LessCompileCache
@cacheDir: path.join(process.env.NYLAS_HOME, 'compile-cache', 'less')
constructor: ({resourcePath, importPaths}) ->
constructor: ({configDirPath, resourcePath, importPaths}) ->
@lessSearchPaths = [
path.join(resourcePath, 'static', 'variables')
path.join(resourcePath, 'static')
@ -18,7 +16,7 @@ class LessCompileCache
importPaths = @lessSearchPaths
@cache = new LessCache
cacheDir: @constructor.cacheDir
cacheDir: path.join(configDirPath, 'compile-cache', 'less')
importPaths: importPaths
resourcePath: resourcePath
fallbackDir: path.join(resourcePath, 'less-compile-cache')

View file

@ -67,20 +67,14 @@ class NylasEnvConstructor extends Model
# Returns the path where the state for the current window will be
# located if it exists.
@getStatePath: ->
{isSpec, mainWindow} = @getLoadSettings()
{isSpec, mainWindow, configDirPath} = @getLoadSettings()
if isSpec
filename = 'spec-saved-state.json'
else if mainWindow
path.join(@getConfigDirPath(), 'main-window-state.json')
path.join(configDirPath, 'main-window-state.json')
else
null
# Get the directory path to NylasEnv's configuration area.
#
# Returns the absolute path to ~/.nylas
@getConfigDirPath: ->
@configDirPath ?= fs.absolute('~/.nylas')
# Returns the load settings hash associated with the current window.
@getLoadSettings: ->
@loadSettings ?= JSON.parse(decodeURIComponent(location.search.substr(14)))
@ -164,9 +158,8 @@ class NylasEnvConstructor extends Model
StyleManager = require './style-manager'
ActionBridge = require './flux/action-bridge'
MenuManager = require './menu-manager'
configDirPath = @getConfigDirPath()
{devMode, safeMode, resourcePath, windowType} = @getLoadSettings()
{devMode, safeMode, resourcePath, configDirPath, windowType} = @getLoadSettings()
document.body.classList.add("platform-#{process.platform}")
document.body.classList.add("window-type-#{windowType}")
@ -370,10 +363,7 @@ class NylasEnvConstructor extends Model
not /\w{7}/.test(@getVersion()) # Check if the release is a 7-character SHA prefix
# Public: Get the directory path to N1's configuration area.
#
# Returns the absolute path to `~/.nylas`.
getConfigDirPath: ->
@constructor.getConfigDirPath()
getConfigDirPath: => @getLoadSettings().configDirPath
# Public: Get the time taken to completely load the current window.
#
@ -659,9 +649,8 @@ class NylasEnvConstructor extends Model
ipcRenderer.send('window-command', 'window:loaded')
showRootWindow: ->
cover = document.getElementById("application-loading-cover")
cover.classList.add('visible')
document.body.classList.add("main-window-loaded")
document.getElementById("application-loading-cover").remove()
document.body.classList.add("window-loaded")
@restoreWindowDimensions()
@getCurrentWindow().setMinimumSize(875, 500)

View file

@ -303,7 +303,7 @@ class ThemeManager
loadLessStylesheet: (lessStylesheetPath, importFallbackVariables=false) ->
unless @lessCache?
LessCompileCache = require './less-compile-cache'
@lessCache = new LessCompileCache({@resourcePath, importPaths: @getImportPaths()})
@lessCache = new LessCompileCache({@configDirPath, @resourcePath, importPaths: @getImportPaths()})
try
if importFallbackVariables

View file

@ -18,7 +18,7 @@ global.NylasEnv =
onBeforeUnload: ->
getWindowLoadTime: -> 0
getConfigDirPath: ->
@configDirPath ?= fs.absolute('~/.nylas')
@configDirPath ?= JSON.parse(decodeURIComponent(location.search.substr(14))).configDirPath
getLoadSettings: ->
@loadSettings ?= JSON.parse(decodeURIComponent(location.search.substr(14)))
inSpecMode: ->

View file

@ -26,10 +26,6 @@
opacity: 0.6;
margin-top: 90px;
}
.application-loading-cover.visible {
opacity: 0;
pointer-events: none;
}
.application-loading-text {
text-align: center;

View file

@ -39,7 +39,7 @@ function setupWindow (loadSettings) {
var hotreload = loadSettings.devMode && !loadSettings.isSpec;
var CompileCache = require('../src/compile-cache')
CompileCache.setHotReload(hotreload)
CompileCache.setHomeDirectory(process.env.NYLAS_HOME)
CompileCache.setHomeDirectory(loadSettings.configDirPath)
var ModuleCache = require('../src/module-cache')
ModuleCache.register(loadSettings)