hippo-fw 0.9.6 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/client/hippo/components/asset.jsx +22 -2
  3. data/client/hippo/components/asset.scss +1 -1
  4. data/client/hippo/components/data-list.jsx +38 -27
  5. data/client/hippo/components/data-list/data-list.scss +2 -0
  6. data/client/hippo/components/data-table.jsx +4 -2
  7. data/client/hippo/components/data-table/formatters.js +7 -0
  8. data/client/hippo/components/data-table/table-styles.scss +10 -0
  9. data/client/hippo/components/date-time.jsx +93 -133
  10. data/client/hippo/components/date-time.scss +1 -36
  11. data/client/hippo/components/form/api.js +4 -3
  12. data/client/hippo/components/form/fields.jsx +7 -1
  13. data/client/hippo/components/form/fields/date-wrapper.jsx +4 -4
  14. data/client/hippo/components/icon.jsx +10 -1
  15. data/client/hippo/components/query-builder.jsx +6 -1
  16. data/client/hippo/components/record-finder/query-layer.jsx +1 -1
  17. data/client/hippo/components/save-button.jsx +55 -0
  18. data/client/hippo/components/text-editor.jsx +10 -9
  19. data/client/hippo/components/text-editor/text-editor.scss +0 -1
  20. data/client/hippo/components/time-zone-select.jsx +60 -0
  21. data/client/hippo/models/asset.js +10 -5
  22. data/client/hippo/models/base.js +1 -1
  23. data/client/hippo/models/pub_sub.js +22 -67
  24. data/client/hippo/models/pub_sub/channel.js +28 -8
  25. data/client/hippo/models/pub_sub/map.js +57 -0
  26. data/client/hippo/models/query/array-result.js +5 -4
  27. data/client/hippo/models/query/field.js +19 -3
  28. data/client/hippo/models/system-setting.js +16 -1
  29. data/client/hippo/models/tenant.js +8 -7
  30. data/client/hippo/screens/system-settings.jsx +10 -12
  31. data/client/hippo/screens/user-management/edit-form.jsx +10 -11
  32. data/client/hippo/workspace/index.jsx +6 -3
  33. data/client/hippo/workspace/menu-option.jsx +2 -5
  34. data/client/hippo/workspace/menu.jsx +13 -1
  35. data/client/hippo/workspace/styles.scss +11 -26
  36. data/command-reference-files/initial/Gemfile +1 -1
  37. data/command-reference-files/model/client/appy-app/models/test_test.js +1 -1
  38. data/command-reference-files/model/spec/server/models/test_test_spec.rb +10 -0
  39. data/lib/hippo/api/cable.rb +0 -2
  40. data/lib/hippo/command/generate_model.rb +2 -3
  41. data/lib/hippo/spec_helper.rb +4 -2
  42. data/lib/hippo/tenant.rb +7 -1
  43. data/lib/hippo/version.rb +1 -1
  44. data/package-lock.json +60 -46
  45. data/package.json +5 -2
  46. data/spec/client/components/__snapshots__/record-finder.spec.jsx.snap +1 -0
  47. data/spec/client/components/__snapshots__/time-zone-select.spec.jsx.snap +48 -0
  48. data/spec/client/components/form.spec.jsx +7 -0
  49. data/spec/client/components/time-zone-select.spec.jsx +11 -0
  50. data/spec/client/models/pub_sub.spec.js +1 -3
  51. data/spec/client/models/pub_sub/channel.spec.js +45 -0
  52. data/spec/client/models/system-setting.spec.js +14 -0
  53. data/spec/client/workspace/__snapshots__/menu.spec.jsx.snap +9 -9
  54. data/spec/server/api/tenant_change_spec.rb +1 -1
  55. data/templates/client/models/model.js +1 -1
  56. data/templates/spec/factories/model.rb +6 -0
  57. data/templates/spec/server/model_spec.rb +4 -4
  58. data/views/hippo_root_view.erb +4 -0
  59. metadata +11 -10
  60. data/client/hippo/components/date-time/calendar.jsx +0 -113
  61. data/client/hippo/components/date-time/date-time-drop.jsx +0 -75
  62. data/client/hippo/components/date-time/date-time.scss +0 -157
  63. data/client/hippo/components/date-time/time.jsx +0 -119
  64. data/client/hippo/workspace/foo.js +0 -0
  65. data/command-reference-files/model/spec/fixtures/appy-app/test_test.yml +0 -11
  66. data/command-reference-files/model/spec/server/test_test_spec.rb +0 -10
  67. data/spec/client/components/date-time.spec.jsx +0 -20
@@ -1,37 +1,12 @@
1
1
  @import '../styles/global';
2
2
  @import '~grommet/scss/aruba/index';
3
3
 
4
- html {
5
- font-family: $brand-font-family;
6
- }
7
-
8
- a.anchor {
9
- display: block;
10
- }
11
-
12
- .request-access fieldset:first-of-type {
13
- padding-top: 0;
14
- }
15
-
16
- pre {
17
- width: 100%;
18
- max-width: 100%;
19
- }
20
-
21
- .generic-branding {
22
- display: none;
23
- }
24
-
25
- .content-pane .grommetux-tabs {
26
- padding-left: 20px;
27
- padding-right: 20px;
28
- }
29
-
30
4
  .screen {
31
5
  flex: 1;
32
6
  flex-direction: column;
33
7
  padding: 0.5rem;
34
8
  display: none;
9
+ min-height: min-content; min-height: -moz-min-content; min-height: -webkit-min-content;
35
10
  &.is-active {
36
11
  display: flex;
37
12
  }
@@ -53,3 +28,13 @@ pre {
53
28
  display:none;
54
29
  }
55
30
  }
31
+
32
+ .screen-selection-menu {
33
+ .grommetux-anchor > .icon {
34
+ margin-right: 0.5rem;
35
+ }
36
+ }
37
+
38
+ .screens-wrapper {
39
+ overflow: hidden;
40
+ }
@@ -3,7 +3,7 @@ source 'https://rubygems.org'
3
3
  # For development while Hippo is evolving track master branch
4
4
  gem "hippo-fw", git: "https://github.com/argosity/hippo", branch: 'master'
5
5
 
6
- # gem "hippo", '0.9.5'
6
+ # gem "hippo", '0.9.6'
7
7
 
8
8
  gem "rake"
9
9
  gem 'puma'
@@ -1,5 +1,5 @@
1
1
  import {
2
- BaseModel, identifiedBy, identifier, belongsTo, hasMany, field, computed
2
+ BaseModel, identifiedBy, identifier, field, session, belongsTo, hasMany,
3
3
  } from './base';
4
4
 
5
5
  @identifiedBy('appy-app/test_test')
@@ -0,0 +1,10 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe AppyApp::TestTest do
4
+
5
+ it "can be instantiated" do
6
+ model = AppyApp::TestTest.new
7
+ expect(model).to be_an(AppyApp::TestTest)
8
+ end
9
+
10
+ end
@@ -15,8 +15,6 @@ module Hippo
15
15
 
16
16
  def connect
17
17
  token = request.params['token']
18
- Hippo.logger_debug("NEW WS CONN: #{token}")
19
-
20
18
  begin
21
19
  self.current_user = User.for_jwt_token(token) if token
22
20
  rescue JWT::DecodeError
@@ -31,9 +31,8 @@ module Hippo
31
31
 
32
32
  def create_model
33
33
  template "lib/namespace/model.rb", "lib/#{identifier}/models/#{file_name}.rb"
34
- template "spec/server/model_spec.rb", "spec/server/#{file_name}_spec.rb"
35
- template "spec/fixtures/namespace/model.yml",
36
- "spec/fixtures/#{identifier}/#{file_name}.yml"
34
+ template "spec/server/model_spec.rb", "spec/server/models/#{file_name}_spec.rb"
35
+ template "spec/factories/model.rb", "spec/factories/#{file_name}.rb"
37
36
  end
38
37
 
39
38
  def create_client
@@ -87,8 +87,10 @@ RSpec.configure do |config|
87
87
  config.around(:each) do |example|
88
88
  Hippo.logger.level = ::Logger::WARN
89
89
  TEST_TENANT.perform do
