Skip to content

Fix geo point with tests #154

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Feb 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,6 @@ typings/
.env
.env.test

# jest snapshot
functions/__tests__/__snapshots__

# parcel-bundler cache (https://parceljs.org/)
.cache
Expand Down
11 changes: 11 additions & 0 deletions functions/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,15 @@ module.exports = {
},
],
},
settings: {
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
},
'import/resolver': {
typescript: {
alwaysTryTypes: true, // always try to resolve types under `<root>@types` directory even it doesn't contain any source code, like `@types/unist`
project: './tsconfig.json',
},
},
},
}
27 changes: 27 additions & 0 deletions functions/__tests__/__snapshots__/config.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`extensions config Test MeilisearchIndex parameters param exists 1`] = `
{
"description": "What Meilisearch index do you want to index your data in?",
"example": "example: my_index",
"label": "Meilisearch Index Name",
"param": "MEILISEARCH_INDEX_NAME",
"required": true,
"type": "string",
"validationErrorMessage": "Must be a valid Index format. Index uid can be of type integer or string only composed of alphanumeric characters, hyphens (-) and underscores (_). Check out our guide on [index creation](https://docs.meilisearch.com/learn/core_concepts/indexes.html#index-creation).",
"validationRegex": "^[0-9A-Za-z_-]+$",
}
`;

exports[`extensions config Test fieldsToIndex parameter param exists 1`] = `
{
"default": "",
"description": "What fields do you want to index in Meilisearch? Create a comma-separated list of the field names, or leave it blank to include all fields. The id field is always indexed even when omitted from the list.",
"example": "example: name,description,...",
"label": "Fields to index in Meilisearch",
"param": "MEILISEARCH_FIELDS_TO_INDEX",
"required": false,
"validationErrorMessage": "Fields must be given through a comma-separated list.",
"validationRegex": "^[^,]?[a-zA-Z-_0-9,]*[^,]$",
}
`;
3 changes: 3 additions & 0 deletions functions/__tests__/__snapshots__/util.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`getFieldsToIndex configuration detected from environment variables 1`] = `undefined`;
43 changes: 26 additions & 17 deletions functions/__tests__/adapter.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import * as firebaseFunctionsTestInit from 'firebase-functions-test'
import { mockConsoleInfo } from './__mocks__/console'
import { firestore } from 'firebase-admin/lib/firestore'
import { adaptDocument, adaptValues } from '../src/adapter'
import * as firestore from 'firebase-admin/firestore'
import {
adaptDocumentForMeilisearch,
adaptFields,
} from '../src/meilisearch-adapter'
import defaultDocument from './data/document'

// Mocking of Firebase functions
Expand All @@ -15,7 +18,9 @@ describe('extensions process', () => {
`docs/${defaultDocument.id}`
)

expect(adaptDocument(defaultDocument.id, snapshot, '')).toStrictEqual({
expect(
adaptDocumentForMeilisearch(defaultDocument.id, snapshot, '')
).toStrictEqual({
_firestore_id: defaultDocument.id,
...defaultDocument.document,
})
Expand All @@ -27,7 +32,9 @@ describe('extensions process', () => {
`docs/${defaultDocument.id}`
)

expect(adaptDocument(defaultDocument.id, snapshot, '')).toStrictEqual({
expect(
adaptDocumentForMeilisearch(defaultDocument.id, snapshot, '')
).toStrictEqual({
_firestore_id: defaultDocument.id,
id: '12345',
...defaultDocument.document,
Expand All @@ -41,7 +48,7 @@ describe('extensions process', () => {
)

expect(
adaptDocument(
adaptDocumentForMeilisearch(
defaultDocument.id,
snapshot,
'title,overview,release_date'
Expand All @@ -57,32 +64,34 @@ describe('extensions process', () => {

describe('adaptValues', () => {
test('adaptValues an id value', () => {
expect(adaptValues('id', defaultDocument.id as any)).toStrictEqual([
'id',
defaultDocument.id,
])
expect(
adaptFields({ id: defaultDocument.id } as firestore.DocumentData, 'id')
).toStrictEqual({ id: defaultDocument.id })
})
test('adaptValues a geo point value', () => {
const geoPoint = new firestore.GeoPoint(48.866667, 2.333333)

expect(adaptValues('_geo', geoPoint)).toStrictEqual([
'_geo',
{
expect(
adaptFields({ _geo: geoPoint } as firestore.DocumentData, '_geo')
).toStrictEqual({
_geo: {
lat: 48.866667,
lng: 2.333333,
},
])
})
expect(mockConsoleInfo).toBeCalledWith(
`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'`
)
})
test('adaptValues a wrong geo point value', () => {
const geoPoint = new firestore.GeoPoint(48.866667, 2.333333)

expect(adaptValues('wrong_geo', geoPoint)).toStrictEqual([
'wrong_geo',
geoPoint,
])
expect(
adaptFields(
{ wrong_geo: geoPoint } as firestore.DocumentData,
'wrong_geo'
)
).toStrictEqual({ wrong_geo: geoPoint })
expect(mockConsoleInfo).toBeCalledWith(
`A GeoPoint was found without the field name '_geo' if you want to use the geoSearch with Meilisearch rename it to '_geo'`
)
Expand Down
5 changes: 3 additions & 2 deletions functions/__tests__/functions.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as firebaseFunctionsTestInit from 'firebase-functions-test'
import mockedEnv from 'mocked-env'
import { mocked } from 'ts-jest/utils'
import { mocked } from 'jest-mock'
import {
mockConsoleLog,
mockConsoleInfo,
Expand All @@ -21,7 +21,7 @@ describe('extension', () => {
let restoreEnv

// Mocking of Meilisearch package
const mockedMeilisearch = mocked(MeiliSearch, true)
const mockedMeilisearch = mocked(MeiliSearch)
const mockedAddDocuments = jest.fn()
const mockedDeleteDocument = jest.fn()
const mockedIndex = jest.fn(() => ({
Expand All @@ -42,6 +42,7 @@ describe('extension', () => {
beforeEach(() => {
restoreEnv = mockedEnv(defaultEnvironment)
config = require('../src/config').config
config.collectionPath = 'collection'
})
afterEach(() => restoreEnv())

Expand Down
34 changes: 19 additions & 15 deletions functions/__tests__/util.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as firebaseFunctionsTestInit from 'firebase-functions-test'
import mockedEnv from 'mocked-env'
import { getChangeType, ChangeType, getChangedDocumentId } from '../src/util'
import { ChangeType, getChangedDocumentId, getActionType } from '../src/util'
import defaultEnvironment from './data/environment'

describe('getChangeType', () => {
Expand All @@ -21,7 +21,7 @@ describe('getChangeType', () => {
afterSnapshot
)

const changeType: ChangeType = getChangeType(documentChange)
const changeType: ChangeType = getActionType(documentChange)

expect(changeType).toEqual(ChangeType.CREATE)
})
Expand All @@ -41,7 +41,7 @@ describe('getChangeType', () => {
afterSnapshot
)

const changeType: ChangeType = getChangeType(documentChange)
const changeType: ChangeType = getActionType(documentChange)

expect(changeType).toEqual(ChangeType.UPDATE)
})
Expand All @@ -61,7 +61,7 @@ describe('getChangeType', () => {
afterSnapshot
)

const changeType: ChangeType = getChangeType(documentChange)
const changeType: ChangeType = getActionType(documentChange)

expect(changeType).toEqual(ChangeType.DELETE)
})
Expand Down Expand Up @@ -132,7 +132,7 @@ describe('getChangedDocumentId', () => {
})

describe('getFieldsToIndex', () => {
let util
let adapter
let restoreEnv
let mockParseFieldsToIndex
const config = global.config
Expand All @@ -149,32 +149,36 @@ describe('getFieldsToIndex', () => {
})

test('return empty list', () => {
util = require('../src/util')
mockParseFieldsToIndex = util.parseFieldsToIndex()
adapter = require('../src/meilisearch-adapter')
mockParseFieldsToIndex = adapter.parseFieldsToIndex()
expect(mockParseFieldsToIndex).toMatchObject([])
})

test('return list with one field', () => {
util = require('../src/util')
mockParseFieldsToIndex = util.parseFieldsToIndex('field')
adapter = require('../src/meilisearch-adapter')
mockParseFieldsToIndex = adapter.parseFieldsToIndex('field')
expect(mockParseFieldsToIndex).toMatchObject(['field'])
})

test('return list with multiple fields', () => {
util = require('../src/util')
mockParseFieldsToIndex = util.parseFieldsToIndex('field1,field2,field3')
adapter = require('../src/meilisearch-adapter')
mockParseFieldsToIndex = adapter.parseFieldsToIndex('field1,field2,field3')
expect(mockParseFieldsToIndex).toMatchObject(['field1', 'field2', 'field3'])
})

test('return list with multiple fields and spaces', () => {
util = require('../src/util')
mockParseFieldsToIndex = util.parseFieldsToIndex('field1, field2, field3')
adapter = require('../src/meilisearch-adapter')
mockParseFieldsToIndex = adapter.parseFieldsToIndex(
'field1, field2, field3'
)
expect(mockParseFieldsToIndex).toMatchObject(['field1', 'field2', 'field3'])
})

test('return list of fiels with underscore', () => {
util = require('../src/util')
mockParseFieldsToIndex = util.parseFieldsToIndex('field_1,field_2,field_3')
adapter = require('../src/meilisearch-adapter')
mockParseFieldsToIndex = adapter.parseFieldsToIndex(
'field_1,field_2,field_3'
)
expect(mockParseFieldsToIndex).toMatchObject([
'field_1',
'field_2',
Expand Down
11 changes: 7 additions & 4 deletions functions/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ process.env.FIREBASE_CONFIG = '{}'
module.exports = {
rootDir: './',
preset: 'ts-jest',
globals: {
'ts-jest': {
tsconfig: '<rootDir>/__tests__/tsconfig.json',
},
transform: {
'^.+\\.[tj]sx?$': [
'ts-jest',
{
tsconfig: '<rootDir>/__tests__/tsconfig.json',
},
],
},
testEnvironment: 'node',
testMatch: ['**/__tests__/*.test.ts'],
Expand Down
4 changes: 3 additions & 1 deletion functions/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ logs.init();
* IndexingWorker is responsible for aggregating a defined field from a Firestore collection into a Meilisearch index.
* It is controlled by a Firestore handler.
*/
exports.indexingWorker = functions.handler.firestore.document.onWrite(async (snapshot) => {
exports.indexingWorker = functions.firestore
.document(config_1.config.collectionPath + '/{documentId}')
.onWrite(async (snapshot) => {
logs.start();
const actionType = (0, util_1.getActionType)(snapshot);
const documentId = (0, util_1.getChangedDocumentId)(snapshot);
Expand Down
15 changes: 12 additions & 3 deletions functions/lib/meilisearch-adapter.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.adaptDocumentForMeilisearch = exports.parseFieldsToIndex = exports.isAFieldToIndex = void 0;
exports.adaptDocumentForMeilisearch = exports.adaptFields = exports.parseFieldsToIndex = exports.isAFieldToIndex = void 0;
const firestore = require("firebase-admin/firestore");
const logs_1 = require("./logs");
/**
* Adapts GeoPoint Firestore instance to fit with Meilisearch geo point.
* @param {firestore.GeoPoint} geoPoint GeoPoint Firestore object.
Expand Down Expand Up @@ -51,15 +52,23 @@ function adaptFields(document, fieldsToIndexSetting) {
return Object.keys(document).reduce((doc, currentField) => {
const value = document[currentField];
if (!isAFieldToIndex(fieldsToIndex, currentField))
if (currentField === '_geo' && value instanceof firestore.GeoPoint) {
return doc;
if (value instanceof firestore.GeoPoint) {
if (currentField === '_geo') {
(0, logs_1.infoGeoPoint)(true);
return {
...doc,
_geo: adaptGeoPoint(value),
};
}
else {
(0, logs_1.infoGeoPoint)(false);
}
}
return { ...doc, [currentField]: value };
}, {});
}
exports.adaptFields = adaptFields;
/**
* Adapts documents from the Firestore database to Meilisearch compatible documents.
* @param {string} documentId Document id.
Expand All @@ -72,7 +81,7 @@ function adaptDocumentForMeilisearch(documentId, snapshot, fieldsToIndexSetting)
if ('_firestore_id' in data) {
delete data.id;
}
const adaptedDoc = adaptFields(document, fieldsToIndexSetting);
const adaptedDoc = adaptFields(data, fieldsToIndexSetting);
return { _firestore_id: documentId, ...adaptedDoc };
}
exports.adaptDocumentForMeilisearch = adaptDocumentForMeilisearch;
15 changes: 8 additions & 7 deletions functions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
"main": "lib/index.js",
"dependencies": {
"commander": "^9.1.0",
"firebase-admin": "^11.3.0",
"firebase-functions": "^3.16.0",
"firebase-admin": "^11.5.0",
"firebase-functions": "^4.2.1",
"inquirer": "^8.2.2",
"meilisearch": "^0.30.0"
},
Expand All @@ -35,18 +35,19 @@
"eslint": "^7.6.0",
"eslint-config-google": "^0.14.0",
"eslint-config-prettier": "^8.3.0",
"eslint-import-resolver-typescript": "^3.5.3",
"eslint-plugin-import": "^2.24.2",
"eslint-plugin-jest": "^24.4.2",
"eslint-plugin-prettier": "^4.0.0",
"firebase-functions-test": "^0.3.2",
"jest": "^27.2.2",
"jest-mock": "^27.1.1",
"firebase-functions-test": "^3.0.0",
"jest": "^29.4.3",
"jest-mock": "^29.4.3",
"js-yaml": "^4.1.0",
"mocked-env": "^1.3.5",
"prettier": "^2.4.1",
"ts-jest": "^27.0.5",
"ts-jest": "^29.0.5",
"ts-node": "^10.2.1",
"typescript": "^4.4.3"
},
"bin": "lib/import/index.js"
}
}
2 changes: 1 addition & 1 deletion functions/src/import/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*/

import * as admin from 'firebase-admin'
import { DocumentSnapshot } from 'firebase-functions/lib/providers/firestore'
import { DocumentSnapshot } from 'firebase-functions/lib/v1/providers/firestore'
import { CLIConfig, parseConfig } from './config'
import * as logs from '../logs'
import { adaptDocumentForMeilisearch } from '../meilisearch-adapter'
Expand Down
Loading