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.
- package/.editorconfig +20 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +26 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +18 -0
- package/.github/ISSUE_TEMPLATE/other.md +7 -0
- package/.github/dependatbot.yml +23 -0
- package/.github/release-draft-template.yml +33 -0
- package/.github/scripts/check-release.sh +42 -0
- package/.github/workflows/publish.yml +30 -0
- package/.github/workflows/release-drafter.yml +16 -0
- package/.github/workflows/test.yml +42 -0
- package/CHANGELOG.md +3 -0
- package/CONTRIBUTING.md +236 -0
- package/LICENSE +201 -0
- package/POSTINSTALL.md +40 -0
- package/PREINSTALL.md +42 -0
- package/README.md +128 -0
- package/bors.toml +8 -0
- package/dataset/firebase-export-metadata.json +8 -0
- package/dataset/firestore_export/all_namespaces/all_kinds/all_namespaces_all_kinds.export_metadata +0 -0
- package/dataset/firestore_export/all_namespaces/all_kinds/output-0 +0 -0
- package/dataset/firestore_export/firestore_export.overall_export_metadata +0 -0
- package/extension.yaml +176 -0
- package/firebase.json +20 -0
- package/functions/.eslintignore +2 -0
- package/functions/.eslintrc.js +54 -0
- package/functions/__tests__/__mocks__/console.ts +7 -0
- package/functions/__tests__/adapter.test.ts +98 -0
- package/functions/__tests__/config.test.ts +130 -0
- package/functions/__tests__/data/document.ts +11 -0
- package/functions/__tests__/data/environment.ts +9 -0
- package/functions/__tests__/functions.test.ts +280 -0
- package/functions/__tests__/jest.setup.ts +1 -0
- package/functions/__tests__/test.types.d.ts +5 -0
- package/functions/__tests__/tsconfig.json +5 -0
- package/functions/__tests__/util.test.ts +200 -0
- package/functions/jest.config.js +12 -0
- package/functions/lib/adapter.js +61 -0
- package/functions/lib/config.js +13 -0
- package/functions/lib/import/config.js +127 -0
- package/functions/lib/import/index.js +93 -0
- package/functions/lib/index.js +90 -0
- package/functions/lib/logs.js +97 -0
- package/functions/lib/meilisearch/create-index.js +17 -0
- package/functions/lib/meilisearch-index.js +17 -0
- package/functions/lib/types.js +2 -0
- package/functions/lib/util.js +47 -0
- package/functions/lib/version.js +4 -0
- package/functions/package.json +53 -0
- package/functions/src/adapter.ts +106 -0
- package/functions/src/config.ts +34 -0
- package/functions/src/import/config.ts +207 -0
- package/functions/src/import/index.ts +115 -0
- package/functions/src/index.ts +103 -0
- package/functions/src/logs.ts +107 -0
- package/functions/src/meilisearch/create-index.ts +20 -0
- package/functions/src/types.ts +8 -0
- package/functions/src/util.ts +63 -0
- package/functions/src/version.ts +1 -0
- package/functions/tsconfig.eslint.json +13 -0
- package/functions/tsconfig.json +23 -0
- package/functions/yarn.lock +5306 -0
- package/guides/IMPORT_EXISTING_DOCUMENTS.md +74 -0
- package/package.json +21 -0
- package/script/version.sh +51 -0
- 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,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
|