90
- DatabaseCleaner.cleaning do
91
- example.run
90
+ Hippo::User.scoped_to(TEST_TENANT.users.first) do
91
+ DatabaseCleaner.cleaning do
92
+ example.run
93
+ end
92
94
  end
93
95
  end
94
96
  end
@@ -3,7 +3,7 @@ require 'activerecord-multi-tenant'
3
3
  module Hippo
4
4
  # Tenant
5
5
  class Tenant < Hippo::Model
6
- validates :slug, uniqueness: { case_sensitive: false }
6
+ validates :slug, uniqueness: true
7
7
  validates :name, :presence => { message: 'for company' }
8
8
  validates :email, :presence => true
9
9
 
@@ -12,6 +12,8 @@ module Hippo
12
12
 
13
13
  before_validation :auto_assign_slug, on: :create
14
14
 
15
+ before_save :downcase_slug
16
+
15
17
  def domain
16
18
  self.slug + '.' + Hippo.config.website_domain
17
19
  end
@@ -49,5 +51,9 @@ module Hippo
49
51
  end
50
52
  end
51
53
 
54
+ def downcase_slug
55
+ self.slug = self.slug.downcase.gsub(/\W/, '')
56
+ end
57
+
52
58
  end
53
59
  end
@@ -1,5 +1,5 @@
1
1
  module Hippo
2
2
 
3
- VERSION = "0.9.6"
3
+ VERSION = "0.9.7"
4
4
 
5
5
  end
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hippo-fw",
3
- "version": "0.9.5",
3
+ "version": "0.9.6",
4
4
  "lockfileVersion": 1,
5
5
  "dependencies": {
6
6
  "@braintree/browser-detection": {
@@ -2304,6 +2304,11 @@
2304
2304
  "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz",
2305
2305
  "integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y="
2306
2306
  },
2307
+ "flatpickr": {
2308
+ "version": "3.0.7",
2309
+ "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-3.0.7.tgz",
2310
+ "integrity": "sha512-wcs8au1XU5Sqm3KQLY7SN7W3DDzrUv9Lp364rZyZpXkqMYpE4XezKKMEhwjMUotEMNdfj4/pd2573FLyFZrIjQ=="
2311
+ },
2307
2312
  "flatten": {
2308
2313
  "version": "1.0.2",
2309
2314
  "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz",
@@ -4729,51 +4734,9 @@
4729
4734
  "integrity": "sha1-aureASDMP3i6pXGVAxYwoK6PE88="
4730
4735
  },
4731
4736
  "mobx-decorated-models": {
4732
- "version": "0.6.3",
4733
- "resolved": "https://registry.npmjs.org/mobx-decorated-models/-/mobx-decorated-models-0.6.3.tgz",
4734
- "integrity": "sha512-8tAjfbV/Qqyt/7RanGdTQjIOJj5d5ZLsC8hS6eTKK4xGf4unudT2E0nCocbl09VBT79e9HzwgwI1s9iKlRNyRg==",
4735
- "dependencies": {
4736
- "acorn": {
4737
- "version": "5.1.1",
4738
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.1.tgz",
4739
- "integrity": "sha512-vOk6uEMctu0vQrvuSqFdJyqj1Q0S5VTDL79qtjo+DhRr+1mmaD+tluFSCZqhvi/JUhXSzoZN2BhtstaPEeE8cw=="
4740
- },
4741
- "ajv": {
4742
- "version": "5.2.2",
4743
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.2.2.tgz",
4744
- "integrity": "sha1-R8aNaehvXZUxA7AHSpQw3GPaXjk="
4745
- },
4746
- "cross-spawn": {
4747
- "version": "5.1.0",
4748
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
4749
- "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk="
4750
- },
4751
- "eslint": {
4752
- "version": "4.4.0",
4753
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.4.0.tgz",
4754
- "integrity": "sha1-o+FT5wS2T3gpDvA1kklOq6Io07w="
4755
- },
4756
- "espree": {
4757
- "version": "3.5.0",
4758
- "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.0.tgz",
4759
- "integrity": "sha1-mDWGJb3QVYYeon4oZ+pyn69GPY0="
4760
- },
4761
- "esprima": {
4762
- "version": "4.0.0",
4763
- "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
4764
- "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw=="
4765
- },
4766
- "js-yaml": {
4767
- "version": "3.9.1",
4768
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.1.tgz",
4769
- "integrity": "sha512-CbcG379L1e+mWBnLvHWWeLs8GyV/EMw862uLI3c+GxVyDHWZcjZinwuBd3iW2pgxgIlksW/1vNJa4to+RvDOww=="
4770
- },
4771
- "pluralize": {
4772
- "version": "4.0.0",
4773
- "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-4.0.0.tgz",
4774
- "integrity": "sha1-WbcIwcAZCi9pLxx2GMRGsFL9F2I="
4775
- }
4776
- }
4737
+ "version": "0.6.5",
4738
+ "resolved": "https://registry.npmjs.org/mobx-decorated-models/-/mobx-decorated-models-0.6.5.tgz",
4739
+ "integrity": "sha512-Vx7QfGYP0uBlkT0Rqn3SewzR/pIZmVrLk9lOO/qwyT5kc4dHrdn+z/F4+CxHxVxYSLQsxOKwFOizKWDZYnUcTQ=="
4777
4740
  },
4778
4741
  "mobx-persist": {
4779
4742
  "version": "0.3.3",
@@ -4795,6 +4758,11 @@
4795
4758
  "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz",
4796
4759
  "integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8="
4797
4760
  },
4761
+ "moment-timezone": {
4762
+ "version": "0.5.13",
4763
+ "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.13.tgz",
4764
+ "integrity": "sha1-mc5cfYJyYusPH3AgRBd/YHRde5A="
4765
+ },
4798
4766
  "mousetrap": {
4799
4767
  "version": "1.6.1",
4800
4768
  "resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.1.tgz",
@@ -5837,6 +5805,52 @@
5837
5805
  "resolved": "https://registry.npmjs.org/react-sidebar/-/react-sidebar-2.3.2.tgz",
5838
5806
  "integrity": "sha1-7BQL6opvX6PY6npWR5ZltEz0+c8="
5839
5807
  },
5808
+ "react-swipeable-views": {
5809
+ "version": "0.12.8",
5810
+ "resolved": "https://registry.npmjs.org/react-swipeable-views/-/react-swipeable-views-0.12.8.tgz",
5811
+ "integrity": "sha512-VCPjjP9WTQejM6Yy46mzzHu9H6p5g/IuQMm6TUOEjj8d82a9ii+YAgWOR2KCR5ew/4lqD4WKX2hD6Ix+Lq80Eg=="
5812
+ },
5813
+ "react-swipeable-views-core": {
5814
+ "version": "0.12.8",
5815
+ "resolved": "https://registry.npmjs.org/react-swipeable-views-core/-/react-swipeable-views-core-0.12.8.tgz",
5816
+ "integrity": "sha512-VudJhi43DwgLFh25aeNPxSwONzyErPFRg13Hm3YcSwSjwhkvNf3oficuPT7/Kd6qxorDj046D8Nkunl/DG5srA=="
5817
+ },
5818
+ "react-swipeable-views-utils": {
5819
+ "version": "0.12.8",
5820
+ "resolved": "https://registry.npmjs.org/react-swipeable-views-utils/-/react-swipeable-views-utils-0.12.8.tgz",
5821
+ "integrity": "sha512-NHXFbB8Bq1RnuBn5IyZoSTofDHuwXbwbkdFIeTFCozeHvLeIHm6A2rRKy2CTYZggNRUukgHZrsGqRU+H1M2iSQ==",
5822
+ "dependencies": {
5823
+ "react-event-listener": {
5824
+ "version": "0.5.0",
5825
+ "resolved": "https://registry.npmjs.org/react-event-listener/-/react-event-listener-0.5.0.tgz",
5826
+ "integrity": "sha1-2CEFE1Vz4Yfj2QDRgVCliCMEuNE=",
5827
+ "dependencies": {
5828
+ "babel-runtime": {
5829
+ "version": "6.26.0",
5830
+ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
5831
+ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4="
5832
+ },
5833
+ "fbjs": {
5834
+ "version": "0.8.14",
5835
+ "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.14.tgz",
5836
+ "integrity": "sha1-0dviviVMNakeCfMfnNUKQLKg7Rw=",
5837
+ "dependencies": {
5838
+ "core-js": {
5839
+ "version": "1.2.7",
5840
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
5841
+ "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
5842
+ }
5843
+ }
5844
+ }
5845
+ }
5846
+ },
5847
+ "regenerator-runtime": {
5848
+ "version": "0.11.0",
5849
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz",
5850
+ "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A=="
5851
+ }
5852
+ }
5853
+ },
5840
5854
  "react-tap-event-plugin": {
5841
5855
  "version": "2.0.1",
5842
5856
  "resolved": "https://registry.npmjs.org/react-tap-event-plugin/-/react-tap-event-plugin-2.0.1.tgz",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hippo-fw",
3
- "version": "0.9.5",
3
+ "version": "0.9.6",
4
4
  "description": "Hippo is a framework for easily writing single page web applications",
5
5
  "main": "client/hippo/index.js",
6
6
  "repository": "https://github.com/argosity/hippo",
@@ -39,6 +39,7 @@
39
39
  "eslint": "^4.2.0",
40
40
  "eslint-config-argosity": "^1.1.5",
41
41
  "file-loader": "^0.11.2",
42
+ "flatpickr": "^3.0.7",
42
43
  "flexboxgrid": "^6.3.1",
43
44
  "grommet": "^1.5.0",
44
45
  "history": "^4.6.3",
@@ -53,9 +54,10 @@
53
54
  "lodash": "^4.17.4",
54
55
  "loglevel": "^1.4.1",
55
56
  "mobx": "^3.2.1",
56
- "mobx-decorated-models": "^0.6.3",
57
+ "mobx-decorated-models": "^0.6.5",
57
58
  "mobx-persist": "^0.3.3",
58
59
  "mobx-react": "^4.2.2",
60
+ "moment-timezone": "^0.5.13",
59
61
  "node-sass": "^4.5.0",
60
62
  "ory-editor": "^0.2.12",
61
63
  "pluralize": "^6.0.0",
@@ -77,6 +79,7 @@
77
79
  "react-router": "^4.1.2",
78
80
  "react-router-dom": "^4.1.2",
79
81
  "react-sidebar": "^2.3.0",
82
+ "react-swipeable-views": "^0.12.8",
80
83
  "react-tap-event-plugin": "^2.0.1",
81
84
  "react-test-renderer": "^15.6.1",
82
85
  "react-tippy": "^1.0.2",
@@ -30,6 +30,7 @@ exports[`RecordFinder Component renders 1`] = `
30
30
  onKeyDown={[Function]}
31
31
  onKeyPress={[Function]}
32
32
  placeholder={undefined}
33
+ tabIndex={0}
33
34
  type="text"
34
35
  value=""
35
36
  />
@@ -0,0 +1,48 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`TimeZone Component matches snapshot 1`] = `
4
+ <div
5
+ className="grommetux-select"
6
+ onClick={[Function]}
7
+ >
8
+ <input
9
+ className="grommetux-input grommetux-select__input"
10
+ placeholder="None"
11
+ readOnly={true}
12
+ value="America/Chicago"
13
+ />
14
+ <button
15
+ aria-label="Select Icon"
16
+ className="grommetux-button grommetux-button--plain grommetux-select__control"
17
+ disabled={false}
18
+ href={undefined}
19
+ onBlur={[Function]}
20
+ onClick={[Function]}
21
+ onFocus={[Function]}
22
+ onMouseDown={[Function]}
23
+ onMouseUp={[Function]}
24
+ type="button"
25
+ >
26
+ <span
27
+ className="grommetux-button__icon"
28
+ >
29
+ <svg
30
+ aria-label="caret-down"
31
+ className="grommetux-control-icon grommetux-control-icon-caret-down grommetux-control-icon--responsive"
32
+ height="24px"
33
+ role="img"
34
+ version="1.1"
35
+ viewBox="0 0 24 24"
36
+ width="24px"
37
+ >
38
+ <polygon
39
+ fill="none"
40
+ points="22 8 12 20 2 8"
41
+ stroke="#000"
42
+ strokeWidth="2"
43
+ />
44
+ </svg>
45
+ </span>
46
+ </button>
47
+ </div>
48
+ `;
@@ -28,6 +28,13 @@ describe('Form Validation functions', () => {
28
28
  expect(form.isValid).toBe(true);
29
29
  });
30
30
 
31
+ it('sets field values when they check in', () => {
32
+ const form = new FormState();
33
+ form.set({ foo: 'bar' });
34
+ form.setField('foo', { label: 'Foo' });
35
+ expect(form.fields.get('foo').value).toEqual('bar');
36
+ });
37
+
31
38
  it('builds tests using blank', () => {
32
39
  const test = nonBlank();
33
40
  expect(test.message).toEqual('is required');
@@ -0,0 +1,11 @@
1
+ import React from 'react'; // eslint-disable-line no-unused-vars
2
+ import TZ from 'hippo/components/time-zone-select';
3
+ import { Snapshot } from 'hippo/testing/screens';
4
+
5
+
6
+ describe('TimeZone Component', () => {
7
+ it('matches snapshot', () => {
8
+ const oc = jest.fn();
9
+ expect(Snapshot(<TZ onChange={oc} value="America/Chicago" />)).toMatchSnapshot();
10
+ });
11
+ });
@@ -3,10 +3,10 @@ import PubSubChannel from 'hippo/models/pub_sub/channel';
3
3
  import Config from 'hippo/config';
4
4
  import { Ship, Container } from '../test-models';
5
5
 
6
+ jest.mock('hippo/models/pub_sub/channel');
6
7
  jest.mock('hippo/user', () => ({
7
8
  isLoggedIn: true,
8
9
  }));
9
- jest.mock('hippo/models/pub_sub/channel');
10
10
  jest.mock('hippo/config');
11
11
 
12
12
  describe('PubSub', () => {
@@ -15,8 +15,6 @@ describe('PubSub', () => {
15
15
  const ship = new Ship();
16
16
  const container = new Container({ id: '2' });
17
17
  onBoot();
18
- expect(PubSubChannel.prototype.subscribe)
19
- .not.toHaveBeenCalledWith('test/boat/test');
20
18
  expect(PubSubChannel.prototype.subscribe)
21
19
  .not.toHaveBeenCalledWith('test/container/2');
22
20
  observePubSub(ship, container);
@@ -0,0 +1,45 @@
1
+ import PubSubChannel from 'hippo/models/pub_sub/channel';
2
+
3
+ describe('PubSub Channel', () => {
4
+ it('subscribes/unsubscribes', () => {
5
+ const onModelChange = jest.fn();
6
+ const perform = jest.fn();
7
+ const received = jest.fn();
8
+ const chan = new PubSubChannel({
9
+ onModelChange,
10
+ cable: {
11
+ subscriptions: {
12
+ create: jest.fn(() => ({
13
+ received,
14
+ perform,
15
+ })),
16
+ },
17
+ },
18
+ });
19
+ const spy1 = jest.fn();
20
+ const channel = 'foo/bar/1';
21
+ chan.subscribe(channel, spy1);
22
+ expect(chan.callbacks.get(channel)).toHaveLength(1);
23
+ const msg = { channel: `ps:${channel}` };
24
+
25
+ const spy2 = jest.fn();
26
+ chan.subscribe(channel, spy2);
27
+
28
+ chan.received(msg);
29
+ expect(spy1).toHaveBeenCalledWith(msg);
30
+ expect(spy2).toHaveBeenCalledWith(msg);
31
+
32
+ chan.unsubscribe(channel, spy1);
33
+ chan.received(msg);
34
+ expect(spy1).toHaveBeenCalledTimes(1);
35
+ expect(spy2).toHaveBeenCalledTimes(2);
36
+
37
+ expect(onModelChange).not.toHaveBeenCalled();
38
+ chan.unsubscribe(channel, spy2);
39
+
40
+ chan.received(msg);
41
+ expect(onModelChange).toHaveBeenCalledWith('foo/bar', '1', {});
42
+ expect(spy1).toHaveBeenCalledTimes(1);
43
+ expect(spy2).toHaveBeenCalledTimes(2);
44
+ });
45
+ });