Skip to content
Open
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
3 changes: 3 additions & 0 deletions packages/bruno-electron/src/app/collection-watcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,9 @@ class CollectionWatcher {

this.startCollectionDiscovery(win, collectionUid);

// Seed the dynamic config lookup before chokidar evaluates the initial tree.
setBrunoConfig(collectionUid, brunoConfig);

// Always ignore node_modules and .git, regardless of user config
// This prevents infinite loops with symlinked directories (e.g., npm workspaces)
const defaultIgnores = ['node_modules', '.git'];
Expand Down
102 changes: 102 additions & 0 deletions packages/bruno-electron/src/app/collection-watcher.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
const path = require('path');

const watcherHandlers = {};
const mockWatcher = {
on: jest.fn((event, handler) => {
watcherHandlers[event] = handler;
return mockWatcher;
}),
close: jest.fn()
};

jest.mock('chokidar', () => ({
watch: jest.fn((watchPath, options) => {
// Chokidar evaluates the predicate during its initial scan, before watch returns.
expect(options.ignored(require('path').join(watchPath, 'myfolder', 'somefile.yml'))).toBe(true);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not include any asserts here. The flow becomes a little confusing to read.

return mockWatcher;
})
}));
Comment thread
coderabbitai[bot] marked this conversation as resolved.

jest.mock('../utils/filesystem', () => ({
hasRequestExtension: jest.fn(),
isWSLPath: jest.fn(() => false),
normalizeAndResolvePath: jest.fn((pathname) => pathname),
sizeInMB: jest.fn(),
getCollectionFormat: jest.fn(() => 'bru')
}));

jest.mock('@usebruno/filestore', () => ({
parseEnvironment: jest.fn(),
parseRequest: jest.fn(),
parseRequestViaWorker: jest.fn(),
parseCollection: jest.fn(),
parseFolder: jest.fn()
}), { virtual: true });

jest.mock('@usebruno/common/utils', () => ({
parseValueByDataType: jest.fn()
}), { virtual: true });

jest.mock('../utils/common', () => ({
uuid: jest.fn(() => 'uuid')
}));

jest.mock('../cache/requestUids', () => ({
getRequestUid: jest.fn()
}));

jest.mock('../utils/encryption', () => ({
decryptStringSafe: jest.fn()
}));

jest.mock('../store/env-secrets', () => jest.fn().mockImplementation(() => ({})));

jest.mock('../services/snapshot', () => ({
getCollection: jest.fn()
}));

jest.mock('../utils/collection', () => ({
parseFileMeta: jest.fn(),
hydrateRequestWithUuid: jest.fn()
}));

jest.mock('../utils/parse', () => ({
parseLargeRequestWithRedaction: jest.fn()
}));

jest.mock('../utils/transformBrunoConfig', () => ({
transformBrunoConfigAfterRead: jest.fn()
}));

jest.mock('./dotenv-watcher', () => ({
addCollectionWatcher: jest.fn(),
removeCollectionWatcher: jest.fn()
}));

const { getBrunoConfig } = require('../store/bruno-config');
const collectionWatcher = require('./collection-watcher');

describe('CollectionWatcher', () => {
afterEach(() => {
collectionWatcher.closeAllWatchers();
Object.keys(watcherHandlers).forEach((event) => delete watcherHandlers[event]);
jest.clearAllMocks();
});

it('honors configured ignore paths during the initial scan', () => {
const watchPath = path.join('tmp', 'collection');
const collectionUid = 'collection-uid';
const brunoConfig = { ignore: ['myfolder'] };

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change the name of the ignored directory into something like ignored_dir. This makes the code a little self explainatory, than having myfolder.

const win = { webContents: { send: jest.fn() } };

collectionWatcher.addWatcher(win, watchPath, collectionUid, brunoConfig);

expect(getBrunoConfig(collectionUid)).toEqual(brunoConfig);

const ignored = require('chokidar').watch.mock.calls[0][1].ignored;
expect(ignored(path.join(watchPath, 'myfolder', 'somefile.yml'))).toBe(true);
expect(ignored(path.join(watchPath, 'visible', 'somefile.yml'))).toBe(false);
expect(ignored(path.join(watchPath, '.git', 'config'))).toBe(true);
expect(ignored(path.join(watchPath, 'node_modules', 'package', 'index.js'))).toBe(true);
Comment on lines +97 to +100

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: assign the paths to a const variable. Makes it a little more readable

});
});