Jelajahi Sumber

Merge pull request #21 from ryangjchandler/feature/event-bus

Add core event bus
Ryan Chandler 5 tahun lalu
induk
melakukan
cce94f4346
9 mengubah file dengan 104 tambahan dan 3 penghapusan
  1. 0 1
      dist/spruce.js
  2. 0 0
      dist/spruce.js.map
  3. 0 1
      dist/spruce.module.js
  4. 0 0
      dist/spruce.module.js.map
  5. 0 1
      dist/spruce.umd.js
  6. 0 0
      dist/spruce.umd.js.map
  7. 26 0
      src/bus.js
  8. 11 0
      src/index.js
  9. 67 0
      tests/bus.spec.js

File diff ditekan karena terlalu besar
+ 0 - 1
dist/spruce.js


File diff ditekan karena terlalu besar
+ 0 - 0
dist/spruce.js.map


File diff ditekan karena terlalu besar
+ 0 - 1
dist/spruce.module.js


File diff ditekan karena terlalu besar
+ 0 - 0
dist/spruce.module.js.map


File diff ditekan karena terlalu besar
+ 0 - 1
dist/spruce.umd.js


File diff ditekan karena terlalu besar
+ 0 - 0
dist/spruce.umd.js.map


+ 26 - 0
src/bus.js

@@ -0,0 +1,26 @@
+export default {
+    events: {},
+
+    on(name, callback) {
+        if (! this.events[name]) {
+            this.events[name] = []
+        }
+
+        this.events[name].push(callback)
+    },
+
+    emit(name, data = {}) {
+        if (this.events[name]) {
+            this.events[name].forEach(callback => {
+                callback(data)
+            })
+        }
+
+        // TODO: deal with this for IE11 :(
+        // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Browser_compatibility#Polyfill
+        window.dispatchEvent(new CustomEvent(`spruce:${name}`, {
+            detail: data,
+            bubbles: true
+        }))
+    }
+}

+ 11 - 0
src/index.js

@@ -1,11 +1,14 @@
 import { domReady, buildInitExpression } from './utils'
 import { createObservable } from './observable'
+import EventBus from './bus'
 
 const Spruce = {
     options: {
         globalStoreVariable: false,
     },
 
+    events: EventBus,
+
     stores: {},
 
     subscribers: [],
@@ -57,6 +60,14 @@ const Spruce = {
 
     config(options = {}) {
         this.options = Object.assign(this.options, options)
+    },
+
+    on(name, callback) {
+        this.events.on(name, callback)
+    },
+
+    emit(name, data = {}) {
+        this.events.emit(name, { ...data, store: this.stores })
     }
 }
 

+ 67 - 0
tests/bus.spec.js

@@ -0,0 +1,67 @@
+import Spruce from '../dist/spruce'
+import Alpine from 'alpinejs'
+import { waitFor } from '@testing-library/dom'
+
+beforeEach(() => {
+    Spruce.subscribers = []
+})
+
+beforeAll(() => {
+    window.Spruce = Spruce
+})
+
+/* Spruce.on() */
+
+test('.on() > can be used to register event listeners', () => {
+    Spruce.on('example', (event) => {})
+
+    expect(Spruce.events.events.hasOwnProperty('example')).toBeTruthy()
+})
+
+test('.on() > listener can access store', () => {
+    Spruce.store('foo', {
+        bar: 'bob'
+    })
+
+    let fixture = undefined;
+
+    Spruce.on('example', (detail) => {
+        fixture = detail
+    })
+
+    Spruce.emit('example')
+
+    expect(fixture.store).toEqual(Spruce.stores)
+})
+
+/* Spruce.emit() */
+
+test('.emit() > will run registered listeners', () => {
+    let fixture = 0;
+
+    Spruce.on('example', (detail) => {
+        fixture =+ detail.inc
+    })
+
+    Spruce.emit('example', { inc: 10 })
+
+    expect(fixture).toEqual(10)
+})
+
+test('.emit() > will dispatch browser event to window with spruce: prefix', async () => {
+    document.body.innerHTML = `
+        <div x-data="{ foo: 'bar' }" @spruce:example.window="foo = $event.detail.foo">
+            <span x-text="foo"></span>
+        </div>
+    `
+
+    Alpine.start()
+
+    expect(document.querySelector('span').innerText).toEqual('bar')
+
+    Spruce.emit('example', { foo: 'car' })
+
+    await waitFor(() => {
+        expect(document.querySelector('span').innerText).toEqual('car')
+    })
+})

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini