Skip to content
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// Stub for the Universal Sentence Encoder model. It transitively depends on the
// native @tensorflow/tfjs-node addon, so it is mocked for unit tests. load()
// returns a model whose embed() yields a deterministic zero vector; tests that
// assert on real embedding values are integration tests and remain skipped.
const DIMENSIONS = 512;

async function load() {
return {
embed: async input => {
const rows = Array.isArray(input) ? input.length : 1;
const vectors = Array.from({length: rows}, () =>
new Array(DIMENSIONS).fill(0)
);
return {
arraySync: () => vectors,
};
},
};
}

module.exports = {load};
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// Stub for the @tensorflow/tfjs-node native module. The real package loads a
// platform-specific native addon (tfjs_binding.node) at require time, which is
// not available in CI where dependencies are installed with --ignore-scripts.
// Unit tests never exercise the model itself, so an empty stub is sufficient;
// tests that need real embeddings are integration tests and remain skipped.
module.exports = {};
9 changes: 9 additions & 0 deletions firestore-semantic-search/functions/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ module.exports = {
testEnvironment: 'node',
collectCoverage: true,
collectCoverageFrom: ['src/**/*.ts', '!src/functions/cleanup.ts'],
moduleNameMapper: {
// Redirect the TensorFlow packages to lightweight stubs. The real
// @tensorflow/tfjs-node loads a native addon at require time that is absent
// in CI (deps installed with --ignore-scripts), which caused unrelated
// suites to fail to run. See __mocks__/@tensorflow/.
'^@tensorflow/tfjs-node$': '<rootDir>/__mocks__/@tensorflow/tfjs-node.js',
'^@tensorflow-models/universal-sentence-encoder$':
'<rootDir>/__mocks__/@tensorflow-models/universal-sentence-encoder.js',
},
transform: {
'^.+\\.ts$': [
'ts-jest',
Expand Down
17 changes: 17 additions & 0 deletions storage-reverse-image-search/functions/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
module.exports = {
preset: 'ts-jest',
testMatch: ['**/*.test.ts'],
// The feature_vectors unit specs load a real TensorFlow model over the
// network and assert on real tensors, so they require the native
// @tensorflow/tfjs-node addon. That addon is not present in CI (dependencies
// are installed with --ignore-scripts), so they belong to the integration
// run (jest.integration.config.js), not the default unit run.
testPathIgnorePatterns: [
'/node_modules/',
'__tests__/unit/feature_vectors\\.test\\.ts$',
'__tests__/unit/feature_vectors\\.memory\\.test\\.ts$',
],
testEnvironment: 'node',
collectCoverage: true,
collectCoverageFrom: ['src/**/*.ts', '!src/functions/cleanup.ts'],
setupFilesAfterEnv: ['<rootDir>/__tests__/setup.ts'],
moduleNameMapper: {
// Redirect @tensorflow/tfjs-node to a lightweight stub. The real package
// loads a native addon at require time that is absent in CI, which caused
// every suite transitively importing feature_vectors.ts to fail to run.
// See test-config/tfjs-node.stub.js.
'^@tensorflow/tfjs-node$': '<rootDir>/test-config/tfjs-node.stub.js',
},
transform: {
'^.+\\.ts$': [
'ts-jest',
Expand Down
16 changes: 16 additions & 0 deletions storage-reverse-image-search/functions/jest.integration.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const base = require('./jest.config');

// Integration config for the specs that exercise the real TensorFlow model
// (native @tensorflow/tfjs-node addon plus a network model download). These are
// intentionally excluded from the default `test` run because CI installs with
// --ignore-scripts and has no addon. Run locally with `npm run test:integration`
// after the native addon has been built.
module.exports = Object.assign({}, base, {
// Use the real @tensorflow/tfjs-node, not the unit stub.
moduleNameMapper: {},
testPathIgnorePatterns: ['/node_modules/'],
testMatch: [
'**/__tests__/unit/feature_vectors.test.ts',
'**/__tests__/unit/feature_vectors.memory.test.ts',
],
});
1 change: 1 addition & 0 deletions storage-reverse-image-search/functions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"build:watch": "tsc --watch",
"mocha": "mocha '**/*.spec.ts'",
"test": "jest",
"test:integration": "jest --config jest.integration.config.js",
"generate-readme": "firebase ext:info .. --markdown > ../README.md",
"publish-from-main": "firebase ext:dev:upload googlecloud/storage-reverse-image-search --repo=https://github.com/googlecloudplatform/firebase-extensions --root=storage-reverse-image-search --ref=main --project pub-ext-gcloud"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// Stub for @tensorflow/tfjs-node, wired in only by jest.config.js via
// moduleNameMapper. The real package loads a native addon (tfjs_binding.node)
// at require time, which is absent in CI (dependencies installed with
// --ignore-scripts). This caused every unit suite transitively importing
// feature_vectors.ts to fail to run.
//
// This file deliberately lives outside a __mocks__ directory: manual mocks for
// node_modules packages are applied automatically by jest and cannot be opted
// out per-config, which would also break the integration run. Wiring it through
// moduleNameMapper keeps it scoped to the unit config, so
// jest.integration.config.js uses the real package.
module.exports = {};
Loading