cozy-bar 1.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/.eslintrc.json +7 -0
  2. package/.github/auto-merge.yml +7 -0
  3. package/.nvmrc +1 -0
  4. package/.transifexrc.tpl +4 -0
  5. package/.travis.yml +28 -0
  6. package/.tx/config +8 -0
  7. package/CHANGELOG.md +493 -0
  8. package/CODEOWNERS +2 -0
  9. package/CONTRIBUTING.md +135 -0
  10. package/LICENSE +21 -0
  11. package/README.md +172 -0
  12. package/babel.config.js +3 -0
  13. package/config/aliases/globalReact.js +1 -0
  14. package/config/aliases/globalReactDOM.js +1 -0
  15. package/config/webpack.config.analyzer.js +10 -0
  16. package/config/webpack.config.base.js +61 -0
  17. package/config/webpack.config.dev.js +16 -0
  18. package/config/webpack.config.extract.js +84 -0
  19. package/config/webpack.config.inline-styles.js +82 -0
  20. package/config/webpack.config.jsx.js +14 -0
  21. package/config/webpack.config.prod.js +18 -0
  22. package/config/webpack.js +31 -0
  23. package/config/webpack.vars.js +11 -0
  24. package/dist/cozy-bar.css +9445 -0
  25. package/dist/cozy-bar.css.map +1 -0
  26. package/dist/cozy-bar.js +122668 -0
  27. package/dist/cozy-bar.js.map +1 -0
  28. package/dist/cozy-bar.min.css +9 -0
  29. package/dist/cozy-bar.min.css.map +1 -0
  30. package/dist/cozy-bar.min.js +57 -0
  31. package/dist/cozy-bar.min.js.map +1 -0
  32. package/dist/cozy-bar.mobile.js +123719 -0
  33. package/dist/cozy-bar.mobile.js.map +1 -0
  34. package/dist/cozy-bar.mobile.min.js +57 -0
  35. package/dist/cozy-bar.mobile.min.js.map +1 -0
  36. package/docs/dev.md +20 -0
  37. package/examples/Procfile +3 -0
  38. package/examples/icon.png +0 -0
  39. package/examples/index.html +7 -0
  40. package/examples/index.jsx +122 -0
  41. package/examples/logs.js +3 -0
  42. package/package.json +163 -0
  43. package/postcss.config.js +23 -0
  44. package/public/fonts/Lato-Bold.woff2 +0 -0
  45. package/public/fonts/Lato-Regular.woff2 +0 -0
  46. package/public/fonts.css +13 -0
  47. package/public/icon-type-folder-32.png +0 -0
  48. package/public/index.html +63 -0
  49. package/renovate.json +5 -0
  50. package/src/assets/icons/16/icon-claudy.svg +5 -0
  51. package/src/assets/icons/16/icon-cozy-16.svg +1 -0
  52. package/src/assets/icons/16/icon-cube-16.svg +6 -0
  53. package/src/assets/icons/16/icon-logout-16.svg +3 -0
  54. package/src/assets/icons/16/icon-magnifier-16.svg +6 -0
  55. package/src/assets/icons/16/icon-people-16.svg +3 -0
  56. package/src/assets/icons/16/icon-phone-16.svg +3 -0
  57. package/src/assets/icons/16/icon-question-mark-16.svg +3 -0
  58. package/src/assets/icons/16/icon-storage-16.svg +3 -0
  59. package/src/assets/icons/24/icon-arrow-left.svg +3 -0
  60. package/src/assets/icons/32/icon-claudy.svg +1 -0
  61. package/src/assets/icons/apps/icon-collect.svg +25 -0
  62. package/src/assets/icons/apps/icon-drive.svg +17 -0
  63. package/src/assets/icons/apps/icon-market-soon.svg +25 -0
  64. package/src/assets/icons/apps/icon-photos.svg +19 -0
  65. package/src/assets/icons/apps/icon-soon.svg +21 -0
  66. package/src/assets/icons/apps/icon-store.svg +19 -0
  67. package/src/assets/icons/claudyActions/icon-bills.svg +6 -0
  68. package/src/assets/icons/claudyActions/icon-laptop.svg +7 -0
  69. package/src/assets/icons/claudyActions/icon-phone.svg +8 -0
  70. package/src/assets/icons/claudyActions/icon-question-mark.svg +6 -0
  71. package/src/assets/icons/comingsoon/icon-bank.svg +12 -0
  72. package/src/assets/icons/comingsoon/icon-sante.svg +12 -0
  73. package/src/assets/icons/comingsoon/icon-store.svg +6 -0
  74. package/src/assets/icons/icon-cozy.svg +3 -0
  75. package/src/assets/icons/icon-shield.svg +3 -0
  76. package/src/assets/icons/spinner.svg +4 -0
  77. package/src/assets/sprites/icon-apps.svg +1 -0
  78. package/src/assets/sprites/icon-cozy-home.svg +16 -0
  79. package/src/components/Apps/AppItem.jsx +117 -0
  80. package/src/components/Apps/AppItemPlaceholder.jsx +12 -0
  81. package/src/components/Apps/AppNavButtons.jsx +88 -0
  82. package/src/components/Apps/AppsContent.jsx +89 -0
  83. package/src/components/Apps/ButtonCozyHome.jsx +30 -0
  84. package/src/components/Apps/ButtonCozyHome.spec.jsx +53 -0
  85. package/src/components/Apps/IconCozyHome.jsx +24 -0
  86. package/src/components/Apps/index.jsx +81 -0
  87. package/src/components/Banner.jsx +41 -0
  88. package/src/components/Bar.jsx +293 -0
  89. package/src/components/Bar.spec.jsx +133 -0
  90. package/src/components/Claudy.jsx +81 -0
  91. package/src/components/Drawer.jsx +227 -0
  92. package/src/components/Drawer.spec.jsx +98 -0
  93. package/src/components/SearchBar.jsx +358 -0
  94. package/src/components/Settings/SettingsContent.jsx +145 -0
  95. package/src/components/Settings/StorageData.jsx +29 -0
  96. package/src/components/Settings/helper.js +8 -0
  97. package/src/components/Settings/index.jsx +218 -0
  98. package/src/components/SupportModal.jsx +59 -0
  99. package/src/components/__snapshots__/Bar.spec.jsx.snap +302 -0
  100. package/src/config/claudyActions.yaml +14 -0
  101. package/src/config/persistWhitelist.yaml +2 -0
  102. package/src/dom.js +80 -0
  103. package/src/index.jsx +235 -0
  104. package/src/index.spec.jsx +34 -0
  105. package/src/lib/api/helpers.js +13 -0
  106. package/src/lib/api/index.jsx +145 -0
  107. package/src/lib/exceptions.js +89 -0
  108. package/src/lib/expiringMemoize.js +13 -0
  109. package/src/lib/icon.js +77 -0
  110. package/src/lib/importIcons.js +14 -0
  111. package/src/lib/intents.js +16 -0
  112. package/src/lib/logger.js +6 -0
  113. package/src/lib/middlewares/appsI18n.js +57 -0
  114. package/src/lib/realtime.js +43 -0
  115. package/src/lib/reducers/apps.js +175 -0
  116. package/src/lib/reducers/apps.spec.js +59 -0
  117. package/src/lib/reducers/content.js +50 -0
  118. package/src/lib/reducers/context.js +83 -0
  119. package/src/lib/reducers/index.js +73 -0
  120. package/src/lib/reducers/locale.js +22 -0
  121. package/src/lib/reducers/settings.js +111 -0
  122. package/src/lib/reducers/theme.js +48 -0
  123. package/src/lib/reducers/unserializable.js +26 -0
  124. package/src/lib/stack-client.js +401 -0
  125. package/src/lib/stack.js +79 -0
  126. package/src/lib/store/index.js +54 -0
  127. package/src/locales/de.json +57 -0
  128. package/src/locales/en.json +57 -0
  129. package/src/locales/es.json +57 -0
  130. package/src/locales/fr.json +57 -0
  131. package/src/locales/it.json +57 -0
  132. package/src/locales/ja.json +57 -0
  133. package/src/locales/nl_NL.json +57 -0
  134. package/src/locales/pl.json +57 -0
  135. package/src/locales/ru.json +57 -0
  136. package/src/locales/sq.json +57 -0
  137. package/src/locales/zh_CN.json +57 -0
  138. package/src/proptypes/index.js +10 -0
  139. package/src/queries/index.js +16 -0
  140. package/src/styles/apps.css +248 -0
  141. package/src/styles/banner.css +64 -0
  142. package/src/styles/bar.css +106 -0
  143. package/src/styles/base.css +41 -0
  144. package/src/styles/claudy.css +99 -0
  145. package/src/styles/drawer.css +126 -0
  146. package/src/styles/index.styl +33 -0
  147. package/src/styles/indicators.css +58 -0
  148. package/src/styles/nav.css +81 -0
  149. package/src/styles/navigation_item.css +39 -0
  150. package/src/styles/searchbar.css +158 -0
  151. package/src/styles/settings.css +44 -0
  152. package/src/styles/storage.css +22 -0
  153. package/src/styles/supportModal.css +20 -0
  154. package/src/styles/theme.styl +25 -0
  155. package/test/__mocks__/fileMock.js +3 -0
  156. package/test/__snapshots__/index.spec.js.snap +41 -0
  157. package/test/components/AppItem.spec.jsx +113 -0
  158. package/test/components/AppsContent.spec.jsx +116 -0
  159. package/test/components/Settings/helper.spec.js +23 -0
  160. package/test/components/__snapshots__/AppsContent.spec.jsx.snap +90 -0
  161. package/test/index.spec.js +24 -0
  162. package/test/jestLib/I18n.js +15 -0
  163. package/test/jestLib/setup.js +14 -0
  164. package/test/lib/__snapshots__/api.spec.jsx.snap +67 -0
  165. package/test/lib/__snapshots__/stack.spec.js.snap +3 -0
  166. package/test/lib/api.spec.jsx +142 -0
  167. package/test/lib/mockStackClient.js +7 -0
  168. package/test/lib/stack-client/stack-client.appiconprops.spec.js +65 -0
  169. package/test/lib/stack-client/stack-client.compare.spec.js +20 -0
  170. package/test/lib/stack-client/stack-client.cozyfetchjson.spec.js +46 -0
  171. package/test/lib/stack-client/stack-client.cozyurl.spec.js +29 -0
  172. package/test/lib/stack-client/stack-client.getapp.spec.js +72 -0
  173. package/test/lib/stack-client/stack-client.getapps.spec.js +72 -0
  174. package/test/lib/stack-client/stack-client.getcontext.spec.js +96 -0
  175. package/test/lib/stack-client/stack-client.getstoragedata.spec.js +85 -0
  176. package/test/lib/stack-client/stack-client.init.spec.js +56 -0
  177. package/test/lib/stack-client/stack-client.intents.spec.js +27 -0
  178. package/test/lib/stack-client/stack-client.logout.spec.js +40 -0
  179. package/test/lib/stack.spec.js +60 -0
  180. package/test/store/__snapshots__/index.spec.js.snap +14 -0
  181. package/test/store/index.spec.js +41 -0
