Compare commits

..

14 Commits

Author SHA1 Message Date
Anoop M D
00e98451d4 Merge branch 'main' into fix/json-serialization-issues 2024-08-27 14:09:10 +05:30
lohit
b4fd350334 feat: electron sandbox bundle libraries check (#2932)
chore: check sandbox libraries bundle file
2024-08-27 14:05:49 +05:30
Mateusz Pietryga
ad388e5a6a fix: Failed to construct 'URL': Invalid URL everytime the URL is modified (#2897)
* fix: Failed to construct 'URL': Invalid URL everytime the URL is modified

A non-parsable URL should be an acceptable state while the text is being typed.

* chore: path params are returned as empty

---------

Co-authored-by: Anoop M D <anoop.md1421@gmail.com>
2024-08-27 12:19:04 +05:30
Pragadesh-45
4ddccefee3 fix: multiple tab collection level settings (#2905)
* added isFolderSettingsOpenedInTabs logic
2024-08-27 11:51:19 +05:30
lohit
b121afe7bb feat: revert await keyword for test (#2933)
feat: revert await keyword for test
2024-08-27 11:41:09 +05:30
LeoGrambert
f6c6a3b2bf feat: add Georgian README translations (#2931) 2024-08-27 11:04:34 +05:30
Timon
cf02ea2572 feat: Replace dictonary i18n with react-i18next (#2915) 2024-08-26 11:09:50 +05:30
zachary-berdell-elliott
9343f1e070 Bugfix/request body value cutoff (#2917)
* Changed display: contents to display: block to fix bug with text cutoff in multipart form and form url encoded request bodies.

* Changed display: contents to display: block to fix bug with text cutoff in multipart form and form url encoded request bodies.
2024-08-26 11:06:33 +05:30
lohit
df2e18bedd bru disableParsingResponseJson function rename (#2785)
* disable response json parse flag

* fix: pr review comments

* update bru req function name
2024-08-08 19:07:12 +05:30
Anoop M D
9a88db7e56 fix(#2767): fix failing test 2024-08-08 18:46:35 +05:30
lohit
4a4439f48e disable response json parse flag (#2782)
* disable response json parse flag

* fix: pr review comments
2024-08-08 18:36:00 +05:30
Anoop M D
4710928407 fix(#2767): addressing review comments 2024-08-08 12:21:04 +05:30
Anoop M D
33804f4c7b fix(#2767): addressing review comments 2024-08-08 12:02:00 +05:30
Anoop M D
e0858d1c99 fix(#2767): Fix serilization issues of bigint in json body 2024-08-07 20:00:41 +05:30
47 changed files with 565 additions and 226 deletions

View File

@@ -34,6 +34,7 @@ Libraries we use
- Schema Validation - Yup
- Request Client - axios
- Filesystem Watcher - chokidar
- i18n - i18next
### Dependencies

View File

@@ -27,6 +27,7 @@
| [正體中文](./readme_zhtw.md)
| **العربية**
| [日本語](./readme_ja.md)
| [ქართული](./readme_ka.md)
برونو هو عميل API جديد ومبتكر، يهدف إلى ثورة الحالة الحالية التي يمثلها برنامج Postman وأدوات مماثلة هناك.

View File

@@ -27,6 +27,7 @@
| [正體中文](./readme_zhtw.md)
| [العربية](./readme_ar.md)
| [日本語](./readme_ja.md)
| [ქართული](./readme_ka.md)
ব্রুনো হল একটি নতুন এবং উদ্ভাবনী API ক্লায়েন্ট, যার লক্ষ্য পোস্টম্যান এবং অনুরূপ সরঞ্জাম দ্বারা প্রতিনিধিত্ব করা স্থিতাবস্থায় বিপ্লব ঘটানো।

View File

@@ -27,6 +27,7 @@
| [正體中文](./readme_zhtw.md)
| [العربية](./readme_ar.md)
| [日本語](./readme_ja.md)
| [ქართული](./readme_ka.md)
Bruno 是一款全新且创新的 API 客户端,旨在颠覆 Postman 和其他类似工具。

View File

@@ -27,6 +27,7 @@
| [正體中文](./readme_zhtw.md)
| [العربية](./readme_ar.md)
| [日本語](./readme_ja.md)
| [ქართული](./readme_ka.md)
Bruno ist ein neuer und innovativer API-Client, der den Status Quo von Postman und ähnlichen Tools revolutionieren soll.

View File

@@ -27,6 +27,8 @@
| [正體中文](./readme_zhtw.md)
| [العربية](./readme_ar.md)
| [日本語](./readme_ja.md)
| [ქართული](./readme_ka.md)
Bruno es un cliente de APIs nuevo e innovador, creado con el objetivo de revolucionar el panorama actual representado por Postman y otras herramientas similares.
Bruno almacena tus colecciones directamente en una carpeta de tu sistema de archivos. Usamos un lenguaje de marcado de texto plano, llamado Bru, para guardar información sobre las peticiones a tus APIs.

View File

@@ -27,6 +27,7 @@
| [正體中文](./readme_zhtw.md)
| [العربية](./readme_ar.md)
| [日本語](./readme_ja.md)
| [ქართული](./readme_ka.md)
Bruno est un nouveau client API, innovant, qui a pour but de révolutionner le _statu quo_ que représentent Postman et les autres outils.

View File

@@ -27,6 +27,7 @@
| [正體中文](./readme_zhtw.md)
| [العربية](./readme_ar.md)
| [日本語](./readme_ja.md)
| [ქართული](./readme_ka.md)
Bruno è un nuovo ed innovativo API client, mirato a rivoluzionare lo status quo rappresentato da Postman e strumenti simili disponibili.

View File

@@ -27,6 +27,7 @@
| [正體中文](./readme_zhtw.md)
| [العربية](./readme_ar.md)
| **日本語**
| [ქართული](./readme_ka.md)
Bruno は革新的な API クライアントです。Postman を代表する API クライアントツールの現状に一石を投じることを目指しています。

176
docs/readme/readme_ka.md Normal file
View File

@@ -0,0 +1,176 @@
<br />
<img src="../../assets/images/logo-transparent.png" width="80"/>
### ბრუნო - ღია წყაროების IDE API-ების შესწავლისა და ტესტირებისათვის.
[![GitHub version](https://badge.fury.io/gh/usebruno%2Fbruno.svg)](https://badge.fury.io/gh/usebruno%bruno)
[![CI](https://github.com/usebruno/bruno/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/usebruno/bruno/actions/workflows/tests.yml)
[![Commit Activity](https://img.shields.io/github/commit-activity/m/usebruno/bruno)](https://github.com/usebruno/bruno/pulse)
[![X](https://img.shields.io/twitter/follow/use_bruno?style=social&logo=x)](https://twitter.com/use_bruno)
[![Website](https://img.shields.io/badge/Website-Visit-blue)](https://www.usebruno.com)
[![Download](https://img.shields.io/badge/Download-Latest-brightgreen)](https://www.usebruno.com/downloads)
[English](../../readme.md)
| [Українська](./readme_ua.md)
| [Русский](./readme_ru.md)
| [Türkçe](./readme_tr.md)
| [Deutsch](./readme_de.md)
| [Français](./readme_fr.md)
| [Português (BR)](./readme_pt_br.md)
| [한국어](./readme_kr.md)
| [বাংলা](./readme_bn.md)
| [Español](./readme_es.md)
| [Italiano](./readme_it.md)
| [Română](./readme_ro.md)
| [Polski](./readme_pl.md)
| [简体中文](./readme_cn.md)
| [正體中文](./readme_zhtw.md)
| [العربية](./readme_ar.md)
| [日本語](./readme_ja.md)
| **ქართული**
ბრუნო არის ახალი და ინოვაციური API კლიენტი, რომელიც მიზნად ისახავს პოსტმანისა და მსგავსი ინსტრუმენტების არსებული მდგომარეობის რევოლუციას.
ბრუნო თქვენი კოლექციების შენახვას უშუალოდ თქვენს ფაილური სისტემის ერთ-ერთ საქაღალოში ახდენს. ჩვენ ვხმარობთ უბრალო ტექსტურ მარკაპ ენის, Bru-ს, API მოთხოვნების შესახებ ინფორმაციის შენახვისთვის.
თქვენ შეგიძლიათ გამოიყენოთ Git ან ნებისმიერი ვერსიის კონტროლის სისტემა თქვენი API კოლექციების გასაზიარებლად.
ბრუნო მხოლოდ ოფლაინ რეჟიმში მუშაობს. ბრუნოში ღრუბლური სინქრონიზაციის დამატების გეგმები არ არის. ჩვენ ვაფასებთ თქვენი მონაცემების პრივატობას და creemos, რომ ისინი თქვენს მოწყობილობაში უნდა დარჩეს. წაიკითხეთ ჩვენი გრძელვადიანი ხედვა [აქ](https://github.com/usebruno/bruno/discussions/269)
[დამატებით ბრუნო](https://www.usebruno.com/downloads)
📢 შეიტყვეთ ჩვენი უახლესი საუბრის შესახებ India FOSS 3.0 კონფერენციაზე [აქ](https://www.youtube.com/watch?v=7bSMFpbcPiY)
![bruno](../../assets/images/landing-2.png) <br /><br />
### ოქროს გამოცემა ✨
მთავარი ფუნქციების უმეტესობა უფასოა და ღია წყაროა. ჩვენ ვცდილობთ ჰარმონიული ბალანსის დაცვას [ღია წყაროების პრინციპებსა და მდგრადობას შორის](https://github.com/usebruno/bruno/discussions/269)
თქვენ შეგიძლიათ შეიძინოთ [ოქროს გამოცემა](https://www.usebruno.com/pricing) ერთჯერადი გადახდით **19 დოლარად**! <br/>
### ინსტალაცია
ბრუნო ხელმისაწვდომია როგორც ბინარული ჩამოტვირთვა [ჩვენ的网站上](https://www.usebruno.com/downloads) Mac-ის, Windows-ისა და Linux-ისთვის.
თქვენ ასევე შეგიძლიათ დააინსტალიროთ ბრუნო პაკეტის მენეჯერების საშუალებით, როგორიცაა Homebrew, Chocolatey, Scoop, Snap, Flatpak და Apt.
```sh
# Mac-ზე Homebrew-ს საშუალებით
brew install bruno
# Windows-ზე Chocolatey-ს საშუალებით
choco install bruno
# Windows-ზე Scoop-ის საშუალებით
scoop bucket add extras
scoop install bruno
# Windows-ზე winget-ის საშუალებით
winget install Bruno.Bruno
# Linux-ზე Snap-ის საშუალებით
snap install bruno
# Linux-ზე Flatpak-ის საშუალებით
flatpak install com.usebruno.Bruno
# Linux-ზე Apt-ის საშუალებით
sudo mkdir -p /etc/apt/keyrings
sudo gpg --no-default-keyring --keyring /etc/apt/keyrings/bruno.gpg --keyserver keyserver.ubuntu.com --recv-keys 9FA6017ECABE0266
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/bruno.gpg] http://debian.usebruno.com/ bruno stable" | sudo tee /etc/apt/sources.list.d/bruno.list
sudo apt update
sudo apt install bruno
```
### პლატფორმებს შორის მუშაობა 🖥️
![bruno](../../assets/images/run-anywhere.png) <br /><br />
### თანამშრომლობა Git-ის საშუალებით 👩‍💻🧑‍💻
ან ნებისმიერი ვერსიის კონტროლის სისტემის საშუალებით
![bruno](../../assets/images/version-control.png) <br /><br />
### სპონსორები
#### ოქროს სპონსორები
<img src="../../assets/images/sponsors/samagata.png" width="150"/>
#### ვერცხლის სპონსორები
<img src="../../assets/images/sponsors/commit-company.png" width="70"/>
#### ბრინჯის სპონსორები
<a href="https://zuplo.link/bruno">
<img src="../../assets/images/sponsors/zuplo.png" width="120"/>
</a>
### მნიშვნელოვანი ბმულები 📌
- [ჩვენი გრძელვადიანი ხედვა](https://github.com/usebruno/bruno/discussions/269)
- [გეგმა](https://github.com/usebruno/bruno/discussions/384)
- [დოკუმენტაცია](https://docs.usebruno.com)
- [Stack Overflow](https://stackoverflow.com/questions/tagged/bruno)
- [ვებსაიტი](https://www.usebruno.com)
- [ფასები](https://www.usebruno.com/pricing)
- [დამატება](https://www.usebruno.com/downloads)
- [GitHub სპონსორები](https://github.com/sponsors/helloanoop).
### ვიტრინა 🎥
- [მოწონებები](https://github.com/usebruno/bruno/discussions/343)
- [მეცნიერების ჰაბი](https://github.com/usebruno/bruno/discussions/386)
- [Scriptmania](https://github.com/usebruno/bruno/discussions/385)
### მხარდაჭერა ❤️
თუ გიყვართ ბრუნო და გინდათ მხარი დაუჭიროთ ჩვენს ღია წყაროების მუშაობას, გაითვალისწინეთ ჩვენი დახმარება [GitHub სპონსორების საშუალებით](https://github.com/sponsors/helloanoop).
### გააზიარეთ მოწმობები 📣
თუ ბრუნო დაგეხმარათ თქვენს სამუშაოში და გუნდებში, გთხოვთ, არ დაგავიწყდეთ ჩვენი [მოწონებების გაზიარება ჩვენს GitHub განხილვაში](https://github.com/usebruno/bruno/discussions/343)
### ახალი პაკეტის მენეჯერებში გამოქვეყნება
იხილეთ [აქ](../../publishing.md) მეტი ინფორმაციისათვის.
### დაინტერესდით 🌐
[𝕎 (Twitter)](https://twitter.com/use_bruno) <br />
[ვებსაიტი](https://www.usebruno.com) <br />
[Discord](https://discord.com/invite/KgcZUncpjq) <br />
[LinkedIn](https://www.linkedin.com/company/usebruno)
### სავაჭრო ნიშანი
**სახელი**
`ბრუნო` არის სავაჭრო ნიშანი, რომელსაც ფლობს [ანუპ მ. დ.](https://www.helloanoop.com/)
**ლოგო**
ლოგო არის [OpenMoji](https://openmoji.org/library/emoji-1F436/) სურათებიდან. ლიცენზია: CC [BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)
### თანამშრომლობა 👩‍💻🧑‍💻
მიხარია, რომ დაინტერესებული ხართ ბრუნოს გაუმჯობესებით. გთხოვთ, გადახედეთ [თანამშრომლობის სახელმძღვანელოს](../../contributing.md)
თუნდაც ვერ მოახერხოთ კოდის საშუალებით კონტრიბუცია, ნუ ინანებთ პრობლემების და ფუნქციის მოთხოვნების ჩაწერას, რომლებიც უნდა განხორციელდეს თქვენი შემთხვევის გადასაჭრელად.
### ავტორები
<div align="center">
<a href="https://github.com/usebruno/bruno/graphs/contributors">
<img src="https://contrib.rocks/image?repo=usebruno/bruno" />
</a>
</div>
### ლიცენზია 📄
[MIT](../../license.md)

View File

@@ -27,6 +27,7 @@
| [正體中文](./readme_zhtw.md)
| [العربية](./readme_ar.md)
| [日本語](./readme_ja.md)
| [ქართული](./readme_ka.md)
Bruno는 새롭고 혁신적인 API 클라이언트로, Postman과 유사한 툴들을 혁신하는 것을 목표로 합니다.

View File

@@ -27,6 +27,7 @@
| [正體中文](./readme_zhtw.md)
| [العربية](./readme_ar.md)
| [日本語](./readme_ja.md)
| [ქართული](./readme_ka.md)
Bruno to nowy i innowacyjny klient API, którego celem jest zrewolucjonizowanie status quo reprezentowanego przez narzędzia takie jak Postman.

View File

@@ -27,6 +27,7 @@
| [正體中文](./readme_zhtw.md)
| [العربية](./readme_ar.md)
| [日本語](./readme_ja.md)
| [ქართული](./readme_ka.md)
Bruno é um novo e inovador cliente de API, com o objetivo de revolucionar o status quo representado por ferramentas como o Postman e outras semelhantes.

View File

@@ -27,6 +27,7 @@
| [正體中文](./readme_zhtw.md)
| [العربية](./readme_ar.md)
| [日本語](./readme_ja.md)
| [ქართული](./readme_ka.md)
Bruno este un client API nou și inovativ, care vizează să revoluționeze status quo-ul reprezentat de Postman și alte instrumente similare.

View File

@@ -27,6 +27,7 @@
| [正體中文](./readme_zhtw.md)
| [العربية](./readme_ar.md)
| [日本語](./readme_ja.md)
| [ქართული](./readme_ka.md)
Bruno - новый и инновационный клиент API, направленный на революцию в установившейся ситуации, представленной Postman и подобными инструментами.

View File

@@ -27,6 +27,7 @@
| [正體中文](./readme_zhtw.md)
| [العربية](./readme_ar.md)
| [日本語](./readme_ja.md)
| [ქართული](./readme_ka.md)
Bruno, Postman ve benzeri araçlar tarafından temsil edilen statükoda devrim yaratmayı amaçlayan yeni ve yenilikçi bir API istemcisidir.

View File

@@ -27,6 +27,7 @@
| [正體中文](./readme_zhtw.md)
| [العربية](./readme_ar.md)
| [日本語](./readme_ja.md)
| [ქართული](./readme_ka.md)
Bruno це новий та іноваційний API клієнт, націлений на революційну зміну статус кво, запровадженого інструментами на кшталт Postman.

View File

@@ -27,6 +27,7 @@
| **正體中文**
| [العربية](./readme_ar.md)
| [日本語](./readme_ja.md)
| [ქართული](./readme_ka.md)
Bruno 是一個全新且有創新性的 API 用戶端,目的在徹底改變以 Postman 和其他類似工具的現況。

116
package-lock.json generated
View File

@@ -50,7 +50,6 @@
},
"node_modules/@ampproject/remapping": {
"version": "2.3.0",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
@@ -671,7 +670,6 @@
},
"node_modules/@babel/compat-data": {
"version": "7.25.2",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -679,7 +677,6 @@
},
"node_modules/@babel/core": {
"version": "7.25.2",
"dev": true,
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "^2.2.0",
@@ -743,7 +740,6 @@
},
"node_modules/@babel/helper-compilation-targets": {
"version": "7.25.2",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/compat-data": "^7.25.2",
@@ -758,7 +754,6 @@
},
"node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": {
"version": "5.1.1",
"dev": true,
"license": "ISC",
"dependencies": {
"yallist": "^3.0.2"
@@ -766,7 +761,6 @@
},
"node_modules/@babel/helper-compilation-targets/node_modules/yallist": {
"version": "3.1.1",
"dev": true,
"license": "ISC"
},
"node_modules/@babel/helper-create-class-features-plugin": {
@@ -845,7 +839,6 @@
},
"node_modules/@babel/helper-module-transforms": {
"version": "7.25.2",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-module-imports": "^7.24.7",
@@ -912,7 +905,6 @@
},
"node_modules/@babel/helper-simple-access": {
"version": "7.24.7",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/traverse": "^7.24.7",
@@ -950,7 +942,6 @@
},
"node_modules/@babel/helper-validator-option": {
"version": "7.24.8",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -971,7 +962,6 @@
},
"node_modules/@babel/helpers": {
"version": "7.25.0",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/template": "^7.25.0",
@@ -3654,6 +3644,37 @@
"node": ">=12"
}
},
"node_modules/@n8n/vm2": {
"version": "3.9.25",
"resolved": "https://registry.npmjs.org/@n8n/vm2/-/vm2-3.9.25.tgz",
"integrity": "sha512-qoGLFzyHBW7HKpwXkl05QKsIh3GkDw6lOiTOWYlUDnOIQ1b7EgM+O5EMjrMGy7r+kz52+Q7o6GLxBIcxVI8rEg==",
"license": "MIT",
"peer": true,
"dependencies": {
"acorn": "^8.7.0",
"acorn-walk": "^8.2.0"
},
"bin": {
"vm2": "bin/vm2"
},
"engines": {
"node": ">=18.10",
"pnpm": ">=9.6"
}
},
"node_modules/@n8n/vm2/node_modules/acorn": {
"version": "8.12.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
"integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/@next/env": {
"version": "12.3.3",
"license": "MIT"
@@ -4730,7 +4751,6 @@
},
"node_modules/@types/linkify-it": {
"version": "5.0.0",
"dev": true,
"license": "MIT"
},
"node_modules/@types/lodash": {
@@ -4739,7 +4759,6 @@
},
"node_modules/@types/markdown-it": {
"version": "12.2.3",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/linkify-it": "*",
@@ -4748,7 +4767,6 @@
},
"node_modules/@types/mdurl": {
"version": "2.0.0",
"dev": true,
"license": "MIT"
},
"node_modules/@types/minimatch": {
@@ -6222,7 +6240,6 @@
},
"node_modules/browserslist": {
"version": "4.23.3",
"dev": true,
"funding": [
{
"type": "opencollective",
@@ -7221,7 +7238,6 @@
},
"node_modules/convert-source-map": {
"version": "2.0.0",
"dev": true,
"license": "MIT"
},
"node_modules/cookie": {
@@ -8461,7 +8477,6 @@
},
"node_modules/electron-to-chromium": {
"version": "1.5.11",
"dev": true,
"license": "ISC"
},
"node_modules/electron-util": {
@@ -9423,7 +9438,6 @@
},
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -10109,6 +10123,15 @@
"node": ">= 12"
}
},
"node_modules/html-parse-stringify": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
"integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
"license": "MIT",
"dependencies": {
"void-elements": "3.1.0"
}
},
"node_modules/html-webpack-plugin": {
"version": "5.6.0",
"dev": true,
@@ -10254,6 +10277,29 @@
"url": "https://github.com/sponsors/typicode"
}
},
"node_modules/i18next": {
"version": "23.14.0",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-23.14.0.tgz",
"integrity": "sha512-Y5GL4OdA8IU2geRrt2+Uc1iIhsjICdHZzT9tNwQ3TVqdNzgxHToGCKf/TPRP80vTCAP6svg2WbbJL+Gx5MFQVA==",
"funding": [
{
"type": "individual",
"url": "https://locize.com"
},
{
"type": "individual",
"url": "https://locize.com/i18next.html"
},
{
"type": "individual",
"url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
}
],
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.23.2"
}
},
"node_modules/iconv-corefoundation": {
"version": "1.1.7",
"license": "MIT",
@@ -13140,7 +13186,6 @@
},
"node_modules/node-releases": {
"version": "2.0.18",
"dev": true,
"license": "MIT"
},
"node_modules/node-vault": {
@@ -15225,6 +15270,28 @@
"react-dom": ">=16"
}
},
"node_modules/react-i18next": {
"version": "15.0.1",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.0.1.tgz",
"integrity": "sha512-NwxLqNM6CLbeGA9xPsjits0EnXdKgCRSS6cgkgOdNcPXqL+1fYNl8fBg1wmnnHvFy812Bt4IWTPE9zjoPmFj3w==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.24.8",
"html-parse-stringify": "^3.0.1"
},
"peerDependencies": {
"i18next": ">= 23.2.3",
"react": ">= 16.8.0"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
}
}
},
"node_modules/react-inspector": {
"version": "6.0.2",
"license": "MIT",
@@ -16134,7 +16201,6 @@
},
"node_modules/semver": {
"version": "6.3.1",
"dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
@@ -17597,7 +17663,6 @@
},
"node_modules/update-browserslist-db": {
"version": "1.1.0",
"dev": true,
"funding": [
{
"type": "opencollective",
@@ -17866,6 +17931,15 @@
"node": ">=0.4.0"
}
},
"node_modules/void-elements": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
"integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/vscode-languageserver-types": {
"version": "3.17.5",
"license": "MIT"
@@ -18376,6 +18450,7 @@
"graphql": "^16.6.0",
"graphql-request": "^3.7.0",
"httpsnippet": "^3.0.6",
"i18next": "^23.14.0",
"idb": "^7.0.0",
"immer": "^9.0.15",
"jsesc": "^3.0.2",
@@ -18405,6 +18480,7 @@
"react-dom": "18.2.0",
"react-github-btn": "^1.4.0",
"react-hot-toast": "^2.4.0",
"react-i18next": "^15.0.1",
"react-inspector": "^6.0.2",
"react-pdf": "^7.5.1",
"react-redux": "^7.2.6",

View File

@@ -37,14 +37,15 @@
"graphql": "^16.6.0",
"graphql-request": "^3.7.0",
"httpsnippet": "^3.0.6",
"i18next": "^23.14.0",
"idb": "^7.0.0",
"immer": "^9.0.15",
"jsesc": "^3.0.2",
"jshint": "^2.13.6",
"json5": "^2.2.3",
"jsonc-parser": "^3.2.1",
"jsonpath-plus": "^7.2.0",
"jsonlint": "^1.6.3",
"jsonpath-plus": "^7.2.0",
"know-your-http-well": "^0.5.0",
"lodash": "^4.17.21",
"markdown-it": "^13.0.2",
@@ -66,6 +67,7 @@
"react-dom": "18.2.0",
"react-github-btn": "^1.4.0",
"react-hot-toast": "^2.4.0",
"react-i18next": "^15.0.1",
"react-inspector": "^6.0.2",
"react-pdf": "^7.5.1",
"react-redux": "^7.2.6",

View File

@@ -67,6 +67,7 @@ if (!SERVER_RENDERED) {
'bru.setVar(key,value)',
'bru.deleteVar(key)',
'bru.setNextRequest(requestName)',
'req.disableParsingResponseJson()'
'bru.getRequestVar(key)',
'bru.sleep(ms)'
];

View File

@@ -19,8 +19,8 @@ const FolderSettings = ({ collection, folder }) => {
const setTab = (tab) => {
dispatch(
updatedFolderSettingsSelectedTab({
collectionUid: collection.uid,
folderUid: folder.uid,
collectionUid: collection?.uid,
folderUid: folder?.uid,
tab
})
);

View File

@@ -17,7 +17,7 @@ const StyledWrapper = styled.div`
overflow: hidden !important;
${'' /* padding-bottom: 50px !important; */}
position: relative;
display: contents;
display: block;
margin: 0px;
padding: 0px;
}

View File

@@ -1,10 +1,10 @@
import React from 'react';
import { IconSpeakerphone, IconBrandTwitter, IconBrandGithub, IconBrandDiscord, IconBook } from '@tabler/icons';
import StyledWrapper from './StyledWrapper';
import { useDictionary } from 'providers/Dictionary/index';
import { useTranslation } from 'react-i18next';
const Support = () => {
const { dictionary } = useDictionary();
const { t } = useTranslation();
return (
<StyledWrapper>
@@ -12,31 +12,31 @@ const Support = () => {
<div className="mt-2">
<a href="https://docs.usebruno.com" target="_blank" className="flex items-end">
<IconBook size={18} strokeWidth={2} />
<span className="label ml-2">{dictionary.documentation}</span>
<span className="label ml-2">{t('COMMON.DOCUMENTATION')}</span>
</a>
</div>
<div className="mt-2">
<a href="https://github.com/usebruno/bruno/issues" target="_blank" className="flex items-end">
<IconSpeakerphone size={18} strokeWidth={2} />
<span className="label ml-2">{dictionary.reportIssues}</span>
<span className="label ml-2">{t('COMMON.REPORT_ISSUES')}</span>
</a>
</div>
<div className="mt-2">
<a href="https://discord.com/invite/KgcZUncpjq" target="_blank" className="flex items-end">
<IconBrandDiscord size={18} strokeWidth={2} />
<span className="label ml-2">{dictionary.discord}</span>
<span className="label ml-2">{t('COMMON.DISCORD')}</span>
</a>
</div>
<div className="mt-2">
<a href="https://github.com/usebruno/bruno" target="_blank" className="flex items-end">
<IconBrandGithub size={18} strokeWidth={2} />
<span className="label ml-2">{dictionary.gitHub}</span>
<span className="label ml-2">{t('COMMON.GITHUB')}</span>
</a>
</div>
<div className="mt-2">
<a href="https://twitter.com/use_bruno" target="_blank" className="flex items-end">
<IconBrandTwitter size={18} strokeWidth={2} />
<span className="label ml-2">{dictionary.twitter}</span>
<span className="label ml-2">{t('COMMON.TWITTER')}</span>
</a>
</div>
</div>

View File

@@ -17,8 +17,6 @@ const Timeline = ({ request, response }) => {
});
});
let requestData = safeStringifyJSON(request.data);
return (
<StyledWrapper className="pb-4 w-full">
<div>
@@ -33,9 +31,10 @@ const Timeline = ({ request, response }) => {
);
})}
{requestData ? (
{request.data ? (
<pre className="line request">
<span className="arrow">{'>'}</span> data {requestData}
<span className="arrow">{'>'}</span> data{' '}
<pre className="text-sm flex flex-wrap whitespace-break-spaces">{request.data}</pre>
</pre>
) : null}
</div>

View File

@@ -189,16 +189,28 @@ const CollectionItem = ({ item, collection, searchText }) => {
toast.error('URL is required');
}
};
const viewFolderSettings = () => {
dispatch(
addTab({
uid: uuid(),
collectionUid: collection.uid,
folderUid: item.uid,
type: 'folder-settings'
})
);
if (isItemAFolder(item)) {
if (itemIsOpenedInTabs(item, tabs)) {
dispatch(
focusTab({
uid: item.uid
})
);
return;
}
dispatch(
addTab({
uid: item.uid,
collectionUid: collection.uid,
type: 'folder-settings'
})
);
return;
}
};
const requestItems = sortRequestItems(filter(item.items, (i) => isItemARequest(i)));
const folderItems = sortFolderItems(filter(item.items, (i) => isItemAFolder(i)));

View File

@@ -1,6 +1,7 @@
import { useState } from 'react';
import toast from 'react-hot-toast';
import { useDispatch } from 'react-redux';
import { useTranslation } from 'react-i18next';
import { openCollection, importCollection } from 'providers/ReduxStore/slices/collections/actions';
import { IconBrandGithub, IconPlus, IconDownload, IconFolders, IconSpeakerphone, IconBook } from '@tabler/icons';
@@ -9,11 +10,10 @@ import CreateCollection from 'components/Sidebar/CreateCollection';
import ImportCollection from 'components/Sidebar/ImportCollection';
import ImportCollectionLocation from 'components/Sidebar/ImportCollectionLocation';
import StyledWrapper from './StyledWrapper';
import { useDictionary } from 'providers/Dictionary/index';
const Welcome = () => {
const dispatch = useDispatch();
const { dictionary } = useDictionary();
const { t } = useTranslation();
const [importedCollection, setImportedCollection] = useState(null);
const [importedTranslationLog, setImportedTranslationLog] = useState({});
const [createCollectionModalOpen, setCreateCollectionModalOpen] = useState(false);
@@ -22,7 +22,7 @@ const Welcome = () => {
const handleOpenCollection = () => {
dispatch(openCollection()).catch(
(err) => console.log(err) && toast.error(dictionary.errorWhileOpeningCollection)
(err) => console.log(err) && toast.error(t('WELCOME.COLLECTION_OPEN_ERROR'))
);
};
@@ -40,12 +40,12 @@ const Welcome = () => {
.then(() => {
setImportCollectionLocationModalOpen(false);
setImportedCollection(null);
toast.success(dictionary.collectionImportedSuccessfully);
toast.success(t('WELCOME.COLLECTION_IMPORT_SUCCESS'));
})
.catch((err) => {
setImportCollectionLocationModalOpen(false);
console.error(err);
toast.error(dictionary.errorWhileImportingCollection);
toast.error(t('WELCOME.COLLECTION_IMPORT_ERROR'));
});
};
@@ -68,45 +68,45 @@ const Welcome = () => {
<Bruno width={50} />
</div>
<div className="text-xl font-semibold select-none">bruno</div>
<div className="mt-4">{dictionary.aboutBruno}</div>
<div className="mt-4">{t('WELCOME.ABOUT_BRUNO')}</div>
<div className="uppercase font-semibold heading mt-10">{dictionary.collections}</div>
<div className="uppercase font-semibold heading mt-10">{t('COMMON.COLLECTIONS')}</div>
<div className="mt-4 flex items-center collection-options select-none">
<div className="flex items-center" onClick={() => setCreateCollectionModalOpen(true)}>
<IconPlus size={18} strokeWidth={2} />
<span className="label ml-2" id="create-collection">
{dictionary.createCollection}
{t('WELCOME.CREATE_COLLECTION')}
</span>
</div>
<div className="flex items-center ml-6" onClick={handleOpenCollection}>
<IconFolders size={18} strokeWidth={2} />
<span className="label ml-2">{dictionary.openCollection}</span>
<span className="label ml-2">{t('WELCOME.OPEN_COLLECTION')}</span>
</div>
<div className="flex items-center ml-6" onClick={() => setImportCollectionModalOpen(true)}>
<IconDownload size={18} strokeWidth={2} />
<span className="label ml-2" id="import-collection">
{dictionary.importCollection}
{t('WELCOME.IMPORT_COLLECTION')}
</span>
</div>
</div>
<div className="uppercase font-semibold heading mt-10 pt-6">Links</div>
<div className="uppercase font-semibold heading mt-10 pt-6">{t('WELCOME.LINKS')}</div>
<div className="mt-4 flex flex-col collection-options select-none">
<div className="flex items-center mt-2">
<a href="https://docs.usebruno.com" target="_blank" className="inline-flex items-center">
<IconBook size={18} strokeWidth={2} />
<span className="label ml-2">{dictionary.documentation}</span>
<span className="label ml-2">{t('COMMON.DOCUMENTATION')}</span>
</a>
</div>
<div className="flex items-center mt-2">
<a href="https://github.com/usebruno/bruno/issues" target="_blank" className="inline-flex items-center">
<IconSpeakerphone size={18} strokeWidth={2} />
<span className="label ml-2">{dictionary.reportIssues}</span>
<span className="label ml-2">{t('COMMON.REPORT_ISSUES')}</span>
</a>
</div>
<div className="flex items-center mt-2">
<a href="https://github.com/usebruno/bruno" target="_blank" className="flex items-center">
<IconBrandGithub size={18} strokeWidth={2} />
<span className="label ml-2">{dictionary.gitHub}</span>
<span className="label ml-2">{t('COMMON.GITHUB')}</span>
</a>
</div>
</div>

View File

@@ -1,16 +0,0 @@
export default {
aboutBruno: 'Opensource IDE for exploring and testing APIs',
collections: 'Collections',
createCollection: 'Create Collection',
openCollection: 'Open Collection',
importCollection: 'Import Collection',
documentation: 'Documentation',
reportIssues: 'Report Issues',
gitHub: 'GitHub',
collectionImportedSuccessfully: 'Collection imported successfully',
errorWhileOpeningCollection: 'An error occurred while opening the collection',
errorWhileImportingCollection:
'An error occurred while importing the collection. Check the logs for more information.',
discord: 'Discord',
twitter: 'Twitter'
};

View File

@@ -1,5 +0,0 @@
import en from './en.js';
export const dictionaries = {
en
};

View File

@@ -0,0 +1,24 @@
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import translationEn from './translation/en.json';
const resources = {
en: {
translation: translationEn,
},
};
i18n
.use(initReactI18next) // passes i18n down to react-i18next
.init({
resources,
lng: 'en', // Use "en" as the default language. "cimode" can be used to debug / show translation placeholder
ns: 'translation', // Use translation as the default Namespace that will be loaded by default
interpolation: {
escapeValue: false // react already safes from xss
}
});
export default i18n;

View File

@@ -0,0 +1,20 @@
{
"COMMON": {
"COLLECTIONS": "Collections",
"DOCUMENTATION": "Documentation",
"REPORT_ISSUES": "Report Issues",
"GITHUB": "GitHub",
"DISCORD": "Discord",
"TWITTER": "Twitter"
},
"WELCOME": {
"ABOUT_BRUNO": "Opensource IDE for exploring and testing APIs",
"LINKS": "Links",
"CREATE_COLLECTION": "Create Collection",
"OPEN_COLLECTION": "Open Collection",
"IMPORT_COLLECTION": "Import Collection",
"COLLECTION_IMPORT_SUCCESS": "Collection imported successfully",
"COLLECTION_IMPORT_ERROR": "An error occurred while importing the collection. Check the logs for more information.",
"COLLECTION_OPEN_ERROR": "An error occurred while opening the collection"
}
}

View File

@@ -23,7 +23,6 @@ import '@fontsource/inter/600.css';
import '@fontsource/inter/700.css';
import '@fontsource/inter/800.css';
import '@fontsource/inter/900.css';
import { DictionaryProvider } from 'providers/Dictionary/index';
function SafeHydrate({ children }) {
return <div suppressHydrationWarning>{typeof window === 'undefined' ? null : children}</div>;
@@ -69,15 +68,13 @@ function MyApp({ Component, pageProps }) {
<NoSsr>
<Provider store={ReduxStore}>
<ThemeProvider>
<DictionaryProvider>
<ToastProvider>
<AppProvider>
<HotkeysProvider>
<Component {...pageProps} />
</HotkeysProvider>
</AppProvider>
</ToastProvider>
</DictionaryProvider>
<ToastProvider>
<AppProvider>
<HotkeysProvider>
<Component {...pageProps} />
</HotkeysProvider>
</AppProvider>
</ToastProvider>
</ThemeProvider>
</Provider>
</NoSsr>

View File

@@ -1,6 +1,7 @@
import Head from 'next/head';
import Bruno from './Bruno';
import GlobalStyle from '../globalStyles';
import '../i18n';
export default function Home() {
return (

View File

@@ -1,28 +0,0 @@
import React from 'react';
import { useState, useContext } from 'react';
import { dictionaries } from 'src/dictionaries/index';
export const DictionaryContext = React.createContext();
const DictionaryProvider = (props) => {
const [language, setLanguage] = useState('en');
const dictionary = dictionaries[language] ?? dictionaries.en;
return (
<DictionaryContext.Provider {...props} value={{ language, setLanguage, dictionary }}>
<>{props.children}</>
</DictionaryContext.Provider>
);
};
const useDictionary = () => {
const context = useContext(DictionaryContext);
if (context === undefined) {
throw new Error(`useDictionary must be used within a DictionaryProvider`);
}
return context;
};
export { useDictionary, DictionaryProvider };

View File

@@ -41,7 +41,7 @@ export const tabsSlice = createSlice({
requestPaneTab: action.payload.requestPaneTab || 'params',
responsePaneTab: 'response',
type: action.payload.type || 'request',
...(action.payload.folderUid ? { folderUid: action.payload.folderUid } : {})
...(action.payload.uid ? { folderUid: action.payload.uid } : {})
});
state.activeTabUid = action.payload.uid;
},

View File

@@ -44,7 +44,8 @@ export const parsePathParams = (url) => {
try {
uri = new URL(uri);
} catch (e) {
throw e;
// URL is non-parsable, is it incomplete? Ignore.
return [];
}
let paths = uri.pathname.split('/');

View File

@@ -1,5 +1,15 @@
const fs = require('fs');
const path = require('path');
const isDev = require('electron-is-dev');
if (isDev) {
if (!fs.existsSync('./src/sandbox/bundle-browser-rollup.js')) {
console.log('JS Sandbox libraries have not been bundled yet');
console.log('Please run the below command \nnpm run sandbox:bundle-libraries --workspace=packages/bruno-js');
throw new Error('JS Sandbox libraries have not been bundled yet');
}
}
const { format } = require('url');
const { BrowserWindow, app, Menu, ipcMain } = require('electron');
const { setContentSecurityPolicy } = require('electron-util');
@@ -70,7 +80,7 @@ app.on('ready', async () => {
mainWindow.once('ready-to-show', () => {
mainWindow.show();
})
});
const url = isDev
? 'http://localhost:3000'
: format({

View File

@@ -272,7 +272,7 @@ const configureRequest = async (
return axiosInstance;
};
const parseDataFromResponse = (response) => {
const parseDataFromResponse = (response, disableParsingResponseJson = false) => {
// Parse the charset from content type: https://stackoverflow.com/a/33192813
const charsetMatch = /charset=([^()<>@,;:"/[\]?.=\s]*)/i.exec(response.headers['content-type'] || '');
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec#using_exec_with_regexp_literals
@@ -290,7 +290,9 @@ const parseDataFromResponse = (response) => {
// Filter out ZWNBSP character
// https://gist.github.com/antic183/619f42b559b78028d1fe9e7ae8a1352d
data = data.replace(/^\uFEFF/, '');
data = JSON.parse(data);
if(!disableParsingResponseJson) {
data = JSON.parse(data);
}
} catch {}
return { data, dataBuffer };
@@ -540,7 +542,7 @@ const registerNetworkIpc = (mainWindow) => {
// Continue with the rest of the request lifecycle - post response vars, script, assertions, tests
const { data, dataBuffer } = parseDataFromResponse(response);
const { data, dataBuffer } = parseDataFromResponse(response, request.__brunoDisableParsingResponseJson);
response.data = data;
response.responseTime = responseTime;
@@ -701,7 +703,7 @@ const registerNetworkIpc = (mainWindow) => {
}
}
const { data } = parseDataFromResponse(response);
const { data } = parseDataFromResponse(response, request.__brunoDisableParsingResponseJson);
response.data = data;
await runPostResponse(
@@ -969,7 +971,7 @@ const registerNetworkIpc = (mainWindow) => {
response = await axiosInstance(request);
timeEnd = Date.now();
const { data, dataBuffer } = parseDataFromResponse(response);
const { data, dataBuffer } = parseDataFromResponse(response, request.__brunoDisableParsingResponseJson);
response.data = data;
response.responseTime = response.headers.get('request-duration');

View File

@@ -59,14 +59,6 @@ const interpolateVars = (request, envVars = {}, runtimeVariables = {}, processEn
const contentType = getContentType(request.headers);
if (contentType.includes('json')) {
if (typeof request.data === 'object') {
try {
let parsed = JSON.stringify(request.data);
parsed = _interpolate(parsed);
request.data = JSON.parse(parsed);
} catch (err) {}
}
if (typeof request.data === 'string') {
if (request.data.length) {
request.data = _interpolate(request.data);

View File

@@ -1,7 +1,6 @@
const os = require('os');
const { get, each, filter, extend, compact } = require('lodash');
const decomment = require('decomment');
var JSONbig = require('json-bigint');
const FormData = require('form-data');
const fs = require('fs');
const path = require('path');
@@ -342,16 +341,10 @@ const prepareRequest = (item, collection) => {
if (!contentTypeDefined) {
axiosRequest.headers['content-type'] = 'application/json';
}
let jsonBody;
try {
jsonBody = decomment(request?.body?.json);
axiosRequest.data = decomment(request?.body?.json);
} catch (error) {
jsonBody = request?.body?.json;
}
try {
axiosRequest.data = JSONbig.parse(jsonBody);
} catch (error) {
axiosRequest.data = jsonBody;
axiosRequest.data = request?.body?.json;
}
}

View File

@@ -6,7 +6,7 @@ describe('prepare-request: prepareRequest', () => {
describe('Decomments request body', () => {
it('If request body is valid JSON', async () => {
const body = { mode: 'json', json: '{\n"test": "{{someVar}}" // comment\n}' };
const expected = { test: '{{someVar}}' };
const expected = '{\n"test": "{{someVar}}" \n}';
const result = prepareRequest({ request: { body } }, {});
expect(result.data).toEqual(expected);
});

View File

@@ -1,11 +1,34 @@
class BrunoRequest {
/**
* The following properties are available as shorthand:
* - req.url
* - req.method
* - req.headers
* - req.timeout
* - req.body
*
* Above shorthands are useful for accessing the request properties directly in the scripts
* It must be noted that the user cannot set these properties directly.
* They should use the respective setter methods to set these properties.
*/
constructor(req) {
this.req = req;
this.url = req.url;
this.method = req.method;
this.headers = req.headers;
this.body = req.data;
this.timeout = req.timeout;
/**
* We automatically parse the JSON body if the content type is JSON
* This is to make it easier for the user to access the body directly
*
* It must be noted that the request data is always a string and is what gets sent over the network
* If the user wants to access the raw data, they can use getBody({raw: true}) method
*/
const isJson = this.hasJSONContentType(this.req.headers);
if (isJson) {
this.body = this.__safeParseJSON(req.data);
}
}
getUrl() {
@@ -13,6 +36,7 @@ class BrunoRequest {
}
setUrl(url) {
this.url = url;
this.req.url = url;
}
@@ -37,6 +61,7 @@ class BrunoRequest {
}
setMethod(method) {
this.method = method;
this.req.method = method;
}
@@ -45,6 +70,7 @@ class BrunoRequest {
}
setHeaders(headers) {
this.headers = headers;
this.req.headers = headers;
}
@@ -53,15 +79,60 @@ class BrunoRequest {
}
setHeader(name, value) {
this.headers[name] = value;
this.req.headers[name] = value;
}
getBody() {
hasJSONContentType(headers) {
const contentType = headers?.['Content-Type'] || headers?.['content-type'] || '';
return contentType.includes('json');
}
/**
* Get the body of the request
*
* We automatically parse and return the JSON body if the content type is JSON
* If the user wants the raw body, they can pass the raw option as true
*/
getBody(options = {}) {
if (options.raw) {
return this.req.data;
}
const isJson = this.hasJSONContentType(this.req.headers);
if (isJson) {
return this.__safeParseJSON(this.req.data);
}
return this.req.data;
}
setBody(data) {
/**
* If the content type is JSON and if the data is an object
* - We set the body property as the object itself
* - We set the request data as the stringified JSON as it is what gets sent over the network
* Otherwise
* - We set the request data as the data itself
* - We set the body property as the data itself
*
* If the user wants to override this behavior, they can pass the raw option as true
*/
setBody(data, options = {}) {
if (options.raw) {
this.req.data = data;
this.body = data;
return;
}
const isJson = this.hasJSONContentType(this.req.headers);
if (isJson && this.__isObject(data)) {
this.body = data;
this.req.data = this.__safeStringifyJSON(data);
return;
}
this.req.data = data;
this.body = data;
}
setMaxRedirects(maxRedirects) {
@@ -73,8 +144,34 @@ class BrunoRequest {
}
setTimeout(timeout) {
this.timeout = timeout;
this.req.timeout = timeout;
}
__safeParseJSON(str) {
try {
return JSON.parse(str);
} catch (e) {
return str;
}
}
__safeStringifyJSON(obj) {
try {
return JSON.stringify(obj);
} catch (e) {
return obj;
}
}
__isObject(obj) {
return obj !== null && typeof obj === 'object';
}
disableParsingResponseJson() {
this.req.__brunoDisableParsingResponseJson = true;
}
}
module.exports = BrunoRequest;

View File

@@ -15,7 +15,7 @@ const BrunoRequest = require('../bruno-request');
const BrunoResponse = require('../bruno-response');
const Test = require('../test');
const TestResults = require('../test-results');
const { cleanJson, appendAwaitToTestFunc } = require('../utils');
const { cleanJson } = require('../utils');
// Inbuilt Library Support
const ajv = require('ajv');
@@ -84,8 +84,6 @@ class TestRuntime {
};
}
// add 'await' prefix to the test function calls
testsFile = appendAwaitToTestFunc(testsFile);
const context = {
test,

View File

@@ -142,15 +142,10 @@ const cleanJson = (data) => {
}
};
const appendAwaitToTestFunc = (str) => {
return str.replace(/(?<!\.\s*)(?<!await\s)(test\()/g, 'await $1');
};
module.exports = {
evaluateJsExpression,
evaluateJsTemplateLiteral,
createResponseParser,
internalExpressionCache,
cleanJson,
appendAwaitToTestFunc
cleanJson
};

View File

@@ -1,10 +1,5 @@
const { describe, it, expect } = require('@jest/globals');
const {
evaluateJsExpression,
internalExpressionCache: cache,
createResponseParser,
appendAwaitToTestFunc
} = require('../src/utils');
const { evaluateJsExpression, internalExpressionCache: cache, createResponseParser } = require('../src/utils');
describe('utils', () => {
describe('expression evaluation', () => {
@@ -142,70 +137,4 @@ describe('utils', () => {
expect(value).toBe(20);
});
});
describe('appendAwaitToTestFunc function', () => {
it('example 1', () => {
const inputTestsString = `
test("should return json", function() {
const data = res.getBody();
expect(res.getBody()).to.eql({
"hello": "bruno"
});
});
`;
const ouutputTestsString = appendAwaitToTestFunc(inputTestsString);
expect(ouutputTestsString).toBe(`
await test("should return json", function() {
const data = res.getBody();
expect(res.getBody()).to.eql({
"hello": "bruno"
});
});
`);
});
it('example 2', () => {
const inputTestsString = `
await test("should return json", function() {
const data = res.getBody();
expect(res.getBody()).to.eql({
"hello": "bruno"
});
});
test("should return json", function() {
const data = res.getBody();
expect(res.getBody()).to.eql({
"hello": "bruno"
});
});
test("should return json", function() {
const data = res.getBody();
expect(res.getBody()).to.eql({
"hello": "bruno"
});
});
`;
const ouutputTestsString = appendAwaitToTestFunc(inputTestsString);
expect(ouutputTestsString).toBe(`
await test("should return json", function() {
const data = res.getBody();
expect(res.getBody()).to.eql({
"hello": "bruno"
});
});
await test("should return json", function() {
const data = res.getBody();
expect(res.getBody()).to.eql({
"hello": "bruno"
});
});
await test("should return json", function() {
const data = res.getBody();
expect(res.getBody()).to.eql({
"hello": "bruno"
});
});
`);
});
});
});

View File

@@ -0,0 +1,44 @@
meta {
name: echo bigint
type: http
seq: 6
}
post {
url: {{host}}/api/echo/json
body: json
auth: none
}
headers {
foo: bar
}
auth:basic {
username: asd
password: j
}
auth:bearer {
token:
}
body:json {
{
"hello": 990531470713421825
}
}
body:text {
{
"hello": 990531470713421825
}
}
assert {
res.status: eq 200
}
script:pre-request {
bru.setVar("foo", "foo-world-2");
}

View File

@@ -27,6 +27,7 @@
| [正體中文](docs/readme/readme_zhtw.md)
| [العربية](docs/readme/readme_ar.md)
| [日本語](docs/readme/readme_ja.md)
| [ქართული](docs/readme/readme_ka.md)
Bruno is a new and innovative API client, aimed at revolutionizing the status quo represented by Postman and similar tools out there.