{"action":"created","comment":{"url":"https://api.github.com/repos/emberjs/ember.js/pulls/comments/62589135","id":62589135,"diff_hunk":"@@ -0,0 +1,1340 @@\n+import { RenderingTest, moduleFor } from '../../utils/test-case';\n+import { strip } from '../../utils/abstract-test-case';\n+import { Component } from '../../utils/helpers';\n+import { set } from 'ember-metal/property_set';\n+\n+import EmberObject from 'ember-runtime/system/object';\n+import { A as emberA } from 'ember-runtime/system/native_array';\n+\n+import jQuery from 'ember-views/system/jquery';\n+\n+function getActionAttributes(element) {\n+  let attributes = element.attributes;\n+  let actionAttrs = [];\n+\n+  for (let i = 0; i < attributes.length; i++) {\n+    let attr = attributes.item(i);\n+\n+    if (attr.name.indexOf('data-ember-action-') === 0) {\n+      actionAttrs.push(attr.name);\n+    }\n+  }\n+\n+  return actionAttrs;\n+}\n+\n+moduleFor('Helpers test: element action', class extends RenderingTest {\n+\n+  ['@test it can call an action on its enclosing component']() {\n+    let fooCallCount = 0;\n+\n+    let ExampleComponent = Component.extend({\n+      actions: {\n+        foo() {\n+          fooCallCount++;\n+        }\n+      }\n+    });\n+\n+    this.registerComponent('example-component', {\n+      ComponentClass: ExampleComponent,\n+      template: '<button {{action \"foo\"}}>Click me</button>'\n+    });\n+\n+    this.render('{{example-component}}');\n+\n+    this.assert.equal(fooCallCount, 0, 'foo has not been called');\n+\n+    this.runTask(() => this.rerender());\n+\n+    this.assert.equal(fooCallCount, 0, 'foo has not been called');\n+\n+    this.runTask(() => {\n+      this.$('button').click();\n+    });\n+\n+    this.assert.equal(fooCallCount, 1, 'foo has been called 1 time');\n+\n+    this.runTask(() => {\n+      this.$('button').click();\n+    });\n+\n+    this.assert.equal(fooCallCount, 2, 'foo has been called 2 times');\n+  }\n+\n+  ['@test it can call an action with parameters']() {\n+    let fooArgs = [];\n+    let component;\n+\n+    let ExampleComponent = Component.extend({\n+      member: 'a',\n+      init() {\n+        this._super(...arguments);\n+        component = this;\n+      },\n+      actions: {\n+        foo(thing) {\n+          fooArgs.push(thing);\n+        }\n+      }\n+    });\n+\n+    this.registerComponent('example-component', {\n+      ComponentClass: ExampleComponent,\n+      template: '<button {{action \"foo\" member}}>Click me</button>'\n+    });\n+\n+    this.render('{{example-component}}');\n+\n+    this.assert.deepEqual(fooArgs, [], 'foo has not been called');\n+\n+    this.runTask(() => this.rerender());\n+\n+    this.assert.deepEqual(fooArgs, [], 'foo has not been called');\n+\n+    this.runTask(() => {\n+      this.$('button').click();\n+    });\n+\n+    this.assert.deepEqual(fooArgs, ['a'], 'foo has not been called');\n+\n+    this.runTask(() => {\n+      component.set('member', 'b');\n+    });\n+\n+    this.runTask(() => {\n+      this.$('button').click();\n+    });\n+\n+    this.assert.deepEqual(fooArgs, ['a', 'b'], 'foo has been called with an updated value');\n+  }\n+\n+  ['@htmlbars it should output a data attribute with a guid']() {\n+    this.render('<button {{action \"show\"}}>me the money</button>');\n+\n+    let button = this.$('button');\n+\n+    this.assert.ok(button.attr('data-ember-action').match(/\\d+/), 'A data-ember-action attribute with a guid was added');\n+  }\n+\n+  ['@glimmer it should output a marker data attribute and a data attribute with a guid']() {\n+    this.render('<button {{action \"show\"}}>me the money</button>');\n+\n+    let button = this.$('button');\n+    let attributes = getActionAttributes(button.get(0));\n+\n+    this.assert.ok(button.attr('data-ember-action').match(''), 'An empty data-ember-action attribute was added');\n+    this.assert.ok(attributes[0].match(/data-ember-action-\\d+/), 'A data-ember-action-xyz attribute with a guid was added');\n+  }\n+\n+  ['@skip it should by default register a click event']() {\n+    // TODO\n+    // Should we be testing implementation details? Why?\n+  }\n+\n+  ['@skip it should allow alternative events to be handled']() {\n+    // TODO\n+    // Should we be testing implementation details? Why?\n+  }\n+\n+  ['@skip it should by default target the view\\'s controller']() {\n+    // TODO\n+    // Should we be testing implementation details? Why?\n+  }\n+\n+  ['@skip inside a yield, the target points at the original target']() {\n+    // TODO\n+    // Testing with views and {{#view}}?\n+  }\n+\n+  ['@test it should allow a target to be specified']() {\n+    let targetWatted = false;\n+\n+    let TargetComponent = Component.extend({\n+      actions: {\n+        wat() {\n+          targetWatted = true;\n+        }\n+      }\n+    });\n+\n+    let target = TargetComponent.create();\n+\n+    let OtherComponent = Component.extend({\n+      anotherTarget: target\n+    });\n+\n+    this.registerComponent('other-component', {\n+      ComponentClass: OtherComponent,\n+      template: '<a {{action \"wat\" target=anotherTarget}}>Wat?</a>'\n+    });\n+\n+    this.render('{{other-component}}');\n+\n+    this.runTask(() => {\n+      this.$('a').click();\n+    });\n+\n+    this.assert.equal(targetWatted, true, 'the specified target was watted');\n+  }\n+\n+  ['@test it should lazily evaluate the target']() {\n+    let firstEdit = 0;\n+    let secondEdit = 0;\n+    let component;\n+\n+    let first = {\n+      edit() {\n+        firstEdit++;\n+      }\n+    };\n+\n+    let second = {\n+      edit() {\n+        secondEdit++;\n+      }\n+    };\n+\n+    let ExampleComponent = Component.extend({\n+      init() {\n+        this._super(...arguments);\n+        component = this;\n+      },\n+      theTarget: first\n+    });\n+\n+    this.registerComponent('example-component', {\n+      ComponentClass: ExampleComponent,\n+      template: '<a {{action \"edit\" target=theTarget}}>Edit</a>'\n+    });\n+\n+    this.render('{{example-component}}');\n+\n+    this.runTask(() => {\n+      this.$('a').click();\n+    });\n+\n+    this.assert.equal(firstEdit, 1);\n+\n+    this.runTask(() => {\n+      set(component, 'theTarget', second);\n+    });\n+\n+    this.runTask(() => {\n+      this.$('a').click();\n+    });\n+\n+    this.assert.equal(firstEdit, 1);\n+    this.assert.equal(secondEdit, 1);\n+  }\n+\n+  ['@test it should register an event handler']() {\n+    let editHandlerWasCalled = false;\n+    let shortcutHandlerWasCalled = false;\n+\n+    let ExampleComponent = Component.extend({\n+      actions: {\n+        edit() { editHandlerWasCalled = true; },\n+        shortcut() { shortcutHandlerWasCalled = true; }\n+      }\n+    });\n+\n+    this.registerComponent('example-component', {\n+      ComponentClass: ExampleComponent,\n+      template: '<a href=\"#\" {{action \"edit\" allowedKeys=\"alt\"}}>click me</a> <div {{action \"shortcut\" allowedKeys=\"any\"}}>click me too</div>'\n+    });\n+\n+    this.render('{{example-component}}');\n+\n+    this.runTask(() => {\n+      let event = jQuery.Event('click');\n+      event.altKey = true;\n+      this.$('a[data-ember-action]').trigger(event);\n+    });\n+\n+    this.assert.equal(editHandlerWasCalled, true, 'the event handler was called');\n+\n+    this.runTask(() => {\n+      let event = jQuery.Event('click');\n+      event.ctrlKey = true;\n+      this.$('div[data-ember-action]').trigger(event);\n+    });\n+\n+    this.assert.equal(shortcutHandlerWasCalled, true, 'the \"any\" shortcut\\'s event handler was called');\n+  }\n+\n+  ['@test it handles whitelisted bound modifier keys']() {\n+    let editHandlerWasCalled = false;\n+    let shortcutHandlerWasCalled = false;\n+\n+    let ExampleComponent = Component.extend({\n+      altKey: 'alt',\n+      anyKey: 'any',\n+      actions: {\n+        edit() { editHandlerWasCalled = true; },\n+        shortcut() { shortcutHandlerWasCalled = true; }\n+      }\n+    });\n+\n+    this.registerComponent('example-component', {\n+      ComponentClass: ExampleComponent,\n+      template: '<a href=\"#\" {{action \"edit\" allowedKeys=altKey}}>click me</a> <div {{action \"shortcut\" allowedKeys=anyKey}}>click me too</div>'\n+    });\n+\n+    this.render('{{example-component}}');\n+\n+    this.runTask(() => {\n+      let event = jQuery.Event('click');\n+      event.altKey = true;\n+      this.$('a[data-ember-action]').trigger(event);\n+    });\n+\n+    this.assert.equal(editHandlerWasCalled, true, 'the event handler was called');\n+\n+    this.runTask(() => {\n+      let event = jQuery.Event('click');\n+      event.ctrlKey = true;\n+      this.$('div[data-ember-action]').trigger(event);\n+    });\n+\n+    this.assert.equal(shortcutHandlerWasCalled, true, 'the \"any\" shortcut\\'s event handler was called');\n+  }\n+\n+  ['@test it handles whitelisted bound modifier keys with current value']() {\n+    let editHandlerWasCalled = false;\n+    let component;\n+\n+    let ExampleComponent = Component.extend({\n+      init() {\n+        this._super(...arguments);\n+        component = this;\n+      },\n+      acceptedKeys: 'alt',\n+      actions: {\n+        edit() { editHandlerWasCalled = true; }\n+      }\n+    });\n+\n+    this.registerComponent('example-component', {\n+      ComponentClass: ExampleComponent,\n+      template: '<a href=\"#\" {{action \"edit\" allowedKeys=acceptedKeys}}>click me</a>'\n+    });\n+\n+    this.render('{{example-component}}');\n+\n+    this.runTask(() => {\n+      let event = jQuery.Event('click');\n+      event.altKey = true;\n+      this.$('a[data-ember-action]').trigger(event);\n+    });\n+\n+    this.assert.equal(editHandlerWasCalled, true, 'the event handler was called');\n+\n+    editHandlerWasCalled = false;\n+\n+    this.runTask(() => {\n+      component.set('acceptedKeys', '');\n+    });\n+\n+    this.runTask(() => {\n+      let event = jQuery.Event('click');\n+      this.$('div[data-ember-action]').trigger(event);\n+    });\n+\n+    this.assert.equal(editHandlerWasCalled, false, 'the event handler was not called');\n+  }\n+\n+  ['@test should be able to use action more than once for the same event within a view']() {\n+    let editHandlerWasCalled = false;\n+    let deleteHandlerWasCalled = false;\n+    let originalHandlerWasCalled = false;\n+    let component;\n+\n+    let ExampleComponent = Component.extend({\n+      init() {\n+        this._super(...arguments);\n+        component = this;\n+      },\n+      actions: {\n+        edit() { editHandlerWasCalled = true; },\n+        'delete'() { deleteHandlerWasCalled = true; }\n+      },\n+      click() { originalHandlerWasCalled = true; }\n+    });\n+\n+    this.registerComponent('example-component', {\n+      ComponentClass: ExampleComponent,\n+      template: '<a id=\"edit\" href=\"#\" {{action \"edit\"}}>edit</a><a id=\"delete\" href=\"#\" {{action \"delete\"}}>delete</a>'\n+    });\n+\n+    this.render('{{example-component}}');\n+\n+    this.runTask(() => {\n+      this.$('#edit').click();\n+    });\n+\n+    this.assert.equal(editHandlerWasCalled, true, 'the edit action was called');\n+    this.assert.equal(deleteHandlerWasCalled, false, 'the delete action was not called');\n+    this.assert.equal(originalHandlerWasCalled, true, 'the click handler was called (due to bubbling)');\n+\n+    editHandlerWasCalled = deleteHandlerWasCalled = originalHandlerWasCalled = false;\n+\n+    this.runTask(() => {\n+      this.$('#delete').click();\n+    });\n+\n+    this.assert.equal(editHandlerWasCalled, false, 'the edit action was not called');\n+    this.assert.equal(deleteHandlerWasCalled, true, 'the delete action was called');\n+    this.assert.equal(originalHandlerWasCalled, true, 'the click handler was called (due to bubbling)');\n+\n+    editHandlerWasCalled = deleteHandlerWasCalled = originalHandlerWasCalled = false;\n+\n+    this.runTask(() => {\n+      component.$().click();\n+    });\n+\n+    this.assert.equal(editHandlerWasCalled, false, 'the edit action was not called');\n+    this.assert.equal(deleteHandlerWasCalled, false, 'the delete action was not called');\n+    this.assert.equal(originalHandlerWasCalled, true, 'the click handler was called');\n+  }\n+\n+  ['@test the event should not bubble if `bubbles=false` is passed']() {\n+    let editHandlerWasCalled = false;\n+    let deleteHandlerWasCalled = false;\n+    let originalHandlerWasCalled = false;\n+    let component;\n+\n+    let ExampleComponent = Component.extend({\n+      init() {\n+        this._super(...arguments);\n+        component = this;\n+      },\n+      actions: {\n+        edit() { editHandlerWasCalled = true; },\n+        'delete'() { deleteHandlerWasCalled = true; }\n+      },\n+      click() { originalHandlerWasCalled = true; }\n+    });\n+\n+    this.registerComponent('example-component', {\n+      ComponentClass: ExampleComponent,\n+      template: '<a id=\"edit\" href=\"#\" {{action \"edit\" bubbles=false}}>edit</a><a id=\"delete\" href=\"#\" {{action \"delete\" bubbles=false}}>delete</a>'\n+    });\n+\n+    this.render('{{example-component}}');\n+\n+    this.runTask(() => {\n+      this.$('#edit').click();\n+    });\n+\n+    this.assert.equal(editHandlerWasCalled, true, 'the edit action was called');\n+    this.assert.equal(deleteHandlerWasCalled, false, 'the delete action was not called');\n+    this.assert.equal(originalHandlerWasCalled, false, 'the click handler was not called');\n+\n+    editHandlerWasCalled = deleteHandlerWasCalled = originalHandlerWasCalled = false;\n+\n+    this.runTask(() => {\n+      this.$('#delete').click();\n+    });\n+\n+    this.assert.equal(editHandlerWasCalled, false, 'the edit action was not called');\n+    this.assert.equal(deleteHandlerWasCalled, true, 'the delete action was called');\n+    this.assert.equal(originalHandlerWasCalled, false, 'the click handler was not called');\n+\n+    editHandlerWasCalled = deleteHandlerWasCalled = originalHandlerWasCalled = false;\n+\n+    this.runTask(() => {\n+      component.$().click();\n+    });\n+\n+    this.assert.equal(editHandlerWasCalled, false, 'the edit action was not called');\n+    this.assert.equal(deleteHandlerWasCalled, false, 'the delete action was not called');\n+    this.assert.equal(originalHandlerWasCalled, true, 'the click handler was called');\n+  }\n+\n+  ['@test the event should not bubble if `bubbles=false` is passed bound']() {\n+    let editHandlerWasCalled = false;\n+    let deleteHandlerWasCalled = false;\n+    let originalHandlerWasCalled = false;\n+    let component;\n+\n+    let ExampleComponent = Component.extend({\n+      init() {\n+        this._super(...arguments);\n+        component = this;\n+      },\n+      isFalse: false,\n+      actions: {\n+        edit() { editHandlerWasCalled = true; },\n+        'delete'() { deleteHandlerWasCalled = true; }\n+      },\n+      click() { originalHandlerWasCalled = true; }\n+    });\n+\n+    this.registerComponent('example-component', {\n+      ComponentClass: ExampleComponent,\n+      template: '<a id=\"edit\" href=\"#\" {{action \"edit\" bubbles=isFalse}}>edit</a><a id=\"delete\" href=\"#\" {{action \"delete\" bubbles=isFalse}}>delete</a>'\n+    });\n+\n+    this.render('{{example-component}}');\n+\n+    this.runTask(() => {\n+      this.$('#edit').click();\n+    });\n+\n+    this.assert.equal(editHandlerWasCalled, true, 'the edit action was called');\n+    this.assert.equal(deleteHandlerWasCalled, false, 'the delete action was not called');\n+    this.assert.equal(originalHandlerWasCalled, false, 'the click handler was not called');\n+\n+    editHandlerWasCalled = deleteHandlerWasCalled = originalHandlerWasCalled = false;\n+\n+    this.runTask(() => {\n+      this.$('#delete').click();\n+    });\n+\n+    this.assert.equal(editHandlerWasCalled, false, 'the edit action was not called');\n+    this.assert.equal(deleteHandlerWasCalled, true, 'the delete action was called');\n+    this.assert.equal(originalHandlerWasCalled, false, 'the click handler was not called');\n+\n+    editHandlerWasCalled = deleteHandlerWasCalled = originalHandlerWasCalled = false;\n+\n+    this.runTask(() => {\n+      component.$().click();\n+    });\n+\n+    this.assert.equal(editHandlerWasCalled, false, 'the edit action was not called');\n+    this.assert.equal(deleteHandlerWasCalled, false, 'the delete action was not called');\n+    this.assert.equal(originalHandlerWasCalled, true, 'the click handler was called');\n+  }\n+\n+  ['@test the bubbling depends on the bound parameter']() {\n+    let editHandlerWasCalled = false;\n+    let originalHandlerWasCalled = false;\n+    let component;\n+\n+    let ExampleComponent = Component.extend({\n+      init() {\n+        this._super(...arguments);\n+        component = this;\n+      },\n+      shouldBubble: false,\n+      actions: {\n+        edit() { editHandlerWasCalled = true; }\n+      },\n+      click() { originalHandlerWasCalled = true; }\n+    });\n+\n+    this.registerComponent('example-component', {\n+      ComponentClass: ExampleComponent,\n+      template: '<a id=\"edit\" href=\"#\" {{action \"edit\" bubbles=shouldBubble}}>edit</a>'\n+    });\n+\n+    this.render('{{example-component}}');\n+\n+    this.runTask(() => {\n+      this.$('#edit').click();\n+    });\n+\n+    this.assert.equal(editHandlerWasCalled, true, 'the edit action was called');\n+    this.assert.equal(originalHandlerWasCalled, false, 'the click handler was not called');\n+\n+    editHandlerWasCalled = originalHandlerWasCalled = false;\n+\n+    this.runTask(() => {\n+      component.set('shouldBubble', true);\n+    });\n+\n+    this.runTask(() => {\n+      this.$('#edit').click();\n+    });\n+\n+    this.assert.equal(editHandlerWasCalled, true, 'the edit action was called');\n+    this.assert.equal(originalHandlerWasCalled, true, 'the click handler was called');\n+  }\n+\n+  ['@test it should work properly in an #each block']() {\n+    let editHandlerWasCalled = false;\n+\n+    let ExampleComponent = Component.extend({\n+      items: emberA([1, 2, 3, 4]),\n+      actions: {\n+        edit() { editHandlerWasCalled = true; }\n+      }\n+    });\n+\n+    this.registerComponent('example-component', {\n+      ComponentClass: ExampleComponent,\n+      template: '{{#each items as |item|}}<a href=\"#\" {{action \"edit\"}}>click me</a>{{/each}}'\n+    });\n+\n+    this.render('{{example-component}}');\n+\n+    this.runTask(() => {\n+      this.$('a').click();\n+    });\n+\n+    this.assert.equal(editHandlerWasCalled, true, 'the event handler was called');\n+  }\n+\n+  ['@test it should work properly in a {{#with foo as |bar|}} block']() {\n+    let editHandlerWasCalled = false;\n+\n+    let ExampleComponent = Component.extend({\n+      something: { ohai: 'there' },\n+      actions: {\n+        edit() { editHandlerWasCalled = true; }\n+      }\n+    });\n+\n+    this.registerComponent('example-component', {\n+      ComponentClass: ExampleComponent,\n+      template: '{{#with something as |somethingElse|}}<a href=\"#\" {{action \"edit\"}}>click me</a>{{/with}}'\n+    });\n+\n+    this.render('{{example-component}}');\n+\n+    this.runTask(() => {\n+      this.$('a').click();\n+    });\n+\n+    this.assert.equal(editHandlerWasCalled, true, 'the event handler was called');\n+  }\n+\n+  ['@glimmer it should unregister event handlers on teardown, but not on rerender']() {\n+    let editHandlerWasCalled = false;\n+    let component;\n+\n+    let ExampleComponent = Component.extend({\n+      init() {\n+        this._super(...arguments);\n+        component = this;\n+      },\n+      active: true,\n+      actions: {\n+        edit() { editHandlerWasCalled = true; }\n+      }\n+    });\n+\n+    this.registerComponent('example-component', {\n+      ComponentClass: ExampleComponent,\n+      template: '{{#if active}}<a href=\"#\" {{action \"edit\"}}>click me</a>{{/if}}'\n+    });\n+\n+    this.render('{{example-component}}');\n+\n+    let previousAttributes = getActionAttributes(component.$('a').get(0));\n+\n+    this.rerender();\n+\n+    let rerenderedAttributes = getActionAttributes(component.$('a').get(0));\n+\n+    this.runTask(() => {\n+      component.set('active', false);\n+    });\n+\n+    this.runTask(() => {\n+      component.set('active', true);\n+    });\n+\n+    let newAttributes = getActionAttributes(component.$('a').get(0));\n+\n+    this.assert.deepEqual(previousAttributes, rerenderedAttributes, 'the same action id is used across rerenders');\n+    this.assert.notDeepEqual(previousAttributes, newAttributes, 'the action id is regenerated when the action is torn down');\n+  }\n+\n+  ['@skip it should unregister event handlers on rerender']() {\n+    // TODO: Port this test for HTMLBars only.\n+  }\n+\n+  ['@skip it should unregister event handlers on inside virtual views']() {","path":"packages/ember-glimmer/tests/integration/helpers/element-action-test.js","position":649,"original_position":649,"commit_id":"277e8eecad44f6e72a89b0df99aea5e20363a6ae","original_commit_id":"277e8eecad44f6e72a89b0df99aea5e20363a6ae","user":{"login":"zackthehuman","id":203712,"avatar_url":"https://avatars.githubusercontent.com/u/203712?v=3","gravatar_id":"","url":"https://api.github.com/users/zackthehuman","html_url":"https://github.com/zackthehuman","followers_url":"https://api.github.com/users/zackthehuman/followers","following_url":"https://api.github.com/users/zackthehuman/following{/other_user}","gists_url":"https://api.github.com/users/zackthehuman/gists{/gist_id}","starred_url":"https://api.github.com/users/zackthehuman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zackthehuman/subscriptions","organizations_url":"https://api.github.com/users/zackthehuman/orgs","repos_url":"https://api.github.com/users/zackthehuman/repos","events_url":"https://api.github.com/users/zackthehuman/events{/privacy}","received_events_url":"https://api.github.com/users/zackthehuman/received_events","type":"User","site_admin":false},"body":"I'm gonna restore the existing test and mark as `@htmlbars` for now.","created_at":"2016-05-09T23:13:55Z","updated_at":"2016-05-09T23:13:55Z","html_url":"https://github.com/emberjs/ember.js/pull/13451#discussion_r62589135","pull_request_url":"https://api.github.com/repos/emberjs/ember.js/pulls/13451","_links":{"self":{"href":"https://api.github.com/repos/emberjs/ember.js/pulls/comments/62589135"},"html":{"href":"https://github.com/emberjs/ember.js/pull/13451#discussion_r62589135"},"pull_request":{"href":"https://api.github.com/repos/emberjs/ember.js/pulls/13451"}}},"pull_request":{"url":"https://api.github.com/repos/emberjs/ember.js/pulls/13451","id":68945608,"html_url":"https://github.com/emberjs/ember.js/pull/13451","diff_url":"https://github.com/emberjs/ember.js/pull/13451.diff","patch_url":"https://github.com/emberjs/ember.js/pull/13451.patch","issue_url":"https://api.github.com/repos/emberjs/ember.js/issues/13451","number":13451,"state":"open","locked":false,"title":"Element Actions for Glimmer","user":{"login":"zackthehuman","id":203712,"avatar_url":"https://avatars.githubusercontent.com/u/203712?v=3","gravatar_id":"","url":"https://api.github.com/users/zackthehuman","html_url":"https://github.com/zackthehuman","followers_url":"https://api.github.com/users/zackthehuman/followers","following_url":"https://api.github.com/users/zackthehuman/following{/other_user}","gists_url":"https://api.github.com/users/zackthehuman/gists{/gist_id}","starred_url":"https://api.github.com/users/zackthehuman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zackthehuman/subscriptions","organizations_url":"https://api.github.com/users/zackthehuman/orgs","repos_url":"https://api.github.com/users/zackthehuman/repos","events_url":"https://api.github.com/users/zackthehuman/events{/privacy}","received_events_url":"https://api.github.com/users/zackthehuman/received_events","type":"User","site_admin":false},"body":"Port existing element actions code into Glimmer. ","created_at":"2016-05-04T23:00:52Z","updated_at":"2016-05-09T23:13:55Z","closed_at":null,"merged_at":null,"merge_commit_sha":"6d44dd3ef7b6ea768cb8453adf005e82df7b3675","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/emberjs/ember.js/pulls/13451/commits","review_comments_url":"https://api.github.com/repos/emberjs/ember.js/pulls/13451/comments","review_comment_url":"https://api.github.com/repos/emberjs/ember.js/pulls/comments{/number}","comments_url":"https://api.github.com/repos/emberjs/ember.js/issues/13451/comments","statuses_url":"https://api.github.com/repos/emberjs/ember.js/statuses/277e8eecad44f6e72a89b0df99aea5e20363a6ae","head":{"label":"zackthehuman:glimmer-actions","ref":"glimmer-actions","sha":"277e8eecad44f6e72a89b0df99aea5e20363a6ae","user":{"login":"zackthehuman","id":203712,"avatar_url":"https://avatars.githubusercontent.com/u/203712?v=3","gravatar_id":"","url":"https://api.github.com/users/zackthehuman","html_url":"https://github.com/zackthehuman","followers_url":"https://api.github.com/users/zackthehuman/followers","following_url":"https://api.github.com/users/zackthehuman/following{/other_user}","gists_url":"https://api.github.com/users/zackthehuman/gists{/gist_id}","starred_url":"https://api.github.com/users/zackthehuman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zackthehuman/subscriptions","organizations_url":"https://api.github.com/users/zackthehuman/orgs","repos_url":"https://api.github.com/users/zackthehuman/repos","events_url":"https://api.github.com/users/zackthehuman/events{/privacy}","received_events_url":"https://api.github.com/users/zackthehuman/received_events","type":"User","site_admin":false},"repo":{"id":54286266,"name":"ember.js","full_name":"zackthehuman/ember.js","owner":{"login":"zackthehuman","id":203712,"avatar_url":"https://avatars.githubusercontent.com/u/203712?v=3","gravatar_id":"","url":"https://api.github.com/users/zackthehuman","html_url":"https://github.com/zackthehuman","followers_url":"https://api.github.com/users/zackthehuman/followers","following_url":"https://api.github.com/users/zackthehuman/following{/other_user}","gists_url":"https://api.github.com/users/zackthehuman/gists{/gist_id}","starred_url":"https://api.github.com/users/zackthehuman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zackthehuman/subscriptions","organizations_url":"https://api.github.com/users/zackthehuman/orgs","repos_url":"https://api.github.com/users/zackthehuman/repos","events_url":"https://api.github.com/users/zackthehuman/events{/privacy}","received_events_url":"https://api.github.com/users/zackthehuman/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/zackthehuman/ember.js","description":"Ember.js - A JavaScript framework for creating ambitious web applications","fork":true,"url":"https://api.github.com/repos/zackthehuman/ember.js","forks_url":"https://api.github.com/repos/zackthehuman/ember.js/forks","keys_url":"https://api.github.com/repos/zackthehuman/ember.js/keys{/key_id}","collaborators_url":"https://api.github.com/repos/zackthehuman/ember.js/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/zackthehuman/ember.js/teams","hooks_url":"https://api.github.com/repos/zackthehuman/ember.js/hooks","issue_events_url":"https://api.github.com/repos/zackthehuman/ember.js/issues/events{/number}","events_url":"https://api.github.com/repos/zackthehuman/ember.js/events","assignees_url":"https://api.github.com/repos/zackthehuman/ember.js/assignees{/user}","branches_url":"https://api.github.com/repos/zackthehuman/ember.js/branches{/branch}","tags_url":"https://api.github.com/repos/zackthehuman/ember.js/tags","blobs_url":"https://api.github.com/repos/zackthehuman/ember.js/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/zackthehuman/ember.js/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/zackthehuman/ember.js/git/refs{/sha}","trees_url":"https://api.github.com/repos/zackthehuman/ember.js/git/trees{/sha}","statuses_url":"https://api.github.com/repos/zackthehuman/ember.js/statuses/{sha}","languages_url":"https://api.github.com/repos/zackthehuman/ember.js/languages","stargazers_url":"https://api.github.com/repos/zackthehuman/ember.js/stargazers","contributors_url":"https://api.github.com/repos/zackthehuman/ember.js/contributors","subscribers_url":"https://api.github.com/repos/zackthehuman/ember.js/subscribers","subscription_url":"https://api.github.com/repos/zackthehuman/ember.js/subscription","commits_url":"https://api.github.com/repos/zackthehuman/ember.js/commits{/sha}","git_commits_url":"https://api.github.com/repos/zackthehuman/ember.js/git/commits{/sha}","comments_url":"https://api.github.com/repos/zackthehuman/ember.js/comments{/number}","issue_comment_url":"https://api.github.com/repos/zackthehuman/ember.js/issues/comments{/number}","contents_url":"https://api.github.com/repos/zackthehuman/ember.js/contents/{+path}","compare_url":"https://api.github.com/repos/zackthehuman/ember.js/compare/{base}...{head}","merges_url":"https://api.github.com/repos/zackthehuman/ember.js/merges","archive_url":"https://api.github.com/repos/zackthehuman/ember.js/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/zackthehuman/ember.js/downloads","issues_url":"https://api.github.com/repos/zackthehuman/ember.js/issues{/number}","pulls_url":"https://api.github.com/repos/zackthehuman/ember.js/pulls{/number}","milestones_url":"https://api.github.com/repos/zackthehuman/ember.js/milestones{/number}","notifications_url":"https://api.github.com/repos/zackthehuman/ember.js/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/zackthehuman/ember.js/labels{/name}","releases_url":"https://api.github.com/repos/zackthehuman/ember.js/releases{/id}","deployments_url":"https://api.github.com/repos/zackthehuman/ember.js/deployments","created_at":"2016-03-19T20:41:49Z","updated_at":"2016-03-19T20:41:53Z","pushed_at":"2016-05-07T06:33:12Z","git_url":"git://github.com/zackthehuman/ember.js.git","ssh_url":"git@github.com:zackthehuman/ember.js.git","clone_url":"https://github.com/zackthehuman/ember.js.git","svn_url":"https://github.com/zackthehuman/ember.js","homepage":"http://www.emberjs.com","size":32943,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"emberjs:master","ref":"master","sha":"5cbdd24b721514fc6f491443f65455323e66476f","user":{"login":"emberjs","id":1253363,"avatar_url":"https://avatars.githubusercontent.com/u/1253363?v=3","gravatar_id":"","url":"https://api.github.com/users/emberjs","html_url":"https://github.com/emberjs","followers_url":"https://api.github.com/users/emberjs/followers","following_url":"https://api.github.com/users/emberjs/following{/other_user}","gists_url":"https://api.github.com/users/emberjs/gists{/gist_id}","starred_url":"https://api.github.com/users/emberjs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/emberjs/subscriptions","organizations_url":"https://api.github.com/users/emberjs/orgs","repos_url":"https://api.github.com/users/emberjs/repos","events_url":"https://api.github.com/users/emberjs/events{/privacy}","received_events_url":"https://api.github.com/users/emberjs/received_events","type":"Organization","site_admin":false},"repo":{"id":1801829,"name":"ember.js","full_name":"emberjs/ember.js","owner":{"login":"emberjs","id":1253363,"avatar_url":"https://avatars.githubusercontent.com/u/1253363?v=3","gravatar_id":"","url":"https://api.github.com/users/emberjs","html_url":"https://github.com/emberjs","followers_url":"https://api.github.com/users/emberjs/followers","following_url":"https://api.github.com/users/emberjs/following{/other_user}","gists_url":"https://api.github.com/users/emberjs/gists{/gist_id}","starred_url":"https://api.github.com/users/emberjs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/emberjs/subscriptions","organizations_url":"https://api.github.com/users/emberjs/orgs","repos_url":"https://api.github.com/users/emberjs/repos","events_url":"https://api.github.com/users/emberjs/events{/privacy}","received_events_url":"https://api.github.com/users/emberjs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/emberjs/ember.js","description":"Ember.js - A JavaScript framework for creating ambitious web applications","fork":false,"url":"https://api.github.com/repos/emberjs/ember.js","forks_url":"https://api.github.com/repos/emberjs/ember.js/forks","keys_url":"https://api.github.com/repos/emberjs/ember.js/keys{/key_id}","collaborators_url":"https://api.github.com/repos/emberjs/ember.js/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/emberjs/ember.js/teams","hooks_url":"https://api.github.com/repos/emberjs/ember.js/hooks","issue_events_url":"https://api.github.com/repos/emberjs/ember.js/issues/events{/number}","events_url":"https://api.github.com/repos/emberjs/ember.js/events","assignees_url":"https://api.github.com/repos/emberjs/ember.js/assignees{/user}","branches_url":"https://api.github.com/repos/emberjs/ember.js/branches{/branch}","tags_url":"https://api.github.com/repos/emberjs/ember.js/tags","blobs_url":"https://api.github.com/repos/emberjs/ember.js/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/emberjs/ember.js/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/emberjs/ember.js/git/refs{/sha}","trees_url":"https://api.github.com/repos/emberjs/ember.js/git/trees{/sha}","statuses_url":"https://api.github.com/repos/emberjs/ember.js/statuses/{sha}","languages_url":"https://api.github.com/repos/emberjs/ember.js/languages","stargazers_url":"https://api.github.com/repos/emberjs/ember.js/stargazers","contributors_url":"https://api.github.com/repos/emberjs/ember.js/contributors","subscribers_url":"https://api.github.com/repos/emberjs/ember.js/subscribers","subscription_url":"https://api.github.com/repos/emberjs/ember.js/subscription","commits_url":"https://api.github.com/repos/emberjs/ember.js/commits{/sha}","git_commits_url":"https://api.github.com/repos/emberjs/ember.js/git/commits{/sha}","comments_url":"https://api.github.com/repos/emberjs/ember.js/comments{/number}","issue_comment_url":"https://api.github.com/repos/emberjs/ember.js/issues/comments{/number}","contents_url":"https://api.github.com/repos/emberjs/ember.js/contents/{+path}","compare_url":"https://api.github.com/repos/emberjs/ember.js/compare/{base}...{head}","merges_url":"https://api.github.com/repos/emberjs/ember.js/merges","archive_url":"https://api.github.com/repos/emberjs/ember.js/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/emberjs/ember.js/downloads","issues_url":"https://api.github.com/repos/emberjs/ember.js/issues{/number}","pulls_url":"https://api.github.com/repos/emberjs/ember.js/pulls{/number}","milestones_url":"https://api.github.com/repos/emberjs/ember.js/milestones{/number}","notifications_url":"https://api.github.com/repos/emberjs/ember.js/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/emberjs/ember.js/labels{/name}","releases_url":"https://api.github.com/repos/emberjs/ember.js/releases{/id}","deployments_url":"https://api.github.com/repos/emberjs/ember.js/deployments","created_at":"2011-05-25T23:39:40Z","updated_at":"2016-05-09T20:03:46Z","pushed_at":"2016-05-09T20:47:25Z","git_url":"git://github.com/emberjs/ember.js.git","ssh_url":"git@github.com:emberjs/ember.js.git","clone_url":"https://github.com/emberjs/ember.js.git","svn_url":"https://github.com/emberjs/ember.js","homepage":"http://www.emberjs.com","size":68017,"stargazers_count":16179,"watchers_count":16179,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":3478,"mirror_url":null,"open_issues_count":240,"forks":3478,"open_issues":240,"watchers":16179,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/emberjs/ember.js/pulls/13451"},"html":{"href":"https://github.com/emberjs/ember.js/pull/13451"},"issue":{"href":"https://api.github.com/repos/emberjs/ember.js/issues/13451"},"comments":{"href":"https://api.github.com/repos/emberjs/ember.js/issues/13451/comments"},"review_comments":{"href":"https://api.github.com/repos/emberjs/ember.js/pulls/13451/comments"},"review_comment":{"href":"https://api.github.com/repos/emberjs/ember.js/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/emberjs/ember.js/pulls/13451/commits"},"statuses":{"href":"https://api.github.com/repos/emberjs/ember.js/statuses/277e8eecad44f6e72a89b0df99aea5e20363a6ae"}}}}