@@ -0,0 +1,72 @@
1
+ import CozyClient from 'cozy-client'
2
+ import stack from 'lib/stack-client'
3
+ import mockStackClient from '../mockStackClient'
4
+
5
+ describe('stack client', () => {
6
+ describe('getApp', () => {
7
+ const slug = 'testapp'
8
+
9
+ const stackClient = {
10
+ ...mockStackClient,
11
+ fetch: jest.fn().mockResolvedValue({
12
+ status: 200,
13
+ headers: { get: () => 'application/json' },
14
+ json: () => {
15
+ // example from https://docs.cozy.io/en/cozy-stack/apps/
16
+ return {
17
+ data: {
18
+ id: '4cfbd8be-8968-11e6-9708-ef55b7c20863',
19
+ type: 'io.cozy.apps',
20
+ meta: {
21
+ rev: '2-bbfb0fc32dfcdb5333b28934f195b96a'
22
+ },
23
+ attributes: {
24
+ name: 'calendar',
25
+ state: 'ready',
26
+ slug: 'calendar'
27
+ },
28
+ links: {
29
+ self: '/apps/calendar',
30
+ icon: '/apps/calendar/icon',
31
+ related: 'https://calendar.alice.example.com/'
32
+ }
33
+ }
34
+ }
35
+ }
36
+ })
37
+ }
38
+
39
+ const cozyClient = new CozyClient({
40
+ stackClient
41
+ })
42
+
43
+ const params = {
44
+ cozyClient,
45
+ onCreateApp: function() {},
46
+ onDeleteApp: function() {}
47
+ }
48
+
49
+ beforeAll(async () => {
50
+ await stack.init(params)
51
+ })
52
+
53
+ afterAll(() => {
54
+ jest.restoreAllMocks()
55
+ })
56
+
57
+ it('should return the `data` content', async () => {
58
+ const data = await stack.get.app(slug)
59
+ expect(data.id).toBe('4cfbd8be-8968-11e6-9708-ef55b7c20863')
60
+ })
61
+
62
+ it('should have called cozy-client', async () => {
63
+ await stack.get.app(slug)
64
+ expect(cozyClient.getStackClient().fetch).toHaveBeenCalled()
65
+ })
66
+
67
+ it('should not throw', async () => {
68
+ expect(() => stack.get.app(slug)).not.toThrow()
69
+ await expect(stack.get.app(slug)).resolves.not.toBe(false)
70
+ })
71
+ })
72
+ })
@@ -0,0 +1,72 @@
1
+ import CozyClient from 'cozy-client'
2
+ import stack from 'lib/stack-client'
3
+ import mockStackClient from '../mockStackClient'
4
+
5
+ describe('stack client', () => {
6
+ describe('getApps', () => {
7
+ const stackClient = {
8
+ ...mockStackClient,
9
+ fetch: jest.fn().mockResolvedValue({
10
+ status: 200,
11
+ headers: { get: () => 'application/json' },
12
+ json: () => {
13
+ // example from https://docs.cozy.io/en/cozy-stack/apps/
14
+ return {
15
+ data: [
16
+ {
17
+ id: '4cfbd8be-8968-11e6-9708-ef55b7c20863',
18
+ type: 'io.cozy.apps',
19
+ meta: {
20
+ rev: '2-bbfb0fc32dfcdb5333b28934f195b96a'
21
+ },
22
+ attributes: {
23
+ name: 'calendar',
24
+ state: 'ready',
25
+ slug: 'calendar'
26
+ },
27
+ links: {
28
+ self: '/apps/calendar',
29
+ icon: '/apps/calendar/icon',
30
+ related: 'https://calendar.alice.example.com/'
31
+ }
32
+ }
33
+ ]
34
+ }
35
+ }
36
+ })
37
+ }
38
+
39
+ const cozyClient = new CozyClient({
40
+ stackClient
41
+ })
42
+
43
+ const params = {
44
+ cozyClient,
45
+ onCreateApp: function() {},
46
+ onDeleteApp: function() {}
47
+ }
48
+
49
+ beforeAll(async () => {
50
+ await stack.init(params)
51
+ })
52
+
53
+ afterAll(() => {
54
+ jest.restoreAllMocks()
55
+ })
56
+
57
+ it('should return the `data` content', async () => {
58
+ const data = await stack.get.apps()
59
+ expect(data[0].id).toBe('4cfbd8be-8968-11e6-9708-ef55b7c20863')
60
+ })
61
+
62
+ it('should have called cozy-client', async () => {
63
+ await stack.get.apps()
64
+ expect(cozyClient.getStackClient().fetch).toHaveBeenCalled()
65
+ })
66
+
67
+ it('should not throw', async () => {
68
+ expect(() => stack.get.apps()).not.toThrow()
69
+ await expect(stack.get.apps()).resolves.not.toBe(false)
70
+ })
71
+ })
72
+ })
@@ -0,0 +1,96 @@
1
+ import stack from 'lib/stack-client'
2
+ import CozyClient from 'cozy-client'
3
+ import { NotFoundException, UnauthorizedStackException } from 'lib/exceptions'
4
+ import mockStackClient from '../mockStackClient'
5
+
6
+ describe('stack client', () => {
7
+ describe('getContext', () => {
8
+ const context404 = new NotFoundException()
9
+
10
+ const context500 = new UnauthorizedStackException()
11
+
12
+ const context200 = {
13
+ status: 200,
14
+ headers: { get: () => 'application/json' },
15
+ json: () => {
16
+ return {
17
+ data: {
18
+ type: 'io.cozy.settings',
19
+ id: 'io.cozy.settings.context',
20
+ attributes: {
21
+ default_redirection: 'drive/#/files',
22
+ help_link: 'https://forum.cozy.io/',
23
+ onboarded_redirection: 'collect/#/discovery/?intro'
24
+ },
25
+ links: {
26
+ self: '/settings/context'
27
+ }
28
+ }
29
+ }
30
+ }
31
+ }
32
+
33
+ const stackClient = {
34
+ ...mockStackClient,
35
+ fetch: jest.fn()
36
+ }
37
+
38
+ const cozyClient = new CozyClient({
39
+ stackClient
40
+ })
41
+
42
+ const params = {
43
+ cozyClient,
44
+ onCreateApp: function() {},
45
+ onDeleteApp: function() {}
46
+ }
47
+
48
+ beforeAll(async () => {
49
+ await stack.init(params)
50
+ })
51
+
52
+ beforeEach(() => {
53
+ stackClient.fetch.mockClear()
54
+ })
55
+
56
+ afterAll(() => {
57
+ jest.restoreAllMocks()
58
+ })
59
+
60
+ it('should not cache 500 errors', async () => {
61
+ stackClient.fetch.mockRejectedValue(context500)
62
+ await stack.get.context().catch(() => undefined)
63
+ await stack.get.context().catch(() => undefined)
64
+ expect(stackClient.fetch).toHaveBeenCalledTimes(2)
65
+ })
66
+
67
+ it('should return the raw json content', async () => {
68
+ stackClient.fetch.mockResolvedValue(context200)
69
+ const data = await stack.get.context()
70
+ expect(data.data.id).toBe('io.cozy.settings.context')
71
+ })
72
+
73
+ it('should be cached', async () => {
74
+ stackClient.fetch.mockResolvedValue(context200)
75
+ const data1 = await stack.get.context()
76
+ // If we did not called mockClear, we
77
+ // would have 0 or 1 call to the mock
78
+ // depending on preceding tests.
79
+ // Here we always should expect 0
80
+ // in the next lines
81
+ stackClient.fetch.mockClear()
82
+ stackClient.fetch.mockRejectedValue(context404)
83
+ const data2 = await stack.get.context()
84
+ expect(data1).toBe(data2)
85
+ expect(stackClient.fetch).toHaveBeenCalledTimes(0)
86
+ })
87
+
88
+ xit('should return the default value for a 404', async () => {
89
+ // @TODO deactivated because the previous tests already
90
+ // set the cache and the tested function is statefull
91
+ stackClient.fetch.mockRejectedValue(context404)
92
+ const data = await stack.get.context()
93
+ expect(data).toEqual({})
94
+ })
95
+ })
96
+ })
@@ -0,0 +1,85 @@
1
+ import stack from 'lib/stack-client'
2
+ import CozyClient from 'cozy-client'
3
+ import mockStackClient from '../mockStackClient'
4
+
5
+ describe('stack client', () => {
6
+ describe('getStorageData', () => {
7
+ const r200 = {
8
+ status: 200,
9
+ headers: { get: () => 'application/json' },
10
+ json: () => {
11
+ return {
12
+ data: {
13
+ type: 'io.cozy.settings',
14
+ id: 'io.cozy.settings.disk-usage',
15
+ attributes: {
16
+ is_limited: true,
17
+ quota: '123456789',
18
+ used: '12345678'
19
+ }
20
+ }
21
+ }
22
+ }
23
+ }
24
+
25
+ const r200noquota = {
26
+ status: 200,
27
+ headers: { get: () => 'application/json' },
28
+ json: () => {
29
+ return {
30
+ data: {
31
+ type: 'io.cozy.settings',
32
+ id: 'io.cozy.settings.disk-usage',
33
+ attributes: {
34
+ is_limited: false,
35
+ used: '2000111222333' // 2To
36
+ }
37
+ }
38
+ }
39
+ }
40
+ }
41
+
42
+ const stackClient = {
43
+ ...mockStackClient,
44
+ fetch: jest.fn()
45
+ }
46
+
47
+ const cozyClient = new CozyClient({
48
+ stackClient
49
+ })
50
+
51
+ const params = {
52
+ cozyClient,
53
+ onCreateApp: function() {},
54
+ onDeleteApp: function() {}
55
+ }
56
+
57
+ beforeAll(async () => {
58
+ await stack.init(params)
59
+ })
60
+
61
+ beforeEach(() => {
62
+ stackClient.fetch.mockClear()
63
+ stackClient.fetch.mockResolvedValue(r200)
64
+ })
65
+
66
+ afterAll(() => {
67
+ jest.restoreAllMocks()
68
+ })
69
+
70
+ it('should return a decidated object', async () => {
71
+ const data = await stack.get.storageData()
72
+ expect(data.usage).toBe(12345678)
73
+ expect(data.quota).toBe(123456789)
74
+ expect(data.isLimited).toBe(true)
75
+ })
76
+
77
+ it('when no quota is provided, one should be given', async () => {
78
+ stackClient.fetch.mockResolvedValue(r200noquota)
79
+ const data = await stack.get.storageData()
80
+ expect(data.usage).toBe(2000111222333)
81
+ expect(data.quota).toBeGreaterThanOrEqual(data.usage)
82
+ expect(data.isLimited).toBe(false)
83
+ })
84
+ })
85
+ })
@@ -0,0 +1,56 @@
1
+ import stack from 'lib/stack-client'
2
+
3
+ import CozyClient from 'cozy-client'
4
+ import initializeRealtime from 'lib/realtime'
5
+ import mockStackClient from '../mockStackClient'
6
+
7
+ jest.mock('lib/realtime')
8
+ initializeRealtime.mockResolvedValue(Promise.resolve())
9
+
10
+ const { init } = stack
11
+
12
+ describe('stack client', () => {
13
+ describe('init', () => {
14
+ let cozyClient, params
15
+
16
+ const setup = async ({ isLogged, isPublic }) => {
17
+ if (isLogged === undefined) {
18
+ throw new Error('Please define explicity isLogged in your tests.')
19
+ }
20
+
21
+ cozyClient = new CozyClient({
22
+ token: { token: 'mytoken' },
23
+ uri: 'https://test.mycozy.cloud',
24
+ stackClient: mockStackClient
25
+ })
26
+ cozyClient.isLogged = isLogged
27
+ params = {
28
+ cozyClient,
29
+ isPublic,
30
+ onCreate: function() {},
31
+ onDelete: function() {}
32
+ }
33
+ await init(params)
34
+ }
35
+
36
+ afterAll(() => {
37
+ jest.restoreAllMocks()
38
+ })
39
+
40
+ it('should not have initialized the realtime if the user is not logged', async () => {
41
+ await setup({ isLogged: false })
42
+ expect(initializeRealtime).toHaveBeenCalledTimes(0)
43
+ })
44
+
45
+ it('should not have initialized the realtime if the user is not logged even if isPublic is set to false', async () => {
46
+ await setup({ isLogged: false, isPublic: false })
47
+ expect(initializeRealtime).toHaveBeenCalledTimes(0)
48
+ })
49
+
50
+ it('should have initialized the realtime is the user is logged', async () => {
51
+ await setup({ isLogged: true })
52
+ expect(initializeRealtime).toHaveBeenCalled()
53
+ expect(initializeRealtime.mock.calls[0][0].cozyClient).toBe(cozyClient)
54
+ })
55
+ })
56
+ })
@@ -0,0 +1,27 @@
1
+ import { Intents } from 'cozy-interapp'
2
+ import stack from 'lib/stack-client'
3
+ import CozyClient from 'cozy-client'
4
+ import mockStackClient from '../mockStackClient'
5
+
6
+ describe('stack client', () => {
7
+ describe('intents', () => {
8
+ const cozyClient = new CozyClient({
9
+ stackClient: mockStackClient
10
+ })
11
+
12
+ const params = {
13
+ cozyClient,
14
+ onCreateApp: function() {},
15
+ onDeleteApp: function() {}
16
+ }
17
+
18
+ beforeAll(async () => {
19
+ await stack.init(params)
20
+ })
21
+
22
+ it('should return correctly the Intents instance', () => {
23
+ const intents = stack.get.intents()
24
+ expect(intents).toBeInstanceOf(Intents)
25
+ })
26
+ })
27
+ })
@@ -0,0 +1,40 @@
1
+ import stack from 'lib/stack-client'
2
+ import CozyClient from 'cozy-client'
3
+ import mockStackClient from '../mockStackClient'
4
+
5
+ describe('stack client', () => {
6
+ describe('logout', () => {
7
+ const stackClient = {
8
+ ...mockStackClient,
9
+ fetch: jest.fn().mockResolvedValue({ status: 200 })
10
+ }
11
+
12
+ const cozyClient = new CozyClient({
13
+ stackClient
14
+ })
15
+
16
+ const params = {
17
+ cozyClient,
18
+ onCreateApp: function() {},
19
+ onDeleteApp: function() {}
20
+ }
21
+
22
+ beforeAll(async () => {
23
+ await stack.init(params)
24
+ await stack.logout()
25
+ })
26
+
27
+ afterAll(() => {
28
+ jest.restoreAllMocks()
29
+ })
30
+
31
+ it('should have called cozy-client', () => {
32
+ expect(cozyClient.getStackClient().fetch).toHaveBeenCalled()
33
+ })
34
+
35
+ it('should not throw', async () => {
36
+ expect(() => stack.logout()).not.toThrow()
37
+ await expect(stack.logout()).resolves.not.toBe(false)
38
+ })
39
+ })
40
+ })
@@ -0,0 +1,60 @@
1
+ import CozyClient from 'cozy-client'
2
+ import client from 'lib/stack-client.js'
3
+ import stack from 'lib/stack.js'
4
+ import mockStackClient from './mockStackClient'
5
+
6
+ const onCreate = function() {}
7
+ const onDelete = function() {}
8
+
9
+ describe('stack proxy', () => {
10
+ beforeAll(() => {
11
+ jest.spyOn(client, 'init').mockResolvedValue(undefined)
12
+ jest.spyOn(client.get, 'app').mockResolvedValue(undefined)
13
+ })
14
+
15
+ afterAll(() => {
16
+ jest.restoreAllMocks()
17
+ })
18
+
19
+ describe('when initialized with a cozy-client instance', () => {
20
+ const params = {
21
+ cozyClient: new CozyClient({ stackClient: mockStackClient }),
22
+ onCreate: function() {},
23
+ onDelete: function() {}
24
+ }
25
+
26
+ beforeAll(() => {
27
+ jest.clearAllMocks()
28
+
29
+ stack.init(params)
30
+ stack.get.app()
31
+ })
32
+
33
+ it('should call the client stack init', () => {
34
+ expect(client.init).toHaveBeenCalled()
35
+ })
36
+
37
+ it('should forward requests to the cozy-client stack client', () => {
38
+ expect(client.get.app).toHaveBeenCalled()
39
+ })
40
+ })
41
+
42
+ it('should throw error if trying to use the stack before init', () => {
43
+ jest.clearAllMocks()
44
+ jest.resetModules()
45
+ const stack = require('lib/stack').default
46
+
47
+ expect(() => {
48
+ stack.getStack()
49
+ }).toThrowErrorMatchingSnapshot()
50
+
51
+ stack.init({
52
+ cozyClient: new CozyClient({ stackClient: mockStackClient }),
53
+ onCreate,
54
+ onDelete
55
+ })
56
+ expect(() => {
57
+ stack.getStack()
58
+ }).not.toThrowError()
59
+ })
60
+ })
@@ -0,0 +1,14 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`store should keep apps data 1`] = `
4
+ Array [
5
+ Object {
6
+ "isCurrentApp": false,
7
+ "slug": "drive",
8
+ },
9
+ Object {
10
+ "isCurrentApp": false,
11
+ "slug": "banks",
12
+ },
13
+ ]
14
+ `;
@@ -0,0 +1,41 @@
1
+ import getOrCreateStore, { createStore } from 'lib/store'
2
+ import { isFetchingApps, getApps, hasFetched } from 'lib/reducers'
3
+
4
+ describe('store', () => {
5
+ let store
6
+
7
+ beforeEach(() => {
8
+ store = createStore()
9
+ })
10
+
11
+ const getState = () => store.getState()
12
+
13
+ it('should keep fetching status', () => {
14
+ expect(isFetchingApps(getState())).toBe(true)
15
+ store.dispatch({ type: 'FETCH_APPS' })
16
+ expect(isFetchingApps(getState())).toBe(true)
17
+ store.dispatch({ type: 'RECEIVE_APP_LIST', apps: [] })
18
+ expect(isFetchingApps(getState())).toBe(false)
19
+ })
20
+
21
+ it('should keep apps data', () => {
22
+ const apps = [{ slug: 'drive' }, { slug: 'banks' }]
23
+ expect(getApps(getState())).toEqual([])
24
+ store.dispatch({ type: 'RECEIVE_APP_LIST', apps: apps })
25
+ expect(getApps(getState())).toMatchSnapshot()
26
+ })
27
+
28
+ it('should remember it has fetched (ok case)', () => {
29
+ expect(hasFetched(getState())).toEqual(false)
30
+ store.dispatch({ type: 'RECEIVE_APP_LIST', apps: [] })
31
+ expect(hasFetched(getState())).toEqual(true)
32
+ })
33
+ })
34
+
35
+ describe('singleton', () => {
36
+ it('should work as a singleton', () => {
37
+ const store = getOrCreateStore()
38
+ const store2 = getOrCreateStore()
39
+ expect(store).toEqual(store2)
40
+ })
41
+ })