{"action":"created","comment":{"url":"https://api.github.com/repos/Shopify/javascript/pulls/comments/72086705","id":72086705,"diff_hunk":"@@ -0,0 +1,355 @@\n+# `import {Testing} from 'Shopify'`\n+\n+This guide looks at our recommended tools and conventions for testing JavaScript at Shopify. The primary focus of this guide is unit testing, but you can find some discussion of other types of testing in the [types of testing section](#types-of-testing).\n+\n+## Table of contents\n+\n+1. [Tools](#tools)\n+1. [Style](#style)\n+1. [Best practices](#best-practices)\n+1. [Types of testing](#types-of-testing)\n+1. [React](#react)\n+1. [Resources](#resources)\n+\n+\n+\n+## Tools\n+\n+We recommend using the following tools in your tests:\n+\n+- [**mocha**](https://mochajs.org/) is our preferred test framework. It provides the basic scaffolding for tests including hooks, excellent support for asynchronous code, and more.\n+\n+- [**chai**](http://chaijs.com/) is our preferred assertion library. It provides many expressive assertions that have descriptive error messages in the case of test failures.\n+\n+- [**sinon**](http://sinonjs.org/) is our preferred library for handling spies and mocks in JavaScript.\n+\n+These tools are commonly used together and have many excellent online resources, including solid documentation. In addition to the above, you can use [chai plugins](http://chaijs.com/plugins/) to provide more meaningful assertions. Use caution, however: only include a plugin where it materially helps improve the legibility of tests (otherwise, the burden of other developers tracking down a particular assertion outweighs the benefits you get from having it). [chai-as-promised](http://chaijs.com/plugins/chai-as-promised/) is an excellent example of a chai plugin that makes otherwise awkward tests much easier to read.\n+\n+In addition to the testing framework, you generally need a test *runner*. Which runner to use will depend on the nature of your project:\n+\n+- For pure-JavaScript projects that do not need access to the DOM, avoid using a test runner and simply run the `mocha` CLI instead (if you need a simple DOM without actual rendering, you can also use [cheerio](https://github.com/cheeriojs/cheerio) to construct a fake DOM).\n+\n+- For Non-Rails projects that require a full DOM, use [Karma](https://karma-runner.github.io/1.0/index.html). It integrates well with other tools you are likely using, such as Webpack and code coverage tools.\n+\n+- Rails projects should use [Teaspoon](https://github.com/modeset/teaspoon), which provides an excellent GUI for running tests in the browser. If you are also using [sprockets-commoner](https://github.com/Shopify/sprockets-commoner) to transpile your JavaScript, make sure to include [teaspoon-bundle](https://github.com/Shopify/teaspoon-bundle) to generate your test bundle.\n+\n+There are a variety of other tools you might need depending on your project. Here are some additional recommendations we make:\n+\n+- **Test coverage**: we recommend using [nyc](https://github.com/istanbuljs/nyc).\n+\n+- **Rails fixtures**: if you are testing a component that has a non-trivial HTML component, using the actual partial improves the test’s resilience. We recommend using [Magic Lamp](https://github.com/crismali/magic_lamp) if you need access to real partials in a Rails application (if you are writing a JavaScript application, you should be able to import your partials using JavaScript imports).\n+\n+[↑ scrollTo('#table-of-contents')](#table-of-contents)\n+\n+\n+\n+## Style\n+\n+- Our [shared linting configuration](../packages/eslint-plugin-shopify) provides a mocha-/ sinon-/ chai-focused linting configuration which you can use to prevent many common mistakes. To use it, simply extend `plugin:shopify/mocha` in your ESLint configuration (full details can be found on that package’s README).\n+\n+- Use [TDD-style `assert` syntax](http://chaijs.com/api/assert/) over BDD-style `expect` or `should`.\n+\n+  > Why? This keeps JavaScript tests more in line with our style for writing Ruby tests, which helps everyone contribute to the test codebase more easily.\n+\n+  ```js\n+  // bad\n+  expect(2 === 1).to.be.false;\n+  (2 === 1).should.be.false;\n+\n+  // good\n+  assert.isFalse(2 === 1);\n+  ```\n+\n+- Use the Mocha-provided [TDD interface](https://mochajs.org/#tdd), which includes the `suite`, `test`, `setup`, and `teardown` functions.\n+\n+  ```js\n+  // bad\n+  describe('myFunction', () => {\n+    beforeEach(() => {\n+      doSomeSetup();\n+    });\n+\n+    it('is a function', () => {\n+      assert.isFunction(myFunction);\n+    });\n+  });\n+\n+  // good\n+  suite('myFunction', () => {\n+    setup(() => {\n+      doSomeSetup();\n+    });\n+\n+    test('it is a function', () => {\n+      assert.isFunction(myFunction);\n+    });\n+  });\n+  ```\n+\n+- Do not attach variables under test to the Mocha test context (`this`). Instead, use variables scoped to the nearest `suite`. If using ESNext, always use arrow functions to ensure that you will not be able to rely on context.\n+\n+  > Why? Using a shared context makes it too easy for tests to \"leak\" (have some impact on other tests), especially in other test files. It also makes it harder to track down what should be in scope at any given time.\n+\n+  ```js\n+  // bad\n+  suite('MyComponent', function() {\n+    setup(function() {\n+      this.subject = new MyComponent();\n+      this.doSomethingWithComponent = function() {\n+        return this.subject.doSomething();\n+      }\n+    });\n+\n+    test(function() {\n+      assert.isFalse(this.doSomethingWithComponent());\n+    });\n+  });\n+\n+  // good\n+  suite('MyComponent', () => {\n+    let subject;\n+    function doSomethingWithComponent() {\n+      return subject.doSomething();\n+    }\n+\n+    setup(() => {\n+      subject = new MyComponent();\n+    });\n+\n+    test(() => {\n+      assert.isFalse(doSomethingWithComponent());\n+    });\n+  });\n+  ```\n+\n+- Move any common setup to the `setup` hook of your suite.\n+\n+  > Why? Setup in the test itself draws attention from whatever is being tested.\n+\n+  ```js\n+  suite('MyComponent', () => {\n+    // bad\n+    suite('#myBadFunc', () => {\n+      test('it does something', () => {\n+        const subject = new MyComponent();\n+        sinon.stub(subject, 'myBadFunc').returns(true);\n+        assert.true(subject.doSomething())\n+      });\n+\n+      test('it does something else', () => {\n+        const subject = new MyComponent();\n+        sinon.stub(subject, 'myBadFunc').returns(true);\n+        assert.false(subject.doSomethingElse())\n+      });\n+    });\n+\n+    // good\n+    suite('#myBadFunc', () => {\n+      let subject;\n+\n+      setup(() => {\n+        subject = new MyComponent();\n+        sinon.stub(subject, 'myBadFunc').returns(true);\n+      });\n+\n+      test('it does something', () => {\n+        assert.true(subject.doSomething())\n+      });\n+\n+      test('it does something else', () => {\n+        assert.false(subject.doSomethingElse())\n+      });\n+    });\n+  });\n+  ```\n+\n+- Something something about how to name your tests\n+\n+- Do not rely on test ordering for your tests to run correctly. Imagine each test was going to be run in a separate process, and must therefore entirely setup any preconditions before running.\n+\n+  > Why? Tests that depend on anything outside of them will inevitably break as more tests are added. Other developers will assume there is no shared context between tests; don’t violate that assumption!\n+\n+- Use sinon’s spies/ stubs instead of rolling your own version.\n+\n+  > Why? Spies and stubs provide a consistent interface in case the tests need to be changed, reduce boilerplate so you can focus on the subject under test, can easily be restored to their original versions, and can be tested with more meaningful assertions.\n+\n+  ```js\n+  suite('MyComponent', () => {\n+    // bad\n+    suite('#myBadFunc', () => {\n+      let original;\n+      let calledWith;\n+\n+      setup(() => {\n+        spy = function(firstArg) { calledWith = firtArg; }\n+        let original = subject.myBadFunc;\n+        subject.myBadFunc = spy;\n+      });\n+\n+      teardown(() => {\n+        subject.myBadFunc = original;\n+      });\n+\n+      test('it works', () => {\n+        subject.doSomething();\n+        assert.equal(calledWith, 'some arg');\n+      });\n+    });\n+\n+    // good\n+    suite('#myGoodFunc', () => {\n+      let spy;\n+\n+      setup(() => {\n+        spy = sinon.spy(subject, 'myGoodFunc');\n+      });\n+\n+      teardown(() => {\n+        spy.restore();\n+      });\n+\n+      test('it works', () => {\n+        subject.doSomething();\n+        assert.calledWith(spy, 'some arg');\n+      });\n+    });\n+  });\n+  ```\n+\n+- Use the most meaningful assertion for what you are trying to test. For a list of available assertions, make sure to check out [chai’s `assert` docs](http://chaijs.com/api/assert/).\n+\n+  > Why? More specific assertions have more specific error messages, making it easier for you (and any developer that deals with this code in the future) to track down and fix test failures.\n+\n+  ```js\n+  // bad\n+  assert.isTrue(foo === bar);\n+\n+  // good\n+  assert.equal(foo, bar);\n+  ```\n+\n+- Use sinon’s custom spy assertions, exposed to chai’s `assert` object.\n+\n+  ```js\n+  // somewhere in the test setup...\n+  // (see http://sinonjs.org/docs/#assert-expose)\n+  sinon.assert.expose(assert);\n+\n+  // bad\n+  assert.isTrue(spy.called);\n+\n+  // good\n+  assert.called(spy);\n+  ```\n+\n+- Always use a test helper that sets up your global test state. This generally includes adding any chai plugins you need, setting up a global sinon sandbox, and any other global hooks you require. It is often useful to expose `sinon`/ `sandbox` and `assert` to the global object in this helper to avoid needing to import them in every test file.\n+\n+  ```js\n+  // Here's an example test-helper file\n+\n+  import chai, {assert} from 'chai';\n+  import sinon from 'sinon';\n+  import chaiAsPromised from 'chai-as-promised';\n+\n+  chai.use(chaiAsPromised);\n+  sinon.assert.expose(assert);\n+\n+  // This creats a sandbox that will automatically restore any\n+  // stubbed properties performed during tests.\n+  const sandbox = sinon.sandbox.create();\n+\n+  global.assert = assert;\n+  global.sinon = sandbox;\n+\n+  afterEach(() => {\n+    sandbox.restore();\n+  });\n+  ```\n+\n+- Use mocha’s ability to automatically finish tests when a returned promise is resolved for tests that are asynchronous and depend on promises.\n+\n+  ```js\n+  // bad\n+  test('it resolves with a value', (done) => {\n+    doSomethingAsync()\n+      .then((result) => {\n+        assert.equal(result, 'something');\n+        done();\n+      })\n+      .catch(() => {\n+        assert(false, 'The promise was rejected :(');\n+      });\n+  });\n+\n+  // good\n+  test('it resolves with a value', () => {\n+    return doSomethingAsync()\n+      .then((result) => {\n+        assert.equal(result, 'something');\n+      });\n+  });\n+\n+  // also good, if using async/ await\n+  test('it resolves with a value', async () => {\n+    const result = await doSomethingAsync();\n+    assert.equal(result, 'something');\n+  });\n+  ```\n+\n+[↑ scrollTo('#table-of-contents')](#table-of-contents)\n+\n+\n+\n+## Best practices\n+\n+- Try to limit the number of assertions made in a single test. For unit tests, you should only be testing one thing at a time (generally, an individual function, either standalone or as a method of an object), and more than one or two assertions is generally indicative that you should split your test into multiple tests.\n+\n+- Something something about how to organize suites (by method? by context?)","path":"testing/README.md","position":307,"original_position":307,"commit_id":"78e7c4d158b6e133d6c30a4a8e01b06eec5f6df0","original_commit_id":"78e7c4d158b6e133d6c30a4a8e01b06eec5f6df0","user":{"login":"lemonmade","id":3012583,"avatar_url":"https://avatars.githubusercontent.com/u/3012583?v=3","gravatar_id":"","url":"https://api.github.com/users/lemonmade","html_url":"https://github.com/lemonmade","followers_url":"https://api.github.com/users/lemonmade/followers","following_url":"https://api.github.com/users/lemonmade/following{/other_user}","gists_url":"https://api.github.com/users/lemonmade/gists{/gist_id}","starred_url":"https://api.github.com/users/lemonmade/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lemonmade/subscriptions","organizations_url":"https://api.github.com/users/lemonmade/orgs","repos_url":"https://api.github.com/users/lemonmade/repos","events_url":"https://api.github.com/users/lemonmade/events{/privacy}","received_events_url":"https://api.github.com/users/lemonmade/received_events","type":"User","site_admin":false},"body":"Similar to question above — do you use nested suites for describing methods? For describing different arguments? Not at all?","created_at":"2016-07-25T15:33:46Z","updated_at":"2016-07-25T15:33:46Z","html_url":"https://github.com/Shopify/javascript/pull/206#discussion_r72086705","pull_request_url":"https://api.github.com/repos/Shopify/javascript/pulls/206","_links":{"self":{"href":"https://api.github.com/repos/Shopify/javascript/pulls/comments/72086705"},"html":{"href":"https://github.com/Shopify/javascript/pull/206#discussion_r72086705"},"pull_request":{"href":"https://api.github.com/repos/Shopify/javascript/pulls/206"}}},"pull_request":{"url":"https://api.github.com/repos/Shopify/javascript/pulls/206","id":77831263,"html_url":"https://github.com/Shopify/javascript/pull/206","diff_url":"https://github.com/Shopify/javascript/pull/206.diff","patch_url":"https://github.com/Shopify/javascript/pull/206.patch","issue_url":"https://api.github.com/repos/Shopify/javascript/issues/206","number":206,"state":"open","locked":false,"title":"Testing guide","user":{"login":"AWaselnuk","id":3630241,"avatar_url":"https://avatars.githubusercontent.com/u/3630241?v=3","gravatar_id":"","url":"https://api.github.com/users/AWaselnuk","html_url":"https://github.com/AWaselnuk","followers_url":"https://api.github.com/users/AWaselnuk/followers","following_url":"https://api.github.com/users/AWaselnuk/following{/other_user}","gists_url":"https://api.github.com/users/AWaselnuk/gists{/gist_id}","starred_url":"https://api.github.com/users/AWaselnuk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AWaselnuk/subscriptions","organizations_url":"https://api.github.com/users/AWaselnuk/orgs","repos_url":"https://api.github.com/users/AWaselnuk/repos","events_url":"https://api.github.com/users/AWaselnuk/events{/privacy}","received_events_url":"https://api.github.com/users/AWaselnuk/received_events","type":"User","site_admin":false},"body":"Hey team. I got the ball rolling with a possible outline for a JS testing guide. Who can iterate on this branch? @tylerball @lemonmade @tessalt @m-ux \r\n\r\nI suggest we a) Get a first version complete before bringing in more FED for review and b) Focus on just writing down what we currently do most of the time rather than advancing the state of the art.\r\n\r\nThis doc can probably provide a great starting point and I've already lifted some stuff from it: https://github.com/Shopify/shopify/wiki/Admin-Testing","created_at":"2016-07-18T15:48:34Z","updated_at":"2016-07-25T15:33:46Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0c5456a181bf4f6ab397e01b033f85533d4c10d4","assignee":{"login":"richgilbank","id":1245284,"avatar_url":"https://avatars.githubusercontent.com/u/1245284?v=3","gravatar_id":"","url":"https://api.github.com/users/richgilbank","html_url":"https://github.com/richgilbank","followers_url":"https://api.github.com/users/richgilbank/followers","following_url":"https://api.github.com/users/richgilbank/following{/other_user}","gists_url":"https://api.github.com/users/richgilbank/gists{/gist_id}","starred_url":"https://api.github.com/users/richgilbank/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/richgilbank/subscriptions","organizations_url":"https://api.github.com/users/richgilbank/orgs","repos_url":"https://api.github.com/users/richgilbank/repos","events_url":"https://api.github.com/users/richgilbank/events{/privacy}","received_events_url":"https://api.github.com/users/richgilbank/received_events","type":"User","site_admin":false},"assignees":[{"login":"richgilbank","id":1245284,"avatar_url":"https://avatars.githubusercontent.com/u/1245284?v=3","gravatar_id":"","url":"https://api.github.com/users/richgilbank","html_url":"https://github.com/richgilbank","followers_url":"https://api.github.com/users/richgilbank/followers","following_url":"https://api.github.com/users/richgilbank/following{/other_user}","gists_url":"https://api.github.com/users/richgilbank/gists{/gist_id}","starred_url":"https://api.github.com/users/richgilbank/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/richgilbank/subscriptions","organizations_url":"https://api.github.com/users/richgilbank/orgs","repos_url":"https://api.github.com/users/richgilbank/repos","events_url":"https://api.github.com/users/richgilbank/events{/privacy}","received_events_url":"https://api.github.com/users/richgilbank/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/Shopify/javascript/pulls/206/commits","review_comments_url":"https://api.github.com/repos/Shopify/javascript/pulls/206/comments","review_comment_url":"https://api.github.com/repos/Shopify/javascript/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Shopify/javascript/issues/206/comments","statuses_url":"https://api.github.com/repos/Shopify/javascript/statuses/78e7c4d158b6e133d6c30a4a8e01b06eec5f6df0","head":{"label":"Shopify:testing-guide","ref":"testing-guide","sha":"78e7c4d158b6e133d6c30a4a8e01b06eec5f6df0","user":{"login":"Shopify","id":8085,"avatar_url":"https://avatars.githubusercontent.com/u/8085?v=3","gravatar_id":"","url":"https://api.github.com/users/Shopify","html_url":"https://github.com/Shopify","followers_url":"https://api.github.com/users/Shopify/followers","following_url":"https://api.github.com/users/Shopify/following{/other_user}","gists_url":"https://api.github.com/users/Shopify/gists{/gist_id}","starred_url":"https://api.github.com/users/Shopify/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Shopify/subscriptions","organizations_url":"https://api.github.com/users/Shopify/orgs","repos_url":"https://api.github.com/users/Shopify/repos","events_url":"https://api.github.com/users/Shopify/events{/privacy}","received_events_url":"https://api.github.com/users/Shopify/received_events","type":"Organization","site_admin":false},"repo":{"id":49887169,"name":"javascript","full_name":"Shopify/javascript","owner":{"login":"Shopify","id":8085,"avatar_url":"https://avatars.githubusercontent.com/u/8085?v=3","gravatar_id":"","url":"https://api.github.com/users/Shopify","html_url":"https://github.com/Shopify","followers_url":"https://api.github.com/users/Shopify/followers","following_url":"https://api.github.com/users/Shopify/following{/other_user}","gists_url":"https://api.github.com/users/Shopify/gists{/gist_id}","starred_url":"https://api.github.com/users/Shopify/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Shopify/subscriptions","organizations_url":"https://api.github.com/users/Shopify/orgs","repos_url":"https://api.github.com/users/Shopify/repos","events_url":"https://api.github.com/users/Shopify/events{/privacy}","received_events_url":"https://api.github.com/users/Shopify/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Shopify/javascript","description":"The home for all things JavaScript at Shopify.","fork":false,"url":"https://api.github.com/repos/Shopify/javascript","forks_url":"https://api.github.com/repos/Shopify/javascript/forks","keys_url":"https://api.github.com/repos/Shopify/javascript/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Shopify/javascript/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Shopify/javascript/teams","hooks_url":"https://api.github.com/repos/Shopify/javascript/hooks","issue_events_url":"https://api.github.com/repos/Shopify/javascript/issues/events{/number}","events_url":"https://api.github.com/repos/Shopify/javascript/events","assignees_url":"https://api.github.com/repos/Shopify/javascript/assignees{/user}","branches_url":"https://api.github.com/repos/Shopify/javascript/branches{/branch}","tags_url":"https://api.github.com/repos/Shopify/javascript/tags","blobs_url":"https://api.github.com/repos/Shopify/javascript/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Shopify/javascript/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Shopify/javascript/git/refs{/sha}","trees_url":"https://api.github.com/repos/Shopify/javascript/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Shopify/javascript/statuses/{sha}","languages_url":"https://api.github.com/repos/Shopify/javascript/languages","stargazers_url":"https://api.github.com/repos/Shopify/javascript/stargazers","contributors_url":"https://api.github.com/repos/Shopify/javascript/contributors","subscribers_url":"https://api.github.com/repos/Shopify/javascript/subscribers","subscription_url":"https://api.github.com/repos/Shopify/javascript/subscription","commits_url":"https://api.github.com/repos/Shopify/javascript/commits{/sha}","git_commits_url":"https://api.github.com/repos/Shopify/javascript/git/commits{/sha}","comments_url":"https://api.github.com/repos/Shopify/javascript/comments{/number}","issue_comment_url":"https://api.github.com/repos/Shopify/javascript/issues/comments{/number}","contents_url":"https://api.github.com/repos/Shopify/javascript/contents/{+path}","compare_url":"https://api.github.com/repos/Shopify/javascript/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Shopify/javascript/merges","archive_url":"https://api.github.com/repos/Shopify/javascript/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Shopify/javascript/downloads","issues_url":"https://api.github.com/repos/Shopify/javascript/issues{/number}","pulls_url":"https://api.github.com/repos/Shopify/javascript/pulls{/number}","milestones_url":"https://api.github.com/repos/Shopify/javascript/milestones{/number}","notifications_url":"https://api.github.com/repos/Shopify/javascript/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Shopify/javascript/labels{/name}","releases_url":"https://api.github.com/repos/Shopify/javascript/releases{/id}","deployments_url":"https://api.github.com/repos/Shopify/javascript/deployments","created_at":"2016-01-18T15:54:37Z","updated_at":"2016-07-10T11:34:29Z","pushed_at":"2016-07-25T15:28:49Z","git_url":"git://github.com/Shopify/javascript.git","ssh_url":"git@github.com:Shopify/javascript.git","clone_url":"https://github.com/Shopify/javascript.git","svn_url":"https://github.com/Shopify/javascript","homepage":null,"size":710,"stargazers_count":35,"watchers_count":35,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":11,"forks":5,"open_issues":11,"watchers":35,"default_branch":"master"}},"base":{"label":"Shopify:master","ref":"master","sha":"d60639ad60ab1f3b5528637d5f6e4ee28d3024ee","user":{"login":"Shopify","id":8085,"avatar_url":"https://avatars.githubusercontent.com/u/8085?v=3","gravatar_id":"","url":"https://api.github.com/users/Shopify","html_url":"https://github.com/Shopify","followers_url":"https://api.github.com/users/Shopify/followers","following_url":"https://api.github.com/users/Shopify/following{/other_user}","gists_url":"https://api.github.com/users/Shopify/gists{/gist_id}","starred_url":"https://api.github.com/users/Shopify/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Shopify/subscriptions","organizations_url":"https://api.github.com/users/Shopify/orgs","repos_url":"https://api.github.com/users/Shopify/repos","events_url":"https://api.github.com/users/Shopify/events{/privacy}","received_events_url":"https://api.github.com/users/Shopify/received_events","type":"Organization","site_admin":false},"repo":{"id":49887169,"name":"javascript","full_name":"Shopify/javascript","owner":{"login":"Shopify","id":8085,"avatar_url":"https://avatars.githubusercontent.com/u/8085?v=3","gravatar_id":"","url":"https://api.github.com/users/Shopify","html_url":"https://github.com/Shopify","followers_url":"https://api.github.com/users/Shopify/followers","following_url":"https://api.github.com/users/Shopify/following{/other_user}","gists_url":"https://api.github.com/users/Shopify/gists{/gist_id}","starred_url":"https://api.github.com/users/Shopify/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Shopify/subscriptions","organizations_url":"https://api.github.com/users/Shopify/orgs","repos_url":"https://api.github.com/users/Shopify/repos","events_url":"https://api.github.com/users/Shopify/events{/privacy}","received_events_url":"https://api.github.com/users/Shopify/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Shopify/javascript","description":"The home for all things JavaScript at Shopify.","fork":false,"url":"https://api.github.com/repos/Shopify/javascript","forks_url":"https://api.github.com/repos/Shopify/javascript/forks","keys_url":"https://api.github.com/repos/Shopify/javascript/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Shopify/javascript/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Shopify/javascript/teams","hooks_url":"https://api.github.com/repos/Shopify/javascript/hooks","issue_events_url":"https://api.github.com/repos/Shopify/javascript/issues/events{/number}","events_url":"https://api.github.com/repos/Shopify/javascript/events","assignees_url":"https://api.github.com/repos/Shopify/javascript/assignees{/user}","branches_url":"https://api.github.com/repos/Shopify/javascript/branches{/branch}","tags_url":"https://api.github.com/repos/Shopify/javascript/tags","blobs_url":"https://api.github.com/repos/Shopify/javascript/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Shopify/javascript/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Shopify/javascript/git/refs{/sha}","trees_url":"https://api.github.com/repos/Shopify/javascript/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Shopify/javascript/statuses/{sha}","languages_url":"https://api.github.com/repos/Shopify/javascript/languages","stargazers_url":"https://api.github.com/repos/Shopify/javascript/stargazers","contributors_url":"https://api.github.com/repos/Shopify/javascript/contributors","subscribers_url":"https://api.github.com/repos/Shopify/javascript/subscribers","subscription_url":"https://api.github.com/repos/Shopify/javascript/subscription","commits_url":"https://api.github.com/repos/Shopify/javascript/commits{/sha}","git_commits_url":"https://api.github.com/repos/Shopify/javascript/git/commits{/sha}","comments_url":"https://api.github.com/repos/Shopify/javascript/comments{/number}","issue_comment_url":"https://api.github.com/repos/Shopify/javascript/issues/comments{/number}","contents_url":"https://api.github.com/repos/Shopify/javascript/contents/{+path}","compare_url":"https://api.github.com/repos/Shopify/javascript/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Shopify/javascript/merges","archive_url":"https://api.github.com/repos/Shopify/javascript/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Shopify/javascript/downloads","issues_url":"https://api.github.com/repos/Shopify/javascript/issues{/number}","pulls_url":"https://api.github.com/repos/Shopify/javascript/pulls{/number}","milestones_url":"https://api.github.com/repos/Shopify/javascript/milestones{/number}","notifications_url":"https://api.github.com/repos/Shopify/javascript/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Shopify/javascript/labels{/name}","releases_url":"https://api.github.com/repos/Shopify/javascript/releases{/id}","deployments_url":"https://api.github.com/repos/Shopify/javascript/deployments","created_at":"2016-01-18T15:54:37Z","updated_at":"2016-07-10T11:34:29Z","pushed_at":"2016-07-25T15:28:49Z","git_url":"git://github.com/Shopify/javascript.git","ssh_url":"git@github.com:Shopify/javascript.git","clone_url":"https://github.com/Shopify/javascript.git","svn_url":"https://github.com/Shopify/javascript","homepage":null,"size":710,"stargazers_count":35,"watchers_count":35,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":11,"forks":5,"open_issues":11,"watchers":35,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Shopify/javascript/pulls/206"},"html":{"href":"https://github.com/Shopify/javascript/pull/206"},"issue":{"href":"https://api.github.com/repos/Shopify/javascript/issues/206"},"comments":{"href":"https://api.github.com/repos/Shopify/javascript/issues/206/comments"},"review_comments":{"href":"https://api.github.com/repos/Shopify/javascript/pulls/206/comments"},"review_comment":{"href":"https://api.github.com/repos/Shopify/javascript/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Shopify/javascript/pulls/206/commits"},"statuses":{"href":"https://api.github.com/repos/Shopify/javascript/statuses/78e7c4d158b6e133d6c30a4a8e01b06eec5f6df0"}}}}
{"actor":{"display_login":"lemonmade"}}