1- import { ChromaClient , AdminClient } from "chromadb" ;
2- import { ChromaDBContainer } from "./chromadb-container" ;
3-
1+ import { ChromaClient , AdminClient , OllamaEmbeddingFunction } from "chromadb" ;
2+ import { ChromaDBContainer , StartedChromaDBContainer } from "./chromadb-container" ;
3+ import * as path from "node:path" ;
4+ import { GenericContainer } from "testcontainers" ;
5+ import * as os from "node:os" ;
6+ import * as fs from "node:fs" ;
7+ // run tests with NODE_OPTIONS=--experimental-vm-modules jest packages/modules/chromadb/src/chromadb-container.test.ts
48describe ( "ChromaDB" , ( ) => {
59 jest . setTimeout ( 360_000 ) ;
610
7- // docs {
8- it ( "should connect and return a query result" , async ( ) => {
11+ // startContainer {
12+ it ( "should connect" , async ( ) => {
13+ const container = await new ChromaDBContainer ( ) . start ( ) ;
14+ const client = await connectTo ( container ) ;
15+ expect ( await client . heartbeat ( ) ) . toBeDefined ( ) ;
16+ // Do something with the client
17+ await container . stop ( ) ;
18+ } ) ;
19+ // }
20+
21+ // simpleConnect {
22+ async function connectTo ( container : StartedChromaDBContainer ) {
23+ const client = new ChromaClient ( {
24+ path : container . getHttpUrl ( ) ,
25+ } ) ;
26+ const hb = await client . heartbeat ( ) ;
27+ expect ( hb ) . toBeDefined ( ) ;
28+ return client ;
29+ }
30+ // }
31+
32+ // createCollection {
33+ it ( "should create collection and get data" , async ( ) => {
934 const container = await new ChromaDBContainer ( ) . start ( ) ;
35+ const client = await connectTo ( container ) ;
36+ const collection = await client . createCollection ( { name : "test" , metadata : { "hnsw:space" : "cosine" } } ) ;
37+ expect ( collection . name ) . toBe ( "test" ) ;
38+ expect ( collection . metadata ) . toBeDefined ( ) ;
39+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
40+ // @ts -ignore
41+ expect ( collection . metadata [ "hnsw:space" ] ) . toBe ( "cosine" ) ;
42+ await collection . add ( { ids : [ "1" ] , embeddings : [ [ 1 , 2 , 3 ] ] , documents : [ "my doc" ] , metadatas : [ { key : "value" } ] } ) ;
43+ const getResults = await collection . get ( { ids : [ "1" ] } ) ;
44+ expect ( getResults . ids [ 0 ] ) . toBe ( "1" ) ;
45+ expect ( getResults . documents [ 0 ] ) . toStrictEqual ( "my doc" ) ;
46+ expect ( getResults . metadatas ) . toBeDefined ( ) ;
47+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
48+ // @ts -ignore
49+ expect ( getResults . metadatas [ 0 ] . key ) . toStrictEqual ( "value" ) ;
50+ await container . stop ( ) ;
51+ } ) ;
52+ // }
53+
54+ // queryCollectionWithEmbeddingFunction {
55+ it ( "should create collection and query" , async ( ) => {
56+ const container = await new ChromaDBContainer ( ) . start ( ) ;
57+ const ollama = await new GenericContainer ( "ollama/ollama" ) . withExposedPorts ( 11434 ) . start ( ) ;
58+ await ollama . exec ( [ "ollama" , "pull" , "nomic-embed-text" ] ) ;
59+ const client = await connectTo ( container ) ;
60+ const embedder = new OllamaEmbeddingFunction ( {
61+ url : `http://${ ollama . getHost ( ) } :${ ollama . getMappedPort ( 11434 ) } /api/embeddings` ,
62+ model : "nomic-embed-text" ,
63+ } ) ;
64+ const collection = await client . createCollection ( {
65+ name : "test" ,
66+ metadata : { "hnsw:space" : "cosine" } ,
67+ embeddingFunction : embedder ,
68+ } ) ;
69+ expect ( collection . name ) . toBe ( "test" ) ;
70+ await collection . add ( {
71+ ids : [ "1" , "2" ] ,
72+ documents : [
73+ "This is a document about dogs. Dogs are awesome." ,
74+ "This is a document about cats. Cats are awesome." ,
75+ ] ,
76+ } ) ;
77+ const results = await collection . query ( { queryTexts : [ "Tell me about dogs" ] , nResults : 1 } ) ;
78+ expect ( results ) . toBeDefined ( ) ;
79+ expect ( results . ids [ 0 ] ) . toEqual ( [ "1" ] ) ;
80+ expect ( results . ids [ 0 ] [ 0 ] ) . toBe ( "1" ) ;
81+ await container . stop ( ) ;
82+ } ) ;
83+
84+ // persistentData {
85+ it ( "should reconnect with volume and persistence data" , async ( ) => {
86+ const sourcePath = fs . mkdtempSync ( path . join ( os . tmpdir ( ) , "chroma-temp" ) ) ;
87+ const container = await new ChromaDBContainer ( )
88+ . withBindMounts ( [ { source : sourcePath , target : "/chroma/chroma" } ] )
89+ . start ( ) ;
90+ const client = await connectTo ( container ) ;
91+ const collection = await client . createCollection ( { name : "test" , metadata : { "hnsw:space" : "cosine" } } ) ;
92+ expect ( collection . name ) . toBe ( "test" ) ;
93+ expect ( collection . metadata ) . toBeDefined ( ) ;
94+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
95+ // @ts -ignore
96+ expect ( collection . metadata [ "hnsw:space" ] ) . toBe ( "cosine" ) ;
97+ await collection . add ( { ids : [ "1" ] , embeddings : [ [ 1 , 2 , 3 ] ] , documents : [ "my doc" ] } ) ;
98+ const getResults = await collection . get ( { ids : [ "1" ] } ) ;
99+ expect ( getResults . ids [ 0 ] ) . toBe ( "1" ) ;
100+ expect ( getResults . documents [ 0 ] ) . toStrictEqual ( "my doc" ) ;
101+ await container . stop ( ) ;
102+ expect ( fs . existsSync ( `${ sourcePath } /chroma.sqlite3` ) ) . toBe ( true ) ;
103+ try {
104+ fs . rmSync ( sourcePath , { force : true , recursive : true } ) ;
105+ } catch ( e ) {
106+ //Ignore clean up, when have no access on fs.
107+ console . log ( e ) ;
108+ }
109+ } ) ;
110+ // }
111+
112+ // auth {
113+ it ( "should use auth" , async ( ) => {
10114 const tenant = "test-tenant" ;
11115 const key = "test-key" ;
12116 const database = "test-db" ;
117+ const container = await new ChromaDBContainer ( )
118+ . withEnvironment ( {
119+ CHROMA_SERVER_AUTHN_CREDENTIALS : key ,
120+ CHROMA_SERVER_AUTHN_PROVIDER : "chromadb.auth.token_authn.TokenAuthenticationServerProvider" ,
121+ CHROMA_AUTH_TOKEN_TRANSPORT_HEADER : "X_CHROMA_TOKEN" ,
122+ } )
123+ . start ( ) ;
124+
13125 const adminClient = new AdminClient ( {
14126 tenant : tenant ,
15127 auth : {
16128 provider : "token" ,
17129 credentials : key ,
18- providerOptions : {
19- headerType : "X_CHROMA_TOKEN" ,
20- } ,
130+ tokenHeaderType : "X_CHROMA_TOKEN" ,
21131 } ,
22132 path : container . getHttpUrl ( ) ,
23133 } ) ;
@@ -30,52 +140,14 @@ describe("ChromaDB", () => {
30140 auth : {
31141 provider : "token" ,
32142 credentials : key ,
33- providerOptions : {
34- headerType : "X_CHROMA_TOKEN" ,
35- } ,
143+ tokenHeaderType : "X_CHROMA_TOKEN" ,
36144 } ,
37145 path : container . getHttpUrl ( ) ,
38146 database,
39147 } ) ;
40148
41149 const collection = await dbClient . createCollection ( { name : "test-collection" } ) ;
42-
43- await collection . add ( {
44- ids : [ "1" , "2" , "3" ] ,
45- documents : [ "apple" , "oranges" , "pineapple" ] ,
46- embeddings : [
47- [ 1 , 2 , 3 ] ,
48- [ 4 , 5 , 6 ] ,
49- [ 7 , 8 , 9 ] ,
50- ] ,
51- } ) ;
52-
53- const result = await collection . get ( { ids : [ "1" , "2" , "3" ] } ) ;
54-
55- expect ( result ) . toMatchInlineSnapshot ( `
56- {
57- "data": null,
58- "documents": [
59- "apple",
60- "oranges",
61- "pineapple",
62- ],
63- "embeddings": null,
64- "ids": [
65- "1",
66- "2",
67- "3",
68- ],
69- "metadatas": [
70- null,
71- null,
72- null,
73- ],
74- "uris": null,
75- }
76- ` ) ;
77-
78- await container . stop ( ) ;
150+ expect ( collection . name ) . toBe ( "test-collection" ) ;
79151 } ) ;
80152 // }
81153} ) ;
0 commit comments