diff --git a/storage-reverse-image-search/functions/jest.config.js b/storage-reverse-image-search/functions/jest.config.js index 9e5ab925..3482a82a 100644 --- a/storage-reverse-image-search/functions/jest.config.js +++ b/storage-reverse-image-search/functions/jest.config.js @@ -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: ['/__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$': '/test-config/tfjs-node.stub.js', + }, transform: { '^.+\\.ts$': [ 'ts-jest', diff --git a/storage-reverse-image-search/functions/jest.integration.config.js b/storage-reverse-image-search/functions/jest.integration.config.js new file mode 100644 index 00000000..0be6aec1 --- /dev/null +++ b/storage-reverse-image-search/functions/jest.integration.config.js @@ -0,0 +1,17 @@ +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 = { + ...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', + ], +}; diff --git a/storage-reverse-image-search/functions/package.json b/storage-reverse-image-search/functions/package.json index 710eecb7..b2b9724d 100644 --- a/storage-reverse-image-search/functions/package.json +++ b/storage-reverse-image-search/functions/package.json @@ -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" }, diff --git a/storage-reverse-image-search/functions/test-config/tfjs-node.stub.js b/storage-reverse-image-search/functions/test-config/tfjs-node.stub.js new file mode 100644 index 00000000..59a46529 --- /dev/null +++ b/storage-reverse-image-search/functions/test-config/tfjs-node.stub.js @@ -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 = {};