repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
public Clawd ADK gateway launch mirror
stars
latest
clone command
git clone gitlawb://did:key:z6Mkq5mY...iFZ5/my-project-publ...git clone gitlawb://did:key:z6Mkq5mY.../my-project-publ...2fa351d6docs: add automaton and perps launch sources16d ago| #1 | import { describe, it, expect, vi, beforeEach } from 'vitest'; |
| #2 | import { mountR2Storage } from './r2'; |
| #3 | import { |
| #4 | createMockEnv, |
| #5 | createMockEnvWithR2, |
| #6 | createMockProcess, |
| #7 | createMockSandbox, |
| #8 | suppressConsole |
| #9 | } from '../test-utils'; |
| #10 | |
| #11 | describe('mountR2Storage', () => { |
| #12 | beforeEach(() => { |
| #13 | suppressConsole(); |
| #14 | }); |
| #15 | |
| #16 | describe('credential validation', () => { |
| #17 | it('returns false when R2_ACCESS_KEY_ID is missing', async () => { |
| #18 | const { sandbox } = createMockSandbox(); |
| #19 | const env = createMockEnv({ |
| #20 | R2_SECRET_ACCESS_KEY: 'secret', |
| #21 | CF_ACCOUNT_ID: 'account123', |
| #22 | }); |
| #23 | |
| #24 | const result = await mountR2Storage(sandbox, env); |
| #25 | |
| #26 | expect(result).toBe(false); |
| #27 | }); |
| #28 | |
| #29 | it('returns false when R2_SECRET_ACCESS_KEY is missing', async () => { |
| #30 | const { sandbox } = createMockSandbox(); |
| #31 | const env = createMockEnv({ |
| #32 | R2_ACCESS_KEY_ID: 'key123', |
| #33 | CF_ACCOUNT_ID: 'account123', |
| #34 | }); |
| #35 | |
| #36 | const result = await mountR2Storage(sandbox, env); |
| #37 | |
| #38 | expect(result).toBe(false); |
| #39 | }); |
| #40 | |
| #41 | it('returns false when CF_ACCOUNT_ID is missing', async () => { |
| #42 | const { sandbox } = createMockSandbox(); |
| #43 | const env = createMockEnv({ |
| #44 | R2_ACCESS_KEY_ID: 'key123', |
| #45 | R2_SECRET_ACCESS_KEY: 'secret', |
| #46 | }); |
| #47 | |
| #48 | const result = await mountR2Storage(sandbox, env); |
| #49 | |
| #50 | expect(result).toBe(false); |
| #51 | }); |
| #52 | |
| #53 | it('returns false when all R2 credentials are missing', async () => { |
| #54 | const { sandbox } = createMockSandbox(); |
| #55 | const env = createMockEnv(); |
| #56 | |
| #57 | const result = await mountR2Storage(sandbox, env); |
| #58 | |
| #59 | expect(result).toBe(false); |
| #60 | expect(console.log).toHaveBeenCalledWith( |
| #61 | expect.stringContaining('R2 storage not configured') |
| #62 | ); |
| #63 | }); |
| #64 | }); |
| #65 | |
| #66 | describe('mounting behavior', () => { |
| #67 | it('mounts R2 bucket when credentials provided and not already mounted', async () => { |
| #68 | const { sandbox, mountBucketMock } = createMockSandbox({ mounted: false }); |
| #69 | const env = createMockEnvWithR2({ |
| #70 | R2_ACCESS_KEY_ID: 'key123', |
| #71 | R2_SECRET_ACCESS_KEY: 'secret', |
| #72 | CF_ACCOUNT_ID: 'account123', |
| #73 | }); |
| #74 | |
| #75 | const result = await mountR2Storage(sandbox, env); |
| #76 | |
| #77 | expect(result).toBe(true); |
| #78 | expect(mountBucketMock).toHaveBeenCalledWith( |
| #79 | 'moltbot-data', |
| #80 | '/data/moltbot', |
| #81 | { |
| #82 | endpoint: 'https://account123.r2.cloudflarestorage.com', |
| #83 | credentials: { |
| #84 | accessKeyId: 'key123', |
| #85 | secretAccessKey: 'secret', |
| #86 | }, |
| #87 | } |
| #88 | ); |
| #89 | }); |
| #90 | |
| #91 | it('returns true immediately when bucket is already mounted', async () => { |
| #92 | const { sandbox, mountBucketMock } = createMockSandbox({ mounted: true }); |
| #93 | const env = createMockEnvWithR2(); |
| #94 | |
| #95 | const result = await mountR2Storage(sandbox, env); |
| #96 | |
| #97 | expect(result).toBe(true); |
| #98 | expect(mountBucketMock).not.toHaveBeenCalled(); |
| #99 | expect(console.log).toHaveBeenCalledWith( |
| #100 | 'R2 bucket already mounted at', |
| #101 | '/data/moltbot' |
| #102 | ); |
| #103 | }); |
| #104 | |
| #105 | it('logs success message when mounted successfully', async () => { |
| #106 | const { sandbox } = createMockSandbox({ mounted: false }); |
| #107 | const env = createMockEnvWithR2(); |
| #108 | |
| #109 | await mountR2Storage(sandbox, env); |
| #110 | |
| #111 | expect(console.log).toHaveBeenCalledWith( |
| #112 | 'R2 bucket mounted successfully - moltbot data will persist across sessions' |
| #113 | ); |
| #114 | }); |
| #115 | }); |
| #116 | |
| #117 | describe('error handling', () => { |
| #118 | it('returns false when mountBucket throws and mount check fails', async () => { |
| #119 | const { sandbox, mountBucketMock, startProcessMock } = createMockSandbox({ mounted: false }); |
| #120 | mountBucketMock.mockRejectedValue(new Error('Mount failed')); |
| #121 | startProcessMock |
| #122 | .mockResolvedValueOnce(createMockProcess('')) |
| #123 | .mockResolvedValueOnce(createMockProcess('')); |
| #124 | |
| #125 | const env = createMockEnvWithR2(); |
| #126 | |
| #127 | const result = await mountR2Storage(sandbox, env); |
| #128 | |
| #129 | expect(result).toBe(false); |
| #130 | expect(console.error).toHaveBeenCalledWith( |
| #131 | 'Failed to mount R2 bucket:', |
| #132 | expect.any(Error) |
| #133 | ); |
| #134 | }); |
| #135 | |
| #136 | it('returns true if mount fails but check shows it is actually mounted', async () => { |
| #137 | const { sandbox, mountBucketMock, startProcessMock } = createMockSandbox(); |
| #138 | startProcessMock |
| #139 | .mockResolvedValueOnce(createMockProcess('')) |
| #140 | .mockResolvedValueOnce(createMockProcess('s3fs on /data/moltbot type fuse.s3fs\n')); |
| #141 | |
| #142 | mountBucketMock.mockRejectedValue(new Error('Transient error')); |
| #143 | |
| #144 | const env = createMockEnvWithR2(); |
| #145 | |
| #146 | const result = await mountR2Storage(sandbox, env); |
| #147 | |
| #148 | expect(result).toBe(true); |
| #149 | expect(console.log).toHaveBeenCalledWith('R2 bucket is mounted despite error'); |
| #150 | }); |
| #151 | }); |
| #152 | }); |
| #153 |