firestore-meilisearch 0.1.0

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 (65) hide show
  1. package/.editorconfig +20 -0
  2. package/.github/ISSUE_TEMPLATE/bug_report.md +26 -0
  3. package/.github/ISSUE_TEMPLATE/feature_request.md +18 -0
  4. package/.github/ISSUE_TEMPLATE/other.md +7 -0
  5. package/.github/dependatbot.yml +23 -0
  6. package/.github/release-draft-template.yml +33 -0
  7. package/.github/scripts/check-release.sh +42 -0
  8. package/.github/workflows/publish.yml +30 -0
  9. package/.github/workflows/release-drafter.yml +16 -0
  10. package/.github/workflows/test.yml +42 -0
  11. package/CHANGELOG.md +3 -0
  12. package/CONTRIBUTING.md +236 -0
  13. package/LICENSE +201 -0
  14. package/POSTINSTALL.md +40 -0
  15. package/PREINSTALL.md +42 -0
  16. package/README.md +128 -0
  17. package/bors.toml +8 -0
  18. package/dataset/firebase-export-metadata.json +8 -0
  19. package/dataset/firestore_export/all_namespaces/all_kinds/all_namespaces_all_kinds.export_metadata +0 -0
  20. package/dataset/firestore_export/all_namespaces/all_kinds/output-0 +0 -0
  21. package/dataset/firestore_export/firestore_export.overall_export_metadata +0 -0
  22. package/extension.yaml +176 -0
  23. package/firebase.json +20 -0
  24. package/functions/.eslintignore +2 -0
  25. package/functions/.eslintrc.js +54 -0
  26. package/functions/__tests__/__mocks__/console.ts +7 -0
  27. package/functions/__tests__/adapter.test.ts +98 -0
  28. package/functions/__tests__/config.test.ts +130 -0
  29. package/functions/__tests__/data/document.ts +11 -0
  30. package/functions/__tests__/data/environment.ts +9 -0
  31. package/functions/__tests__/functions.test.ts +280 -0
  32. package/functions/__tests__/jest.setup.ts +1 -0
  33. package/functions/__tests__/test.types.d.ts +5 -0
  34. package/functions/__tests__/tsconfig.json +5 -0
  35. package/functions/__tests__/util.test.ts +200 -0
  36. package/functions/jest.config.js +12 -0
  37. package/functions/lib/adapter.js +61 -0
  38. package/functions/lib/config.js +13 -0
  39. package/functions/lib/import/config.js +127 -0
  40. package/functions/lib/import/index.js +93 -0
  41. package/functions/lib/index.js +90 -0
  42. package/functions/lib/logs.js +97 -0
  43. package/functions/lib/meilisearch/create-index.js +17 -0
  44. package/functions/lib/meilisearch-index.js +17 -0
  45. package/functions/lib/types.js +2 -0
  46. package/functions/lib/util.js +47 -0
  47. package/functions/lib/version.js +4 -0
  48. package/functions/package.json +53 -0
  49. package/functions/src/adapter.ts +106 -0
  50. package/functions/src/config.ts +34 -0
  51. package/functions/src/import/config.ts +207 -0
  52. package/functions/src/import/index.ts +115 -0
  53. package/functions/src/index.ts +103 -0
  54. package/functions/src/logs.ts +107 -0
  55. package/functions/src/meilisearch/create-index.ts +20 -0
  56. package/functions/src/types.ts +8 -0
  57. package/functions/src/util.ts +63 -0
  58. package/functions/src/version.ts +1 -0
  59. package/functions/tsconfig.eslint.json +13 -0
  60. package/functions/tsconfig.json +23 -0
  61. package/functions/yarn.lock +5306 -0
  62. package/guides/IMPORT_EXISTING_DOCUMENTS.md +74 -0
  63. package/package.json +21 -0
  64. package/script/version.sh +51 -0
  65. package/test-params-example.env +9 -0
@@ -0,0 +1,54 @@
1
+ module.exports = {
2
+ root: true,
3
+ env: {
4
+ 'jest/globals': true,
5
+ 'browser': true,
6
+ 'commonjs': true,
7
+ 'es2021': true,
8
+ 'es6': true,
9
+ 'node': true,
10
+ },
11
+ extends: [
12
+ 'eslint:recommended',
13
+ 'plugin:import/errors',
14
+ 'plugin:import/warnings',
15
+ 'plugin:import/typescript',
16
+ 'plugin:@typescript-eslint/recommended',
17
+ 'plugin:@typescript-eslint/recommended-requiring-type-checking',
18
+ 'google',
19
+ 'plugin:prettier/recommended',
20
+ ],
21
+ parser: '@typescript-eslint/parser',
22
+ parserOptions: {
23
+ project: ['tsconfig.eslint.json'],
24
+ sourceType: 'module',
25
+ tsconfigRootDir: __dirname,
26
+ },
27
+ ignorePatterns: [
28
+ '/lib/**/*', // Ignore built files.
29
+ ],
30
+ plugins: ['@typescript-eslint', 'import', 'jest'],
31
+ rules: {
32
+ '@typescript-eslint/no-unused-vars': 'off',
33
+ '@typescript-eslint/no-unsafe-member-access': 'off',
34
+ '@typescript-eslint/ban-ts-comment': 'off',
35
+ '@typescript-eslint/no-unsafe-assignment': 'off',
36
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
37
+ '@typescript-eslint/no-unsafe-return': 'off',
38
+ '@typescript-eslint/no-unsafe-call': 'off',
39
+ '@typescript-eslint/no-var-requires': 'off',
40
+ '@typescript-eslint/no-explicit-any': 'off',
41
+ 'no-unused-vars': 'off',
42
+ 'array-callback-return': 'off',
43
+ 'arrow-parens': ['error', 'as-needed'],
44
+ 'prettier/prettier': [
45
+ 'error',
46
+ {
47
+ quoteProps: 'consistent',
48
+ semi: false,
49
+ arrowParens: 'avoid',
50
+ singleQuote: true,
51
+ },
52
+ ],
53
+ },
54
+ }
@@ -0,0 +1,7 @@
1
+ import { logger } from 'firebase-functions'
2
+
3
+ export const mockConsoleLog = jest.spyOn(logger, 'log').mockImplementation()
4
+
5
+ export const mockConsoleInfo = jest.spyOn(logger, 'info').mockImplementation()
6
+
7
+ export const mockConsoleError = jest.spyOn(logger, 'error').mockImplementation()
@@ -0,0 +1,98 @@
1
+ import * as firebaseFunctionsTestInit from 'firebase-functions-test'
2
+ import { mocked } from 'ts-jest/utils'
3
+ import { mockConsoleInfo } from './__mocks__/console'
4
+ import { GeoPoint } from 'firebase-admin/lib/firestore'
5
+ import { adaptDocument, adaptValues } from '../src/adapter'
6
+ import { getFieldsToIndex } from '../src/util'
7
+ import defaultDocument from './data/document'
8
+
9
+ jest.mock('../src/util')
10
+
11
+ // Mocking of Firebase functions
12
+ const firebaseMock = firebaseFunctionsTestInit()
13
+
14
+ describe('extensions process', () => {
15
+ describe('adaptDocument', () => {
16
+ const mockedGetFieldsToIndex = mocked(getFieldsToIndex, true)
17
+
18
+ test('adaptDocument with fields not set', () => {
19
+ mockedGetFieldsToIndex.mockReturnValueOnce([])
20
+ const snapshot = firebaseMock.firestore.makeDocumentSnapshot(
21
+ defaultDocument.document,
22
+ `docs/${defaultDocument.id}`
23
+ )
24
+
25
+ expect(adaptDocument(defaultDocument.id, snapshot)).toStrictEqual({
26
+ _firestore_id: defaultDocument.id,
27
+ ...defaultDocument.document,
28
+ })
29
+ })
30
+
31
+ test('adaptDocument with fields not set and with id field in document', () => {
32
+ mockedGetFieldsToIndex.mockReturnValueOnce([])
33
+ const snapshot = firebaseMock.firestore.makeDocumentSnapshot(
34
+ { id: '12345', ...defaultDocument.document },
35
+ `docs/${defaultDocument.id}`
36
+ )
37
+
38
+ expect(adaptDocument(defaultDocument.id, snapshot)).toStrictEqual({
39
+ _firestore_id: defaultDocument.id,
40
+ id: '12345',
41
+ ...defaultDocument.document,
42
+ })
43
+ })
44
+
45
+ test('adaptDocument with fields set', () => {
46
+ mockedGetFieldsToIndex.mockReturnValueOnce([
47
+ 'title',
48
+ 'overview',
49
+ 'release_date',
50
+ ])
51
+ const snapshot = firebaseMock.firestore.makeDocumentSnapshot(
52
+ defaultDocument.document,
53
+ `docs/${defaultDocument.id}`
54
+ )
55
+
56
+ expect(adaptDocument(defaultDocument.id, snapshot)).toStrictEqual({
57
+ _firestore_id: defaultDocument.id,
58
+ title: defaultDocument.document.title,
59
+ overview: defaultDocument.document.overview,
60
+ release_date: defaultDocument.document.release_date,
61
+ })
62
+ })
63
+ })
64
+
65
+ describe('adaptValues', () => {
66
+ test('adaptValues an id value', () => {
67
+ expect(adaptValues('id', defaultDocument.id as any)).toStrictEqual([
68
+ 'id',
69
+ defaultDocument.id,
70
+ ])
71
+ })
72
+ test('adaptValues a geo point value', () => {
73
+ const geoPoint = new GeoPoint(48.866667, 2.333333)
74
+
75
+ expect(adaptValues('_geo', geoPoint)).toStrictEqual([
76
+ '_geo',
77
+ {
78
+ lat: 48.866667,
79
+ lng: 2.333333,
80
+ },
81
+ ])
82
+ expect(mockConsoleInfo).toBeCalledWith(
83
+ `A GeoPoint was found with the field name '_geo' for compatibility with Meilisearch the field 'latitude' was renamed to 'lat' and the field 'longitude' to 'lng'`
84
+ )
85
+ })
86
+ test('adaptValues a wrong geo point value', () => {
87
+ const geoPoint = new GeoPoint(48.866667, 2.333333)
88
+
89
+ expect(adaptValues('wrong_geo', geoPoint)).toStrictEqual([
90
+ 'wrong_geo',
91
+ geoPoint,
92
+ ])
93
+ expect(mockConsoleInfo).toBeCalledWith(
94
+ `A GeoPoint was found without the field name '_geo' if you want to use the geoSearch with Meilisearch rename it to '_geo'`
95
+ )
96
+ })
97
+ })
98
+ })
@@ -0,0 +1,130 @@
1
+ import { readFileSync } from 'fs'
2
+ import { resolve as pathResolve } from 'path'
3
+ import * as yaml from 'js-yaml'
4
+ import mockedEnv from 'mocked-env'
5
+ import defaultEnvironment from './data/environment'
6
+
7
+ const EXTENSION_YAML = yaml.load(
8
+ readFileSync(pathResolve(__dirname, '../../extension.yaml'), 'utf8')
9
+ )
10
+
11
+ const extensionParams = EXTENSION_YAML.params.reduce((obj, parameter) => {
12
+ obj[parameter.param] = parameter
13
+ return obj
14
+ }, {})
15
+
16
+ describe('extensions config', () => {
17
+ let config
18
+ let restoreEnv
19
+
20
+ beforeEach(() => {
21
+ jest.resetModules()
22
+ restoreEnv = mockedEnv(defaultEnvironment)
23
+ config = require('../src/config').config
24
+ })
25
+ afterEach(() => restoreEnv())
26
+
27
+ test('config loaded from environment variables', () => {
28
+ const testConfig = {
29
+ location: defaultEnvironment.LOCATION,
30
+ collectionPath: defaultEnvironment.COLLECTION_PATH,
31
+ meilisearch: {
32
+ host: defaultEnvironment.MEILISEARCH_HOST,
33
+ apiKey: defaultEnvironment.MEILISEARCH_API_KEY,
34
+ indexUid: defaultEnvironment.MEILISEARCH_INDEX_NAME,
35
+ fieldsToIndex: defaultEnvironment.MEILISEARCH_FIELDS_TO_INDEX,
36
+ },
37
+ }
38
+
39
+ expect(config).toStrictEqual(testConfig)
40
+ })
41
+
42
+ // MEILISEARCH_FIELDS_TO_INDEX
43
+ describe('Test fieldsToIndex parameter', () => {
44
+ test('param exists', () => {
45
+ const extensionParam = extensionParams['MEILISEARCH_FIELDS_TO_INDEX']
46
+ expect(extensionParam).toMatchSnapshot()
47
+ })
48
+
49
+ describe('validationRegex', () => {
50
+ test('does not allow spaces', () => {
51
+ const { validationRegex } =
52
+ extensionParams['MEILISEARCH_FIELDS_TO_INDEX']
53
+ const text = 'foo bar'
54
+ const search = new RegExp(validationRegex)
55
+
56
+ expect(search.exec(text)).toBeNull()
57
+ })
58
+
59
+ test('allow comma-separated list', () => {
60
+ const { validationRegex } =
61
+ extensionParams['MEILISEARCH_FIELDS_TO_INDEX']
62
+ const text = 'field1,field2,field3'
63
+ const search = new RegExp(validationRegex)
64
+
65
+ expect(search.exec(text)).not.toBeNull()
66
+ })
67
+
68
+ test('allows a alphanumeric underscore list of field', () => {
69
+ const { validationRegex } =
70
+ extensionParams['MEILISEARCH_FIELDS_TO_INDEX']
71
+ const text = 'field_1,field_2,field_3'
72
+ const search = new RegExp(validationRegex)
73
+
74
+ expect(search.exec(text)).not.toBeNull()
75
+ })
76
+
77
+ test('allows a alphanumeric dash list of field', () => {
78
+ const { validationRegex } =
79
+ extensionParams['MEILISEARCH_FIELDS_TO_INDEX']
80
+ const text = 'field-1,field-2,field-3'
81
+ const search = new RegExp(validationRegex)
82
+
83
+ expect(search.exec(text)).not.toBeNull()
84
+ })
85
+ })
86
+ })
87
+
88
+ // MEILISEARCH_INDEX_NAME
89
+ describe('Test MeilisearchIndex parameters', () => {
90
+ test('param exists', () => {
91
+ const extensionParam = extensionParams['MEILISEARCH_INDEX_NAME']
92
+
93
+ expect(extensionParam).toMatchSnapshot()
94
+ })
95
+
96
+ describe('validationRegex', () => {
97
+ test('does not allow empty strings', () => {
98
+ const { validationRegex } = extensionParams['MEILISEARCH_INDEX_NAME']
99
+ const text = ''
100
+ const search = new RegExp(validationRegex)
101
+
102
+ expect(search.exec(text)).toBeNull()
103
+ })
104
+
105
+ test('does not allow spaces', () => {
106
+ const { validationRegex } = extensionParams['MEILISEARCH_INDEX_NAME']
107
+ const text = 'foo bar'
108
+ const search = new RegExp(validationRegex)
109
+
110
+ expect(search.exec(text)).toBeNull()
111
+ })
112
+
113
+ test('allows a alphanumeric underscore in index name', () => {
114
+ const { validationRegex } = extensionParams['MEILISEARCH_INDEX_NAME']
115
+ const text = 'index_1'
116
+ const search = new RegExp(validationRegex)
117
+
118
+ expect(search.exec(text)).not.toBeNull()
119
+ })
120
+
121
+ test('allows a alphanumeric dash in index name', () => {
122
+ const { validationRegex } = extensionParams['MEILISEARCH_INDEX_NAME']
123
+ const text = 'index-1'
124
+ const search = new RegExp(validationRegex)
125
+
126
+ expect(search.exec(text)).not.toBeNull()
127
+ })
128
+ })
129
+ })
130
+ })
@@ -0,0 +1,11 @@
1
+ export default {
2
+ id: '0jKUH3XUNXFyujm3rZAa',
3
+ document: {
4
+ title: 'The Lord of the Rings: The Fellowship of the Ring',
5
+ genre: ['Adventure', 'Fantasy', 'Action'],
6
+ overview:
7
+ 'Young hobbit Frodo Baggins, after inheriting a mysterious ring from his uncle Bilbo, must leave his home in order to keep it from falling into the hands of its evil creator. Along the way, a fellowship is formed to protect the ringbearer and make sure that the ring arrives at its final destination: Mt. Doom, the only place where it can be destroyed.',
8
+ poster: 'https://image.tmdb.org/t/p/w500/6oom5QYQ2yQTMJIbnvbkBL9cHo6.jpg',
9
+ release_date: 1008633600,
10
+ },
11
+ }
@@ -0,0 +1,9 @@
1
+ export default {
2
+ LOCATION: 'us-central1',
3
+ PROJECT_ID: 'fake-project',
4
+ COLLECTION_PATH: 'collection',
5
+ MEILISEARCH_FIELDS_TO_INDEX: '',
6
+ MEILISEARCH_INDEX_NAME: 'example',
7
+ MEILISEARCH_HOST: 'http://127.0.0.1:7700',
8
+ MEILISEARCH_API_KEY: 'masterKey',
9
+ }
@@ -0,0 +1,280 @@
1
+ import * as firebaseFunctionsTestInit from 'firebase-functions-test'
2
+ import mockedEnv from 'mocked-env'
3
+ import { mocked } from 'ts-jest/utils'
4
+ import { mockConsoleLog, mockConsoleInfo } from './__mocks__/console'
5
+ import { MeiliSearch } from 'meilisearch'
6
+ import defaultEnvironment from './data/environment'
7
+ import defaultDocument from './data/document'
8
+
9
+ jest.mock('meilisearch')
10
+
11
+ // Mocking of Firebase functions
12
+ let firebaseMock = firebaseFunctionsTestInit()
13
+
14
+ describe('extension', () => {
15
+ let config
16
+ let restoreEnv
17
+
18
+ // Mocking of Meilisearch package
19
+ const mockedMeilisearch = mocked(MeiliSearch, true)
20
+ const mockedAddDocuments = jest.fn()
21
+ const mockedUpdateDocuments = jest.fn()
22
+ const mockedDeleteDocument = jest.fn()
23
+ const mockedIndex = jest.fn(() => ({
24
+ addDocuments: mockedAddDocuments,
25
+ updateDocuments: mockedUpdateDocuments,
26
+ deleteDocument: mockedDeleteDocument,
27
+ }))
28
+ mockedMeilisearch.mockReturnValue({
29
+ // @ts-ignore
30
+ index: mockedIndex,
31
+ })
32
+
33
+ // Mocking of firestore-meilisearch
34
+ const mockExport = (document: any, data: any) => {
35
+ const ref = require('../src/index').indexingWorker
36
+ return firebaseFunctionsTestInit().wrap(ref)(document, data)
37
+ }
38
+
39
+ beforeEach(() => {
40
+ restoreEnv = mockedEnv(defaultEnvironment)
41
+ config = require('../src/config').config
42
+ })
43
+ afterEach(() => restoreEnv())
44
+
45
+ test('functions are exported', () => {
46
+ const exportedFunctions = jest.requireActual('../src')
47
+
48
+ expect(exportedFunctions.indexingWorker).toBeInstanceOf(Function)
49
+ })
50
+
51
+ test('Meilisearch client initialized', () => {
52
+ expect(mockedMeilisearch).toHaveBeenCalledWith({
53
+ apiKey: defaultEnvironment.MEILISEARCH_API_KEY,
54
+ host: defaultEnvironment.MEILISEARCH_HOST,
55
+ })
56
+ expect(mockConsoleLog).toBeCalledWith(
57
+ 'Initializing extension with configuration',
58
+ config
59
+ )
60
+ })
61
+
62
+ test('Meilisearch index initialized', () => {
63
+ expect(mockedIndex).toHaveBeenCalledWith(
64
+ defaultEnvironment.MEILISEARCH_INDEX_NAME
65
+ )
66
+ expect(mockConsoleLog).toBeCalledWith(
67
+ 'Initializing extension with configuration',
68
+ config
69
+ )
70
+ })
71
+
72
+ describe('functions.indexingWorker', () => {
73
+ firebaseMock = firebaseFunctionsTestInit()
74
+
75
+ beforeEach(() => {
76
+ jest.clearAllMocks()
77
+ })
78
+
79
+ test('function runs with created data', async () => {
80
+ const beforeSnapshot = firebaseMock.firestore.makeDocumentSnapshot(
81
+ {},
82
+ `collection/{}`
83
+ )
84
+ const afterSnapshot = firebaseMock.firestore.makeDocumentSnapshot(
85
+ defaultDocument.document,
86
+ `collection/${defaultDocument.id}`
87
+ )
88
+ const documentChange = firebaseMock.makeChange(
89
+ beforeSnapshot,
90
+ afterSnapshot
91
+ )
92
+
93
+ const callResult = await mockExport(documentChange, {
94
+ resource: {
95
+ name: 'test',
96
+ },
97
+ })
98
+
99
+ expect(callResult).toBeUndefined()
100
+ expect(mockConsoleLog).toBeCalledWith(
101
+ 'Started execution of extension with configuration',
102
+ config
103
+ )
104
+ expect(mockConsoleLog).toBeCalledWith('Completed execution of extension')
105
+ expect(mockConsoleInfo).toBeCalledWith(
106
+ `Creating new document ${
107
+ afterSnapshot.id as string
108
+ } in Meilisearch index ${defaultEnvironment.MEILISEARCH_INDEX_NAME}`,
109
+ { _firestore_id: defaultDocument.id, ...afterSnapshot.data() }
110
+ )
111
+ expect(mockedAddDocuments).toHaveBeenCalledWith(
112
+ [
113
+ {
114
+ _firestore_id: defaultDocument.id,
115
+ ...defaultDocument.document,
116
+ },
117
+ ],
118
+ { primaryKey: '_firestore_id' }
119
+ )
120
+ })
121
+
122
+ test('function runs with created data with id fields in document', async () => {
123
+ const beforeSnapshot = firebaseMock.firestore.makeDocumentSnapshot(
124
+ {},
125
+ `collection/{}`
126
+ )
127
+ const afterSnapshot = firebaseMock.firestore.makeDocumentSnapshot(
128
+ { id: '12345', ...defaultDocument.document },
129
+ `collection/${defaultDocument.id}`
130
+ )
131
+ const documentChange = firebaseMock.makeChange(
132
+ beforeSnapshot,
133
+ afterSnapshot
134
+ )
135
+
136
+ const callResult = await mockExport(documentChange, {
137
+ resource: {
138
+ name: 'test',
139
+ },
140
+ })
141
+
142
+ expect(callResult).toBeUndefined()
143
+ expect(mockConsoleLog).toBeCalledWith(
144
+ 'Started execution of extension with configuration',
145
+ config
146
+ )
147
+ expect(mockConsoleLog).toBeCalledWith('Completed execution of extension')
148
+ expect(mockConsoleInfo).toBeCalledWith(
149
+ `Creating new document ${
150
+ afterSnapshot.id as string
151
+ } in Meilisearch index ${defaultEnvironment.MEILISEARCH_INDEX_NAME}`,
152
+ { _firestore_id: defaultDocument.id, ...afterSnapshot.data() }
153
+ )
154
+ expect(mockedAddDocuments).toHaveBeenCalledWith(
155
+ [
156
+ {
157
+ _firestore_id: defaultDocument.id,
158
+ id: '12345',
159
+ ...defaultDocument.document,
160
+ },
161
+ ],
162
+ { primaryKey: '_firestore_id' }
163
+ )
164
+ })
165
+
166
+ test('function runs with updated data', async () => {
167
+ const beforeSnapshot = firebaseMock.firestore.makeDocumentSnapshot(
168
+ { foo: 'bar' },
169
+ `collection/${defaultDocument.id}`
170
+ )
171
+ const afterSnapshot = firebaseMock.firestore.makeDocumentSnapshot(
172
+ defaultDocument.document,
173
+ `collection/${defaultDocument.id}`
174
+ )
175
+ const documentChange = firebaseMock.makeChange(
176
+ beforeSnapshot,
177
+ afterSnapshot
178
+ )
179
+
180
+ const callResult = await mockExport(documentChange, {
181
+ resource: {
182
+ name: 'test',
183
+ },
184
+ })
185
+
186
+ expect(callResult).toBeUndefined()
187
+ expect(mockConsoleLog).toBeCalledWith(
188
+ 'Started execution of extension with configuration',
189
+ config
190
+ )
191
+ expect(mockConsoleInfo).toBeCalledWith(
192
+ `Updating document ${afterSnapshot.id as string} in Meilisearch index ${
193
+ defaultEnvironment.MEILISEARCH_INDEX_NAME
194
+ }`,
195
+ { _firestore_id: defaultDocument.id, ...afterSnapshot.data() }
196
+ )
197
+ expect(mockConsoleLog).toBeCalledWith('Completed execution of extension')
198
+ expect(mockedUpdateDocuments).toHaveBeenCalledWith([
199
+ {
200
+ _firestore_id: defaultDocument.id,
201
+ ...defaultDocument.document,
202
+ },
203
+ ])
204
+ })
205
+
206
+ test('function runs with updated data with id fields in document', async () => {
207
+ const beforeSnapshot = firebaseMock.firestore.makeDocumentSnapshot(
208
+ { foo: 'bar' },
209
+ `collection/${defaultDocument.id}`
210
+ )
211
+ const afterSnapshot = firebaseMock.firestore.makeDocumentSnapshot(
212
+ { id: '12345', ...defaultDocument.document },
213
+ `collection/${defaultDocument.id}`
214
+ )
215
+ const documentChange = firebaseMock.makeChange(
216
+ beforeSnapshot,
217
+ afterSnapshot
218
+ )
219
+
220
+ const callResult = await mockExport(documentChange, {
221
+ resource: {
222
+ name: 'test',
223
+ },
224
+ })
225
+
226
+ expect(callResult).toBeUndefined()
227
+ expect(mockConsoleLog).toBeCalledWith(
228
+ 'Started execution of extension with configuration',
229
+ config
230
+ )
231
+ expect(mockConsoleInfo).toBeCalledWith(
232
+ `Updating document ${afterSnapshot.id as string} in Meilisearch index ${
233
+ defaultEnvironment.MEILISEARCH_INDEX_NAME
234
+ }`,
235
+ {
236
+ _firestore_id: defaultDocument.id,
237
+ id: '12345',
238
+ ...afterSnapshot.data(),
239
+ }
240
+ )
241
+ expect(mockConsoleLog).toBeCalledWith('Completed execution of extension')
242
+ expect(mockedUpdateDocuments).toHaveBeenCalledWith([
243
+ {
244
+ _firestore_id: defaultDocument.id,
245
+ id: '12345',
246
+ ...defaultDocument.document,
247
+ },
248
+ ])
249
+ })
250
+
251
+ test('functions runs with deleted data', async () => {
252
+ const beforeSnapshot = firebaseMock.firestore.makeDocumentSnapshot(
253
+ { foo: 'bar' },
254
+ `collection/${defaultDocument.id}`
255
+ )
256
+ const afterSnapshot = { ...defaultDocument.document, exists: false }
257
+ const documentChange = firebaseMock.makeChange(
258
+ beforeSnapshot,
259
+ afterSnapshot
260
+ )
261
+
262
+ const callResult = await mockExport(documentChange, {
263
+ resource: {
264
+ name: 'test',
265
+ },
266
+ })
267
+
268
+ expect(callResult).toBeUndefined()
269
+ expect(mockConsoleLog).toBeCalledWith(
270
+ 'Started execution of extension with configuration',
271
+ config
272
+ )
273
+ expect(mockConsoleInfo).toBeCalledWith(
274
+ `Deleting document ${defaultDocument.id} in Meilisearch index ${defaultEnvironment.MEILISEARCH_INDEX_NAME}`
275
+ )
276
+ expect(mockConsoleLog).toBeCalledWith('Completed execution of extension')
277
+ expect(mockedDeleteDocument).toHaveBeenCalledWith(defaultDocument.id)
278
+ })
279
+ })
280
+ })
@@ -0,0 +1 @@
1
+ global.config = () => require('../src/config').default
@@ -0,0 +1,5 @@
1
+ declare namespace NodeJS {
2
+ interface Global {
3
+ config: () => jest.ModuleMocker
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": "../tsconfig.json",
3
+ "files": ["test.types.d.ts"],
4
+ "include": ["**/*"]
5
+ }