Files
bruno/packages/bruno-electron/tests/app/apiSpecs.spec.js
adwait-bruno ad14fdfba5 fix(openapi):validate API spec imports (#8322)
* fix(openapi):validate API spec imports and resolve preview to error state instead of hanging

* fix(openapi):allows opening of malformed files with correct extension

* fix(openapi):reject non-OpenAPI content in spec preview before timeout

* test(openapi): add unit + e2e coverage for spec import validation

* refactor(openapi):centralise spec error messages and fix dialog restore

* fix:removed nested try catch

* test:added common locators

* refactor:removed repeated lines

* refactor:removed redundant file reads

---------

Co-authored-by: Adwait Aayush <adwaitaayush@Adwaits-MacBook-Air.local>
2026-07-07 22:05:23 +05:30

108 lines
3.9 KiB
JavaScript

const path = require('path');
const fs = require('fs');
const os = require('os');
const { INVALID_EXTENSION_MESSAGE } = require('../../src/app/apiSpecs');
jest.mock('electron', () => ({
dialog: { showOpenDialog: jest.fn() },
ipcMain: { emit: jest.fn() }
}));
const { ipcMain } = require('electron');
const { openApiSpec } = require('../../src/app/apiSpecs');
describe('openApiSpec', () => {
let tmpDir;
let win;
let watcher;
const writeSpecFile = (filename, content) => {
const filePath = path.join(tmpDir, filename);
fs.writeFileSync(filePath, content);
return filePath;
};
beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'bruno-apispec-'));
win = { webContents: { send: jest.fn() } };
watcher = { hasWatcher: jest.fn() };
});
afterEach(() => {
fs.rmSync(tmpDir, { recursive: true, force: true });
});
test.each(['spec.txt', 'spec.xml', 'spec', 'spec.yamlx'])(
'rejects a file with an unsupported extension (%s)',
async (filename) => {
const specPath = writeSpecFile(filename, 'This is a plain text file, not an OpenAPI spec.');
await openApiSpec(win, watcher, specPath);
expect(win.webContents.send).toHaveBeenCalledWith('main:display-error', {
message: INVALID_EXTENSION_MESSAGE
});
expect(ipcMain.emit).not.toHaveBeenCalled();
}
);
test.each(['openapi.yaml', 'openapi.yml', 'openapi.json', 'openapi.YAML', 'openapi.Json'])(
'accepts a file with a supported extension (%s)',
async (filename) => {
const specPath = writeSpecFile(filename, '{}');
watcher.hasWatcher.mockReturnValue(false);
await openApiSpec(win, watcher, specPath);
expect(win.webContents.send).not.toHaveBeenCalledWith('main:display-error', expect.anything());
expect(ipcMain.emit).toHaveBeenCalledWith('main:apispec-opened', win, specPath, expect.any(String), undefined);
}
);
test('does not send a display error when dontSendDisplayErrors is set', async () => {
const specPath = writeSpecFile('spec.txt', 'not a spec');
await openApiSpec(win, watcher, specPath, { dontSendDisplayErrors: true });
expect(win.webContents.send).not.toHaveBeenCalled();
});
test('opens a valid spec by emitting main:apispec-opened', async () => {
const specPath = writeSpecFile('openapi.yaml', 'openapi: 3.0.0\ninfo:\n title: Test\n version: 1.0.0\npaths: {}\n');
watcher.hasWatcher.mockReturnValue(false);
await openApiSpec(win, watcher, specPath);
expect(ipcMain.emit).toHaveBeenCalledWith('main:apispec-opened', win, specPath, expect.any(String), undefined);
expect(win.webContents.send).not.toHaveBeenCalledWith('main:display-error', expect.anything());
});
test('opens a malformed file with a valid extension without throwing, resolving json to null', async () => {
const specPath = writeSpecFile('malformed.yaml', 'openapi: 3.0.0\ninfo:\n title: Test\n version: : :\npaths: [');
watcher.hasWatcher.mockReturnValue(true);
await openApiSpec(win, watcher, specPath);
expect(win.webContents.send).toHaveBeenCalledWith(
'main:apispec-tree-updated',
'addFile',
expect.objectContaining({ pathname: specPath, json: null })
);
expect(win.webContents.send).not.toHaveBeenCalledWith('main:display-error', expect.anything());
});
test('opens a broken JSON file with a valid extension without throwing, resolving json to null', async () => {
const specPath = writeSpecFile('broken.json', '{\n "openapi": "3.0.0",\n "info": {\n "title": "Test"\n "version": "1.0.0"\n },\n "paths": {\n');
watcher.hasWatcher.mockReturnValue(true);
await openApiSpec(win, watcher, specPath);
expect(win.webContents.send).toHaveBeenCalledWith(
'main:apispec-tree-updated',
'addFile',
expect.objectContaining({ pathname: specPath, json: null })
);
expect(win.webContents.send).not.toHaveBeenCalledWith('main:display-error', expect.anything());
});
});