@@ -8,7 +8,13 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
88import * as fs from 'node:fs' ;
99import * as path from 'node:path' ;
1010import * as os from 'node:os' ;
11- import { resolveWorkspacePolicyState } from './policy.js' ;
11+ import {
12+ resolveWorkspacePolicyState ,
13+ autoAcceptWorkspacePolicies ,
14+ setAutoAcceptWorkspacePolicies ,
15+ disableWorkspacePolicies ,
16+ setDisableWorkspacePolicies ,
17+ } from './policy.js' ;
1218import { writeToStderr } from '@google/gemini-cli-core' ;
1319
1420// Mock debugLogger to avoid noise in test output
@@ -41,6 +47,9 @@ describe('resolveWorkspacePolicyState', () => {
4147 fs . mkdirSync ( workspaceDir ) ;
4248 policiesDir = path . join ( workspaceDir , '.gemini' , 'policies' ) ;
4349
50+ // Enable policies for these tests to verify loading logic
51+ setDisableWorkspacePolicies ( false ) ;
52+
4453 vi . clearAllMocks ( ) ;
4554 } ) ;
4655
@@ -63,29 +72,30 @@ describe('resolveWorkspacePolicyState', () => {
6372 } ) ;
6473 } ) ;
6574
75+ it ( 'should have disableWorkspacePolicies set to true by default' , ( ) => {
76+ // We explicitly set it to false in beforeEach for other tests,
77+ // so here we test that setting it to true works.
78+ setDisableWorkspacePolicies ( true ) ;
79+ expect ( disableWorkspacePolicies ) . toBe ( true ) ;
80+ } ) ;
81+
6682 it ( 'should return policy directory if integrity matches' , async ( ) => {
6783 // Set up policies directory with a file
6884 fs . mkdirSync ( policiesDir , { recursive : true } ) ;
6985 fs . writeFileSync ( path . join ( policiesDir , 'policy.toml' ) , 'rules = []' ) ;
7086
71- // First call to establish integrity (interactive accept)
87+ // First call to establish integrity (interactive auto- accept)
7288 const firstResult = await resolveWorkspacePolicyState ( {
7389 cwd : workspaceDir ,
7490 trustedFolder : true ,
7591 interactive : true ,
7692 } ) ;
77- expect ( firstResult . policyUpdateConfirmationRequest ) . toBeDefined ( ) ;
78-
79- // Establish integrity manually as if accepted
80- const { PolicyIntegrityManager } = await import ( '@google/gemini-cli-core' ) ;
81- const integrityManager = new PolicyIntegrityManager ( ) ;
82- await integrityManager . acceptIntegrity (
83- 'workspace' ,
84- workspaceDir ,
85- firstResult . policyUpdateConfirmationRequest ! . newHash ,
86- ) ;
93+ expect ( firstResult . workspacePoliciesDir ) . toBe ( policiesDir ) ;
94+ expect ( firstResult . policyUpdateConfirmationRequest ) . toBeUndefined ( ) ;
95+ expect ( writeToStderr ) . not . toHaveBeenCalled ( ) ;
8796
8897 // Second call should match
98+
8999 const result = await resolveWorkspacePolicyState ( {
90100 cwd : workspaceDir ,
91101 trustedFolder : true ,
@@ -107,26 +117,33 @@ describe('resolveWorkspacePolicyState', () => {
107117 expect ( result . policyUpdateConfirmationRequest ) . toBeUndefined ( ) ;
108118 } ) ;
109119
110- it ( 'should return confirmation request if changed in interactive mode' , async ( ) => {
111- fs . mkdirSync ( policiesDir , { recursive : true } ) ;
112- fs . writeFileSync ( path . join ( policiesDir , 'policy.toml' ) , 'rules = []' ) ;
120+ it ( 'should return confirmation request if changed in interactive mode when AUTO_ACCEPT is false ' , async ( ) => {
121+ const originalValue = autoAcceptWorkspacePolicies ;
122+ setAutoAcceptWorkspacePolicies ( false ) ;
113123
114- const result = await resolveWorkspacePolicyState ( {
115- cwd : workspaceDir ,
116- trustedFolder : true ,
117- interactive : true ,
118- } ) ;
124+ try {
125+ fs . mkdirSync ( policiesDir , { recursive : true } ) ;
126+ fs . writeFileSync ( path . join ( policiesDir , 'policy.toml' ) , 'rules = []' ) ;
119127
120- expect ( result . workspacePoliciesDir ) . toBeUndefined ( ) ;
121- expect ( result . policyUpdateConfirmationRequest ) . toEqual ( {
122- scope : 'workspace' ,
123- identifier : workspaceDir ,
124- policyDir : policiesDir ,
125- newHash : expect . any ( String ) ,
126- } ) ;
128+ const result = await resolveWorkspacePolicyState ( {
129+ cwd : workspaceDir ,
130+ trustedFolder : true ,
131+ interactive : true ,
132+ } ) ;
133+
134+ expect ( result . workspacePoliciesDir ) . toBeUndefined ( ) ;
135+ expect ( result . policyUpdateConfirmationRequest ) . toEqual ( {
136+ scope : 'workspace' ,
137+ identifier : workspaceDir ,
138+ policyDir : policiesDir ,
139+ newHash : expect . any ( String ) ,
140+ } ) ;
141+ } finally {
142+ setAutoAcceptWorkspacePolicies ( originalValue ) ;
143+ }
127144 } ) ;
128145
129- it ( 'should warn and auto-accept if changed in non-interactive mode' , async ( ) => {
146+ it ( 'should warn and auto-accept if changed in non-interactive mode when AUTO_ACCEPT is true ' , async ( ) => {
130147 fs . mkdirSync ( policiesDir , { recursive : true } ) ;
131148 fs . writeFileSync ( path . join ( policiesDir , 'policy.toml' ) , 'rules = []' ) ;
132149
@@ -143,6 +160,30 @@ describe('resolveWorkspacePolicyState', () => {
143160 ) ;
144161 } ) ;
145162
163+ it ( 'should warn and auto-accept if changed in non-interactive mode when AUTO_ACCEPT is false' , async ( ) => {
164+ const originalValue = autoAcceptWorkspacePolicies ;
165+ setAutoAcceptWorkspacePolicies ( false ) ;
166+
167+ try {
168+ fs . mkdirSync ( policiesDir , { recursive : true } ) ;
169+ fs . writeFileSync ( path . join ( policiesDir , 'policy.toml' ) , 'rules = []' ) ;
170+
171+ const result = await resolveWorkspacePolicyState ( {
172+ cwd : workspaceDir ,
173+ trustedFolder : true ,
174+ interactive : false ,
175+ } ) ;
176+
177+ expect ( result . workspacePoliciesDir ) . toBe ( policiesDir ) ;
178+ expect ( result . policyUpdateConfirmationRequest ) . toBeUndefined ( ) ;
179+ expect ( writeToStderr ) . toHaveBeenCalledWith (
180+ expect . stringContaining ( 'Automatically accepting and loading' ) ,
181+ ) ;
182+ } finally {
183+ setAutoAcceptWorkspacePolicies ( originalValue ) ;
184+ }
185+ } ) ;
186+
146187 it ( 'should not return workspace policies if cwd is the home directory' , async ( ) => {
147188 const policiesDir = path . join ( tempDir , '.gemini' , 'policies' ) ;
148189 fs . mkdirSync ( policiesDir , { recursive : true } ) ;
@@ -159,7 +200,26 @@ describe('resolveWorkspacePolicyState', () => {
159200 expect ( result . policyUpdateConfirmationRequest ) . toBeUndefined ( ) ;
160201 } ) ;
161202
162- it ( 'should not return workspace policies if cwd is a symlink to the home directory' , async ( ) => {
203+ it ( 'should return empty state if disableWorkspacePolicies is true even if folder is trusted' , async ( ) => {
204+ setDisableWorkspacePolicies ( true ) ;
205+
206+ // Set up policies directory with a file
207+ fs . mkdirSync ( policiesDir , { recursive : true } ) ;
208+ fs . writeFileSync ( path . join ( policiesDir , 'policy.toml' ) , 'rules = []' ) ;
209+
210+ const result = await resolveWorkspacePolicyState ( {
211+ cwd : workspaceDir ,
212+ trustedFolder : true ,
213+ interactive : true ,
214+ } ) ;
215+
216+ expect ( result ) . toEqual ( {
217+ workspacePoliciesDir : undefined ,
218+ policyUpdateConfirmationRequest : undefined ,
219+ } ) ;
220+ } ) ;
221+
222+ it ( 'should return empty state if cwd is a symlink to the home directory' , async ( ) => {
163223 const policiesDir = path . join ( tempDir , '.gemini' , 'policies' ) ;
164224 fs . mkdirSync ( policiesDir , { recursive : true } ) ;
165225 fs . writeFileSync ( path . join ( policiesDir , 'policy.toml' ) , 'rules = []' ) ;
0 commit comments