diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 93e03cd9..c7cad53c 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest defaults: run: - working-directory: packages/oc-docs + working-directory: packages/bruno-api-docs steps: - uses: actions/checkout@v4 @@ -31,5 +31,5 @@ jobs: if: ${{ !cancelled() }} with: name: playwright-report - path: packages/oc-docs/playwright-report/ + path: packages/bruno-api-docs/playwright-report/ retention-days: 30 diff --git a/README.md b/README.md index eab9a439..3df1e75f 100644 --- a/README.md +++ b/README.md @@ -1,128 +1,25 @@ -# OpenCollection +# bruno-api-docs -An open specification for describing **executable API collections**: requests, environments, variables, authentication, scripts, and assertions, stored as plain YAML. +`@opencollection/docs` — an interactive API documentation site and request playground for the [OpenCollection](https://www.opencollection.com) format. -## What is OpenCollection? +Point it at an OpenCollection and it renders a browsable docs site: a sidebar of requests, per-request documentation (params, headers, body, auth, scripts, assertions), and a live playground that sends the request and shows the response. -OpenCollection is a format for describing API collections in a way that tools can read, write, and run. A collection is a tree of HTTP, GraphQL, gRPC, and WebSocket requests, together with the environments, variables, auth, scripts, and assertions needed to actually send them. - -Most API formats describe a contract. OpenAPI tells you an endpoint exists, what it accepts, and what it returns. OpenCollection captures the next step: the concrete request, with these headers, this body, this environment, this token, and these assertions on the response. A collection is something you run, not just something you read. - -The format is plain YAML with a published JSON Schema. It is an open specification: published, openly licensed, and not tied to any single application or proprietary format. - -## Why it exists - -| Layer | Format | Answers | -|---|---|---| -| Contract | OpenAPI | What does this API look like? | -| Orchestration | Arazzo | How do I chain calls across APIs? | -| **Execution** | **OpenCollection** | **Send this request, with these variables, and check this result.** | - -OpenAPI has no concept of "send this request now, with these variables, and assert this response." That executable working set is what teams keep in their API client, and until now it has lived in proprietary, tool-locked formats. OpenCollection is that artifact in an open, neutral YAML format. - -## The specification - -The current version is **1.0.0**. The schema is authored in [JSON Schema (draft-07)](http://json-schema.org/draft-07/schema#). - -- Read the human-readable spec at [spec.opencollection.com](https://spec.opencollection.com). -- Browse the schema interactively at [schema.opencollection.com](https://schema.opencollection.com). -- Read the schema source at [`packages/oc-schema/src/opencollection.schema.json`](./packages/oc-schema/src/opencollection.schema.json). - -## Example - -```yaml -opencollection: "1.0.0" -info: - name: Sample API - version: "1.0.0" -items: - - info: - name: Get Users - type: http - http: - method: GET - url: https://api.example.com/users - params: - - name: limit - value: "10" - type: query -``` - -A collection can be a single bundled file or a tree of files and folders on disk. - -## Adoption - -[Bruno](https://www.usebruno.com), the open-source, git-native API client used by tens of thousands of teams, reads and writes OpenCollection as a native storage format. Bruno can generate documentation from a collection and import from and export to other formats through the same schema. - -## Repository layout - -This repository is an npm-workspaces monorepo. - -### Published packages - -| Package | Description | -|---|---| -| [`@opencollection/schema`](./packages/oc-schema) | The JSON Schema definitions for the OpenCollection format. | -| [`@opencollection/types`](./packages/oc-types) | TypeScript types for the OpenCollection schema. | -| [`@opencollection/converters`](./packages/oc-converters) | Converters from other collection formats into OpenCollection. | - -### Sites in this repository - -| Directory | Description | -|---|---| -| [`packages/oc-spec-site`](./packages/oc-spec-site) | The human-readable specification site (spec.opencollection.com). | -| [`packages/oc-schema-explorer`](./packages/oc-schema-explorer) | The interactive schema explorer (schema.opencollection.com). | - -## Using OpenCollection in your tools - -OpenCollection is meant to be consumed by any tool. The packages below let you read, validate, and manipulate collections through openly-licensed libraries with no dependency on a particular application. - -### Validate a collection - -For a tool that ingests OpenCollection files (a CI check, an editor integration, a registry that validates on publish), the schema is published so you can validate against it directly: +## Install ```bash -npm install @opencollection/schema ajv -``` - -```js -import Ajv from 'ajv'; -import { OpenCollectionSchema } from '@opencollection/schema'; - -const ajv = new Ajv({ allErrors: true }); -const validate = ajv.compile(OpenCollectionSchema); - -if (!validate(myCollection)) { - console.error(validate.errors); -} +npm install @opencollection/docs ``` -### Work with collections in TypeScript +## Usage -For type-safe access to collection objects in a TypeScript project: - -```bash -npm install --save-dev @opencollection/types -``` - -### Migrate existing collections - -To convert collections from another format into OpenCollection: - -```bash -npm install @opencollection/converters -``` - -```js -import { brunoToOpenCollection } from '@opencollection/converters'; - -const collection = brunoToOpenCollection(brunoCollection); -``` +It ships three ways: -## Project and maintenance +- **React component** — import `OpenCollection` and pass it a collection. +- **Standalone bundle** — a self-contained JS/CSS build (`dist-standalone/`) for dropping into any page, served from the CDN. +- **Express / server entry** — render the docs from a Node server. -OpenCollection is currently authored and maintained by [Bruno](https://www.usebruno.com). The specification, schema, and tooling are developed in the open, and contributions are welcome. +See [`examples/`](./examples) for a working setup of each (`react`, `standalone-html`, `express-server`). -## Contributing +## Development -See [contributing.md](./contributing.md) to build the packages locally. Issues and pull requests are tracked on [GitHub](https://github.com/opencollection-dev/opencollection). +Work happens in `packages/bruno-api-docs`. See [contributing.md](./contributing.md) for setup, dev/test/build commands, and the PR flow. diff --git a/contributing.md b/contributing.md index 0b0230cd..595b6352 100644 --- a/contributing.md +++ b/contributing.md @@ -1,8 +1,6 @@ -# Contributing to OpenCollection +# Contributing to bruno-api-docs -Thanks for your interest in OpenCollection. This guide covers how to set up the repository, work on the packages, and propose changes. - -For an overview of what OpenCollection is and how the repository is organized, see the [README](./README.md). +Thanks for your interest. This repo holds `@opencollection/docs`, the interactive API documentation site and request playground for the [OpenCollection](https://www.opencollection.com) format. ## Prerequisites @@ -11,79 +9,33 @@ For an overview of what OpenCollection is and how the repository is organized, s ## Setup -This repository is an npm-workspaces monorepo. Install all packages from the root: - ```bash -git clone https://github.com/opencollection-dev/opencollection.git -cd opencollection +git clone https://github.com/usebruno/bruno-api-docs.git +cd bruno-api-docs npm install ``` -A single install at the root wires up every workspace. - -## Working on the packages - -Run a workspace script with `npm run + + diff --git a/examples/standalone-html/index2.html b/examples/standalone-html/index2.html index 8c7d36da..f498e6ec 100644 --- a/examples/standalone-html/index2.html +++ b/examples/standalone-html/index2.html @@ -14,8 +14,8 @@ height: 100vh; } - - + + diff --git a/main.json b/main.json deleted file mode 100644 index 31efaa74..00000000 --- a/main.json +++ /dev/null @@ -1,4476 +0,0 @@ -{ - "name": "bruno-testbench", - "version": "1", - "items": [ - { - "type": "http", - "name": "ping", - "filename": "ping.bru", - "seq": 1, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "bru.runner.stopExecution();" - }, - "vars": {}, - "assertions": [], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "folder", - "name": "graphql", - "filename": "graphql", - "items": [ - { - "type": "graphql", - "name": "spacex", - "filename": "spacex.bru", - "seq": 1, - "request": { - "url": "https://spacex-production.up.railway.app/", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "graphql", - "graphql": { - "query": "{\n company {\n ceo\n }\n}\n" - }, - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "cgAc6fGnMoVZmVUmttac9" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - }, - { - "type": "folder", - "name": "echo", - "filename": "echo", - "items": [ - { - "type": "http", - "name": "echo bom json", - "filename": "echo bom json.bru", - "seq": 1, - "request": { - "url": "{{host}}/api/echo/bom-json-test", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "echo form-url-encoded", - "filename": "echo form-url-encoded.bru", - "seq": 9, - "request": { - "url": "{{echo-host}}", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "formUrlEncoded", - "formUrlEncoded": [ - { - "name": "form-data-key", - "value": "{{form-data-key}}", - "enabled": true - }, - { - "name": "form-data-stringified-object", - "value": "{{form-data-stringified-object}}", - "enabled": true - } - ], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "let obj = JSON.stringify({foo:123});\nbru.setVar('form-data-key', 'form-data-value');\nbru.setVar('form-data-stringified-object', obj);" - }, - "vars": {}, - "assertions": [ - { - "name": "res.body", - "value": "eq form-data-key=form-data-value&form-data-stringified-object=%7B%22foo%22%3A123%7D", - "enabled": true, - "uid": "GXP3iOow05yWkFbazZh97" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "echo json", - "filename": "echo json.bru", - "seq": 2, - "request": { - "url": "{{host}}/api/echo/json", - "method": "POST", - "headers": [ - { - "name": "foo", - "value": "bar", - "enabled": true - } - ], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"hello\": \"bruno\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "bru.setVar(\"foo\", \"foo-world-2\");" - }, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "NtmLz1fS7Ms6eQ6ZrDRN0" - } - ], - "tests": "test(\"should return json\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"hello\": \"bruno\"\n });\n}); ", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "echo multipart via scripting", - "filename": "echo multipart scripting.bru", - "seq": 10, - "request": { - "url": "{{echo-host}}", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "multipartForm", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "const FormData = require(\"form-data\");\nconst form = new FormData();\nform.append('form-data-key', 'form-data-value');\nreq.setBody(form);" - }, - "vars": {}, - "assertions": [ - { - "name": "res.body", - "value": "contains form-data-value", - "enabled": true, - "uid": "6jqCWTqQtH6GSgpFNU3ep" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "echo multipart", - "filename": "echo multipart.bru", - "seq": 8, - "request": { - "url": "{{echo-host}}", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "multipartForm", - "formUrlEncoded": [], - "multipartForm": [ - { - "type": "text", - "name": "foo", - "value": "{\"bar\":\"baz\"}", - "enabled": true - }, - { - "type": "text", - "name": "form-data-key", - "value": "{{form-data-key}}", - "enabled": true - }, - { - "type": "text", - "name": "form-data-stringified-object", - "value": "{{form-data-stringified-object}}", - "enabled": true - }, - { - "type": "file", - "name": "file", - "value": [ - "bruno.png" - ], - "enabled": true - } - ], - "file": [] - }, - "script": { - "req": "let obj = JSON.stringify({foo:123});\nbru.setVar('form-data-key', 'form-data-value');\nbru.setVar('form-data-stringified-object', obj);" - }, - "vars": {}, - "assertions": [ - { - "name": "res.body", - "value": "contains form-data-value", - "enabled": true, - "uid": "mvYX54Lmd3i79iB48LEyz" - }, - { - "name": "res.body", - "value": "contains {\"foo\":123}", - "enabled": true, - "uid": "CAEG8PjR6KPYsIbxz1N0f" - }, - { - "name": "res.body", - "value": "contains Content-Type: application/json--test", - "enabled": true, - "uid": "aZHXzHRJMkWaVqA0kFLJV" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "echo numbers", - "filename": "echo numbers.bru", - "seq": 1, - "request": { - "url": "{{echo-host}}", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"integer\": 123,\n \"negativeInteger\": -99,\n \"zero\": 0,\n \"float\": 2.718,\n \"negativeFloat\": -1.618,\n \"largeDouble\": 12345.678901234567,\n \"smallDouble\": 9.876e-12,\n \"booleanTrue\": true,\n \"booleanFalse\": false\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body.integer", - "value": "eq 123", - "enabled": true, - "uid": "ZtVS9gUgc5iSmDq0gNIaT" - }, - { - "name": "res.body.integer", - "value": "isNumber", - "enabled": true, - "uid": "fqLAWWm8pqG2YacqLa58R" - }, - { - "name": "res.body.negativeInteger", - "value": "eq -99", - "enabled": true, - "uid": "ULU5rgNpJBc4t1OspKAIi" - }, - { - "name": "res.body.negativeInteger", - "value": "isNumber", - "enabled": true, - "uid": "gpZjNNkPr2AXn6GzkhkN8" - }, - { - "name": "res.body.zero", - "value": "eq 0", - "enabled": true, - "uid": "D2pXZJB9aTOAwqwXmTVEB" - }, - { - "name": "res.body.zero", - "value": "isNumber", - "enabled": true, - "uid": "TE6Q5jhRkjg0Rsp0zNLl7" - }, - { - "name": "res.body.float", - "value": "eq 2.718", - "enabled": true, - "uid": "izHjCWoESD3JaoDgQBwa0" - }, - { - "name": "res.body.float", - "value": "isNumber", - "enabled": true, - "uid": "MRZ9PsV8AogLzvgUolu68" - }, - { - "name": "res.body.negativeFloat", - "value": "eq -1.618", - "enabled": true, - "uid": "fzzJP0kj71WFqZ0DDMeIo" - }, - { - "name": "res.body.negativeFloat", - "value": "isNumber", - "enabled": true, - "uid": "cm2c5v40ilCZsraGiR564" - }, - { - "name": "res.body.largeDouble", - "value": "eq 12345.678901234567", - "enabled": true, - "uid": "6gnCn1c8TSHigYy1taFhN" - }, - { - "name": "res.body.largeDouble", - "value": "isNumber", - "enabled": true, - "uid": "qEHQ1qRt6HyCzMqhUrdIT" - }, - { - "name": "res.body.smallDouble", - "value": "eq 9.876e-12", - "enabled": true, - "uid": "ZKrwMPCjBEGqZ4yb1KxoG" - }, - { - "name": "res.body.smallDouble", - "value": "isNumber", - "enabled": true, - "uid": "xRWLvDJJZSzmpz5vubw8p" - }, - { - "name": "res.body.booleanTrue", - "value": "eq true", - "enabled": true, - "uid": "FENKG4gsPZtHyYYBLNKie" - }, - { - "name": "res.body.booleanFalse", - "value": "eq false", - "enabled": true, - "uid": "6SoMig8CeBBIW590VwX5K" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "echo plaintext", - "filename": "echo plaintext.bru", - "seq": 3, - "request": { - "url": "{{host}}/api/echo/text", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "text", - "text": "hello", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "uWsY31SAmtyc2JIpTxqzO" - } - ], - "tests": "test(\"should return plain text\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql(\"hello\");\n});\n", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "echo xml parsed(self closing tags)", - "filename": "echo xml parsed(self closing tags).bru", - "seq": 6, - "request": { - "url": "{{host}}/api/echo/xml-parsed", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "xml", - "xml": "\n bruno\n \n", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "F4K7K3z239O2WvhcYc8cu" - } - ], - "tests": "test(\"should return parsed xml\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"hello\": {\n \"world\": [\n \"bruno\",\n \"\"\n ]\n }\n });\n});\n", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "echo xml parsed", - "filename": "echo xml parsed.bru", - "seq": 4, - "request": { - "url": "{{host}}/api/echo/xml-parsed", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "xml", - "xml": "\n bruno\n", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "4OxoP1d1Sn7J0Rr5A5MoR" - } - ], - "tests": "test(\"should return parsed xml\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"hello\": {\n \"world\": [\"bruno\"]\n }\n });\n});\n", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "echo xml raw", - "filename": "echo xml raw.bru", - "seq": 5, - "request": { - "url": "{{host}}/api/echo/xml-raw", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "xml", - "xml": "bruno", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "test echo any", - "filename": "test echo any.bru", - "seq": 11, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"headers\": { \"content-type\": \"text/plain\" },\n \"content\": \"hello\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body", - "value": "eq hello", - "enabled": true, - "uid": "7Plt7ZGJQhoOFXFKnTQce" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "test echo-any json", - "filename": "test echo-any json.bru", - "seq": 12, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"type\": \"application/json\",\n \"contentJSON\": {\"x\": 42}\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body.x", - "value": "eq 42", - "enabled": true, - "uid": "wU1YDNe5ZYZLi1noaCsHK" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "folder", - "name": "multiline", - "filename": "multiline", - "items": [ - { - "type": "http", - "name": "echo binary", - "filename": "echo binary.bru", - "seq": 1, - "request": { - "url": "{{echo-host}}", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "file", - "formUrlEncoded": [], - "multipartForm": [], - "file": [ - { - "filePath": "bruno.png", - "contentType": "image/png", - "selected": true - } - ] - }, - "script": {}, - "vars": {}, - "assertions": [], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - } - ] - }, - { - "type": "folder", - "name": "auth", - "filename": "auth", - "items": [ - { - "type": "folder", - "name": "inherit auth", - "filename": "inherit auth", - "items": [ - { - "type": "http", - "name": "inherit Bearer Auth 200", - "filename": "inherit Bearer Auth 200.bru", - "seq": 2, - "request": { - "url": "{{host}}/api/auth/bearer/protected", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "res": "bru.setEnvVar(\"foo\", \"bar\");" - }, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "200", - "enabled": true, - "uid": "60I5u9Am5kDPd7juwvKV5" - }, - { - "name": "res.body.message", - "value": "Authentication successful", - "enabled": true, - "uid": "fkQViSlIxJJ0RyhCN5tp3" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "inherit" - } - } - } - ] - }, - { - "type": "folder", - "name": "basic", - "filename": "basic", - "items": [ - { - "type": "folder", - "name": "via auth", - "filename": "via auth", - "items": [ - { - "type": "http", - "name": "Basic Auth 200", - "filename": "Basic Auth 200.bru", - "seq": 1, - "request": { - "url": "{{host}}/api/auth/basic/protected", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "200", - "enabled": true, - "uid": "d5CVuD1HpRVtyUWziE6Y7" - }, - { - "name": "res.body.message", - "value": "Authentication successful", - "enabled": true, - "uid": "kSZPZekosG0Uci7SE8Hju" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "basic", - "basic": { - "username": "bruno", - "password": "{{basic_auth_password}}" - } - } - } - }, - { - "type": "http", - "name": "Basic Auth 400", - "filename": "Basic Auth 401.bru", - "seq": 2, - "request": { - "url": "{{host}}/api/auth/basic/protected", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "401", - "enabled": true, - "uid": "xnlyXClGdlx7gGLwzaniZ" - }, - { - "name": "res.body", - "value": "Unauthorized", - "enabled": true, - "uid": "20H5jGbawcioeVKPLMsHn" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - }, - { - "type": "folder", - "name": "via script", - "filename": "via script", - "items": [ - { - "type": "http", - "name": "Basic Auth 401", - "filename": "Basic Auth 401.bru", - "seq": 2, - "request": { - "url": "{{host}}/api/auth/basic/protected", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "const username = \"bruno\";\nconst password = \"invalid\";\n\nconst authString = `${username}:${password}`;\nconst encodedAuthString = require('btoa')(authString);\n\nreq.setHeader(\"Authorization\", `Basic ${encodedAuthString}`);" - }, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "401", - "enabled": true, - "uid": "96LEDffmtAmfKTsfemJaB" - }, - { - "name": "res.body", - "value": "Unauthorized", - "enabled": true, - "uid": "7B66oHgquEiW39PCRcf5A" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "Basic Auth 200", - "filename": "Basic Auth 200.bru", - "seq": 1, - "request": { - "url": "{{host}}/api/auth/basic/protected", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "const username = \"bruno\";\nconst password = \"della\";\n\nconst authString = `${username}:${password}`;\nconst encodedAuthString = require('btoa')(authString);\n\nreq.setHeader(\"Authorization\", `Basic ${encodedAuthString}`);" - }, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "C7EXFxZSx9MTjrPvbZK9h" - }, - { - "name": "res.body.message", - "value": "Authentication successful", - "enabled": true, - "uid": "zXFBjrNaXojNhRdJVJ86w" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - } - ] - }, - { - "type": "folder", - "name": "cookie", - "filename": "cookie", - "items": [ - { - "type": "http", - "name": "Check", - "filename": "Check.bru", - "seq": 2, - "request": { - "url": "{{host}}/api/auth/cookie/protected", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "Login", - "filename": "Login.bru", - "seq": 1, - "request": { - "url": "{{host}}/api/auth/cookie/login", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - }, - { - "type": "folder", - "name": "bearer", - "filename": "bearer", - "items": [ - { - "type": "folder", - "name": "via headers", - "filename": "via headers", - "items": [ - { - "type": "http", - "name": "Bearer Auth 200", - "filename": "Bearer Auth 200.bru", - "seq": 1, - "request": { - "url": "{{host}}/api/auth/bearer/protected", - "method": "GET", - "headers": [ - { - "name": "Authorization", - "value": "Bearer your_secret_token", - "enabled": true - } - ], - "params": [], - "body": { - "mode": "json", - "json": "", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "res": "bru.setEnvVar(\"foo\", \"bar\");" - }, - "vars": { - "req": [ - { - "name": "a-c", - "value": "foo", - "enabled": true, - "local": false - } - ] - }, - "assertions": [ - { - "name": "res.status", - "value": "200", - "enabled": true, - "uid": "uV4xNx780Qk3ff8zj0xVX" - }, - { - "name": "res.body.message", - "value": "Authentication successful", - "enabled": true, - "uid": "0t9sjKI6l5tFRfLYcFLXv" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - }, - { - "type": "folder", - "name": "via auth", - "filename": "via auth", - "items": [ - { - "type": "http", - "name": "Bearer Auth 200", - "filename": "Bearer Auth 200.bru", - "seq": 1, - "request": { - "url": "{{host}}/api/auth/bearer/protected", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "res": "bru.setEnvVar(\"foo\", \"bar\");" - }, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "200", - "enabled": true, - "uid": "nD6fKpZaZcqky2EMS3hhQ" - }, - { - "name": "res.body.message", - "value": "Authentication successful", - "enabled": true, - "uid": "HRp5kskhIHPPXXDesRKj0" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "bearer", - "bearer": { - "token": "{{bearer_auth_token}}" - } - } - } - } - ] - } - ] - } - ] - }, - { - "type": "folder", - "name": "multipart", - "filename": "multipart" - }, - { - "type": "folder", - "name": "lib", - "filename": "lib", - "items": [ - { - "type": "js", - "name": "constants", - "filename": "constants.js", - "seq": 1, - "fileContent": "const PI = 3.14;\n\nmodule.exports = {\n PI\n};" - }, - { - "type": "js", - "name": "math", - "filename": "math.js", - "seq": 1, - "fileContent": "const { PI } = require('./constants');\n\nconst sum = (a, b) => a + b;\nconst areaOfCircle = (radius) => PI * radius * radius;\n\nmodule.exports = {\n sum,\n areaOfCircle\n};\n" - }, - { - "type": "js", - "name": "notes", - "filename": "notes.js", - "seq": 1, - "fileContent": "const visualizeNotes = (res) => {\n let response = res.body;\n\n let notes = response?.notes || {};\n let responseRuntime = notes.runtime_sec || 0;\n\n notes.runtime = new Date(responseRuntime * 1000).toISOString().substr(11, 8);\n\n if (typeof response?.data === 'undefined' && typeof response?.rows === 'object') {\n response.data = response?.rows?.map(function (data) {\n return data?.values;\n });\n }\n\n const templateScript = `\n \n `;\n\n const mainScript = `\n \n `;\n\n const style = `\n \n `;\n\n const htmlString = `\n \n \n ${style}\n \n \n \n ${templateScript}\n ${mainScript}\n \n \n `;\n\n return htmlString;\n};\n\nmodule.exports = visualizeNotes;\n" - } - ] - }, - { - "type": "folder", - "name": "string interpolation", - "filename": "string interpolation", - "root": { - "request": { - "vars": { - "req": [ - { - "name": "folder_pre_var", - "value": "folder_pre_var_value", - "enabled": true, - "local": false, - "uid": "V3bTRQFGwkKI4UoahPd2V" - }, - { - "name": "folder_pre_var_2", - "value": "{{env.var1}}", - "enabled": true, - "local": false, - "uid": "av2XViQpOS4JZDWur8dK2" - } - ] - } - }, - "meta": { - "name": "string interpolation" - } - }, - "items": [ - { - "type": "http", - "name": "env vars", - "filename": "env vars.bru", - "seq": 2, - "request": { - "url": "{{host}}/api/echo/json", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"envVar1\": \"{{env.var1}}\",\n \"envVar2\": \"{{env-var2}}\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "u2yA2zeeglSqFZxTDHEiZ" - } - ], - "tests": "test(\"should return json\", function() {\n expect(res.getBody()).to.eql({\n \"envVar1\": \"envVar1\",\n \"envVar2\": \"envVar2\"\n });\n});\n", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "missing values", - "filename": "missing values.bru", - "seq": 1, - "request": { - "url": "{{host}}/api/echo/json?foo={{undefinedVar}}", - "method": "POST", - "headers": [], - "params": [ - { - "name": "foo", - "value": "{{undefinedVar}}", - "type": "query", - "enabled": true - } - ], - "body": { - "mode": "json", - "json": "{\n \"hello\": \"{{undefinedVar2}}\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "BwlJRndmkVnlQgCdpdNoE" - } - ], - "tests": "test(\"should return json\", function() {\n const url = req.getUrl();\n const query = url.split(\"?\")[1];\n expect(query).to.equal(\"foo={{undefinedVar}}\");\n\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"hello\": \"{{undefinedVar2}}\"\n });\n});\n", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "process env vars", - "filename": "process env vars.bru", - "seq": 4, - "request": { - "url": "{{host}}/api/echo/json", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"bark\": \"{{bark}}\",\n \"bark2\": \"{{process.env.PROC_ENV_VAR}}\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "VDoqOFucl5B4UdBGqGCAl" - } - ], - "tests": "test(\"should return json\", function() {\n expect(res.getBody()).to.eql({\n \"bark\": \"woof\",\n \"bark2\": \"woof\"\n });\n});\n", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "runtime vars", - "filename": "runtime vars.bru", - "seq": 3, - "request": { - "url": "{{host}}/api/echo/text", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "text", - "json": "{\n \"envVar1\": \"{{env.var1}}\",\n \"envVar2\": \"{{env-var2}}\"\n}", - "text": "Hi, I am {{rUser.full_name}},\nI am {{rUser.age}} years old.\nMy favorite food is {{rUser.fav-food[0]}} and {{rUser.fav-food[1]}}.\nI like attention: {{rUser.want.attention}}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "bru.setVar(\"rUser\", {\n full_name: 'Bruno',\n age: 5,\n 'fav-food': ['egg', 'meat'],\n 'want.attention': true\n});" - }, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "EodEloyMBhRCH8mPoLR8E" - } - ], - "tests": "test(\"should return json\", function() {\n const expectedResponse = `Hi, I am Bruno,\nI am 5 years old.\nMy favorite food is egg and meat.\nI like attention: true`;\n expect(res.getBody()).to.equal(expectedResponse);\n});\n", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - }, - { - "type": "folder", - "name": "redirects", - "filename": "redirects", - "items": [ - { - "type": "http", - "name": "Disable Redirect", - "filename": "Disable Redirect.bru", - "seq": 1, - "request": { - "url": "{{host}}/redirect-to-ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "req.setMaxRedirects(0);" - }, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "302", - "enabled": true, - "uid": "Kqu9TpenOeiPke7gM6e2W" - } - ], - "tests": "test(\"should disable redirect to ping\", function() {\n const data = res.getBody();\n expect(data).to.equal('Found. Redirecting to /ping');\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "Test Redirect", - "filename": "Test Redirect.bru", - "seq": 2, - "request": { - "url": "{{host}}/redirect-to-ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "200", - "enabled": true, - "uid": "IDIABjMsPFmyysPy3DDLG" - }, - { - "name": "res.body", - "value": "pong", - "enabled": true, - "uid": "d74g0aRt3Mlk1yaTa2BD1" - } - ], - "tests": "test(\"should redirect to ping\", function() {\n const data = res.getBody();\n expect(data).to.equal('pong');\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - }, - { - "type": "folder", - "name": "asserts", - "filename": "asserts", - "items": [ - { - "type": "http", - "name": "test-assert-combinations", - "filename": "test-assert-combinations.bru", - "seq": 1, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"type\": \"application/json\",\n \"contentJSON\": {\n \"string\": \"foo\",\n \"stringWithSQuotes\": \"'foo'\",\n \"stringWithDQuotes\": \"\\\"foo\\\"\",\n \"number\": 123,\n \"numberAsString\": \"123\",\n \"numberAsStringWithSQuotes\": \"'123'\",\n \"numberAsStringWithDQuotes\": \"\\\"123\\\"\",\n \"numberAsStringWithLeadingZero\": \"0123\",\n \"numberBig\": 9007199254740992000,\n \"numberBigAsString\": \"9007199254740991999\",\n \"null\": null,\n \"nullAsString\": \"null\",\n \"nullAsStringWithSQuotes\": \"'null'\",\n \"nullAsStringWithDQuotes\": \"\\\"null\\\"\",\n \"true\": true,\n \"trueAsString\": \"true\",\n \"trueAsStringWithSQuotes\": \"'true'\",\n \"trueAsStringWithDQuotes\": \"\\\"true\\\"\",\n \"false\": false,\n \"falseAsString\": \"false\",\n \"falseAsStringWithSQuotes\": \"'false'\",\n \"falseAsStringWithDQuotes\": \"\\\"false\\\"\",\n \"stringWithCurlyBraces\": \"{foo}\",\n \"stringWithDoubleCurlyBraces\": \"{{foobar}}\"\n }\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body.string", - "value": "eq foo", - "enabled": true, - "uid": "BIAZhDa8r5jiaeUMC9oJx" - }, - { - "name": "res.body.string", - "value": "eq 'foo'", - "enabled": true, - "uid": "MmDv72YGFukil4LAZ6H1f" - }, - { - "name": "res.body.string", - "value": "eq \"foo\"", - "enabled": true, - "uid": "p0YuYI8JJhOLnQmb1OJyO" - }, - { - "name": "res.body.stringWithSQuotes", - "value": "eq \"'foo'\"", - "enabled": true, - "uid": "6vBjUYmjT6w680kXw5GN8" - }, - { - "name": "res.body.stringWithDQuotes", - "value": "eq '\"foo\"'", - "enabled": true, - "uid": "6SlJJOabN6dqU6zzBGJ5V" - }, - { - "name": "res.body.number", - "value": "eq 123", - "enabled": true, - "uid": "qsTsccOFzdaTad54qLRPD" - }, - { - "name": "res.body.numberAsString", - "value": "eq '123'", - "enabled": true, - "uid": "acr4c0DbVSMHybtmPfpAK" - }, - { - "name": "res.body.numberAsString", - "value": "eq \"123\"", - "enabled": true, - "uid": "j2UBEitg7trKqERvHFonB" - }, - { - "name": "res.body.numberAsStringWithSQuotes", - "value": "eq \"'123'\"", - "enabled": true, - "uid": "HkhFuTMDlPTtjdRH1JtDq" - }, - { - "name": "res.body.numberAsStringWithDQuotes", - "value": "eq '\"123\"'", - "enabled": true, - "uid": "FOJ9Il1Mw26AVh3mtfH2A" - }, - { - "name": "res.body.numberAsStringWithLeadingZero", - "value": "eq \"0123\"", - "enabled": true, - "uid": "PYqZgMwa8utODeQu6jGZ8" - }, - { - "name": "res.body.numberBig.toString()", - "value": "eq '9007199254740992000'", - "enabled": true, - "uid": "ceH22BYjeONOfjQzCQuQ5" - }, - { - "name": "res.body.numberBigAsString", - "value": "eq \"9007199254740991999\"", - "enabled": true, - "uid": "ISsGCwNYz2gO1OiwCrSzj" - }, - { - "name": "res.body.null", - "value": "eq null", - "enabled": true, - "uid": "ymthap5UgbSWYrA2KrhSf" - }, - { - "name": "res.body.nullAsString", - "value": "eq \"null\"", - "enabled": true, - "uid": "70dQ4jmZ3NObBuSgNms4U" - }, - { - "name": "res.body.nullAsStringWithSQuotes", - "value": "eq \"'null'\"", - "enabled": true, - "uid": "8sHCgezylhO5WobuMF6x5" - }, - { - "name": "res.body.nullAsStringWithDQuotes", - "value": "eq '\"null\"'", - "enabled": true, - "uid": "Beo0GPeJjGChOUW3ULJFq" - }, - { - "name": "res.body.true", - "value": "eq true", - "enabled": true, - "uid": "xyKYxUigaRbnsM3NUCGqo" - }, - { - "name": "res.body.trueAsString", - "value": "eq \"true\"", - "enabled": true, - "uid": "TpEuGS0KamPW2P5WlNKIz" - }, - { - "name": "res.body.trueAsStringWithSQuotes", - "value": "eq \"'true'\"", - "enabled": true, - "uid": "NGOStfvaFasU1BnDQBeNw" - }, - { - "name": "res.body.trueAsStringWithDQuotes", - "value": "eq '\"true\"'", - "enabled": true, - "uid": "1aQu1geER6NzyRyvn6YKL" - }, - { - "name": "res.body.false", - "value": "eq false", - "enabled": true, - "uid": "5hYV1aZexcmTnvWVGukhR" - }, - { - "name": "res.body.falseAsString", - "value": "eq \"false\"", - "enabled": true, - "uid": "0nlBWyhHLkqwJnnQvntpH" - }, - { - "name": "res.body.falseAsStringWithSQuotes", - "value": "eq \"'false'\"", - "enabled": true, - "uid": "6SyZkAdoR7nymmSuxEAVm" - }, - { - "name": "res.body.falseAsStringWithDQuotes", - "value": "eq '\"false\"'", - "enabled": true, - "uid": "ikW1dRvg543wlg4OBVOj4" - }, - { - "name": "res.body.nonexistent", - "value": "eq undefined", - "enabled": true, - "uid": "18cmPWFrjuhO9w3r37QbC" - }, - { - "name": "res.body.stringWithCurlyBraces", - "value": "eq \"{foo}\"", - "enabled": true, - "uid": "MG7kIGiDRpVMWFsUNJwwL" - }, - { - "name": "res.body.stringWithDoubleCurlyBraces", - "value": "eq \"{{foobar}}\"", - "enabled": true, - "uid": "lc8H3nkOK6oH9EU8pfGAB" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - }, - { - "type": "folder", - "name": "response-parsing", - "filename": "response-parsing", - "items": [ - { - "type": "http", - "name": "test JSON false response", - "filename": "test JSON false response.bru", - "seq": 11, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"headers\": { \"content-type\": \"application/json\" },\n \"content\": \"false\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body", - "value": "eq false", - "enabled": true, - "uid": "44ByglOpNCcWR39kkFqUB" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "test JSON null response", - "filename": "test JSON null response.bru", - "seq": 6, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"headers\": { \"content-type\": \"application/json\" },\n \"content\": \"null\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body", - "value": "eq null", - "enabled": true, - "uid": "SoMSHwOxrNF0mO7vjtMIq" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "test JSON number response", - "filename": "test JSON number response.bru", - "seq": 12, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"headers\": { \"content-type\": \"application/json\" },\n \"content\": \"3.1\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body", - "value": "eq 3.1", - "enabled": true, - "uid": "PXORG50VO2DQhpxTe4Z9b" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "test JSON response", - "filename": "test JSON response.bru", - "seq": 2, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"headers\": { \"content-type\": \"application/json\" },\n \"contentJSON\": { \"message\": \"hello\" }\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body.message", - "value": "eq hello", - "enabled": true, - "uid": "ghYaoqOIqNkzYySyevIbS" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "test JSON string response", - "filename": "test JSON string response.bru", - "seq": 7, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"headers\": { \"content-type\": \"application/json\" },\n \"content\": \"\\\"ok\\\"\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body", - "value": "eq ok", - "enabled": true, - "uid": "lrb7s0Cy5fSBmpsnQS2hC" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "test JSON string with quotes response", - "filename": "test JSON string with quotes response.bru", - "seq": 8, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"headers\": { \"content-type\": \"application/json\" },\n \"contentJSON\": \"\\\"ok\\\"\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body", - "value": "eq '\"ok\"'", - "enabled": true, - "uid": "0vtvad5pJzWJ82EkoP1tL" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "test JSON true response", - "filename": "test JSON true response.bru", - "seq": 10, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"headers\": { \"content-type\": \"application/json\" },\n \"content\": \"true\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body", - "value": "eq true", - "enabled": true, - "uid": "gWf2HHCyZEfJDjF9epFgh" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "test JSON unsafe-int response", - "filename": "test JSON unsafe-int response.bru", - "seq": 13, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"headers\": { \"content-type\": \"application/json\" },\n \"content\": \"90071992547409919876\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body.toString()", - "value": "eq 90071992547409920000", - "enabled": true, - "uid": "VPxENgWx5laoc8a8AbPSt" - } - ], - "tests": "", - "docs": "Note: This test is not perfect, we should match the unparsed raw-response with the expected string version of the unsafe-integer", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "test binary response", - "filename": "test binary response.bru", - "seq": 4, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"type\": \"application/octet-stream\",\n \"contentBase64\": \"+Z1P82iH1wmbILfvnhvjQVbVAktP4TzltpxYD74zNyA=\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [], - "tests": "test(\"response matches the expectation after utf-8 decoding(needs improvement)\", function () {\n expect(res.getStatus()).to.equal(200);\n const dataBinary = Buffer.from(\"+Z1P82iH1wmbILfvnhvjQVbVAktP4TzltpxYD74zNyA=\", \"base64\"); \n expect(res.body).to.equal(dataBinary.toString(\"utf-8\"));\n});", - "docs": "Note:\n\nThis test is not perfect and needs to be improved by direclty matching expected binary data with raw-response.\n\nCurrently res.body is decoded with `utf-8` by default and looses data in the process. We need some property in `res` which gives access to raw-data/Buffer.", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "test html response", - "filename": "test html response.bru", - "seq": 5, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"headers\": { \"content-type\": \"text/html\" },\n \"content\": \"

hello

\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body", - "value": "eq

hello

", - "enabled": true, - "uid": "2ljMHST9vdVDcGsDYeea5" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "test image response", - "filename": "test image response.bru", - "seq": 3, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"type\": \"image/png\",\n \"contentBase64\": \"iVBORw0KGgoAAAANSUhEUgAAAGQAAABkAQMAAABKLAcXAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAGUExURQCqAP///59OGOoAAAABYktHRAH/Ai3eAAAAB3RJTUUH6QMHCwUNKHvFmgAAABRJREFUOMtjYBgFo2AUjIJRQE8AAAV4AAEpcbn8AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDI1LTAzLTA3VDExOjA1OjEzKzAwOjAwQkgGWgAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyNS0wMy0wN1QxMTowNToxMyswMDowMDMVvuYAAAAodEVYdGRhdGU6dGltZXN0YW1wADIwMjUtMDMtMDdUMTE6MDU6MTMrMDA6MDBkAJ85AAAAAElFTkSuQmCC\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "test plain text response with formatting", - "filename": "test plain text response with formatting.bru", - "seq": 18, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"headers\": { \"content-type\": \"text/plain\" },\n \"content\": \"hello\\n\\tworld\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body", - "value": "eq hello\\n\\tworld", - "enabled": true, - "uid": "krtHsmpnhOUT4SP575BjE" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "test plain text response", - "filename": "test plain text response.bru", - "seq": 1, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"headers\": { \"content-type\": \"text/plain\" },\n \"content\": \"hello\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body", - "value": "eq hello", - "enabled": true, - "uid": "iiduau7JWqfG721cU41GX" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "test invalid JSON response with formatting", - "filename": "test invalid JSON response with formatting.bru", - "seq": 19, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"headers\": { \"content-type\": \"application/json\" },\n \"content\": \"hello\\n\\tworld\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body", - "value": "eq hello\\n\\tworld", - "enabled": true, - "uid": "2Lgh5484D4lpF5w2d0y4M" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "test plain text utf16 response", - "filename": "test plain text utf16 response.bru", - "seq": 14, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"headers\": { \"content-type\": \"text/plain; charset=utf-16\" },\n \"contentBase64\": \"dABoAGkAcwAgAGkAcwAgAGUAbgBjAG8AZABlAGQAIAB3AGkAdABoACAAdQB0AGYAMQA2AA==\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body", - "value": "eq \"this is encoded with utf16\"", - "enabled": true, - "uid": "bTudYyt3VYDJBGUQMaBrn" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "test plain text utf16-be with BOM response", - "filename": "test plain text utf16-be with BOM response.bru", - "seq": 15, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"headers\": { \"content-type\": \"text/plain; charset=utf-16\" },\n \"contentBase64\": \"/v8AdABoAGkAcwAgAGkAcwAgAGUAbgBjAG8AZABlAGQAIAB3AGkAdABoACAAdQB0AGYAMQA2AC0AYgBlACAAdwBpAHQAaAAgAEIATwBN\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body", - "value": "eq \"this is encoded with utf16-be with BOM\"", - "enabled": true, - "uid": "2y4vvfKmEIiPbazx9WcI7" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "test plain text utf16-le with BOM response", - "filename": "test plain text utf16-le with BOM response.bru", - "seq": 16, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"headers\": { \"content-type\": \"text/plain; charset=utf-16\" },\n \"contentBase64\": \"//50AGgAaQBzACAAaQBzACAAZQBuAGMAbwBkAGUAZAAgAHcAaQB0AGgAIAB1AHQAZgAxADYALQBsAGUAIAB3AGkAdABoACAAQgBPAE0A\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body", - "value": "eq \"this is encoded with utf16-le with BOM\"", - "enabled": true, - "uid": "DoCOfg20CxCaNv59xBeMK" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "test plain text utf8 with BOM response", - "filename": "test plain text utf8 with BOM response.bru", - "seq": 17, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"headers\": { \"content-type\": \"text/plain; charset=utf8\" },\n \"contentBase64\": \"77u/dGhpcyBpcyB1dGY4IGVuY29kZWQgd2l0aCBCT00sIHdoeSBub3Q/\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body", - "value": "eq \"this is utf8 encoded with BOM, why not?\"", - "enabled": true, - "uid": "W2wEieY0CyJnZPTS7QFdi" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "test xml response", - "filename": "test xml response.bru", - "seq": 9, - "request": { - "url": "{{httpfaker}}/api/echo/custom", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"headers\": { \"content-type\": \"application/xml\" },\n \"content\": \"hello\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.body", - "value": "eq hello", - "enabled": true, - "uid": "LpkeJWArhseIjWVvrRSsY" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - }, - { - "type": "folder", - "name": "preview", - "filename": "preview", - "items": [ - { - "type": "folder", - "name": "html", - "filename": "html", - "items": [ - { - "type": "http", - "name": "bruno", - "filename": "bruno.bru", - "seq": 1, - "request": { - "url": "https://www.usebruno.com", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "Lq3jQdo5w6Sj5DmK7RR4e" - } - ], - "tests": "test(\"should return parsed xml\", function() {\n const headers = res.getHeaders();\n expect(headers['content-type']).to.eql(\"text/html; charset=utf-8\");\n});\n", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - }, - { - "type": "folder", - "name": "image", - "filename": "image", - "items": [ - { - "type": "http", - "name": "bruno", - "filename": "bruno.bru", - "seq": 1, - "request": { - "url": "https://www.usebruno.com/favicon.ico", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [], - "tests": "test(\"should return parsed xml\", function() {\n const headers = res.getHeaders();\n expect(headers['content-type']).to.eql(\"image/x-icon\");\n});\n", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - } - ] - }, - { - "type": "folder", - "name": "scripting", - "filename": "scripting", - "items": [ - { - "type": "folder", - "name": "js", - "filename": "js", - "root": { - "request": { - "headers": [ - { - "name": "folder-header", - "value": "folder-header-value", - "enabled": true, - "uid": "IbjpKtt6OSIEfbEpq63i5" - } - ], - "script": { - "req": "// used by `scripting/js/folder-collection script-tests`\nconst shouldTestFolderScripts = bru.getVar('should-test-folder-scripts');\nif(shouldTestFolderScripts) {\n bru.setVar('folder-var-set-by-folder-script', 'folder-var-value-set-by-folder-script');\n}" - }, - "tests": "// used by `scripting/js/folder-collection script-tests`\nconst shouldTestFolderScripts = bru.getVar('should-test-folder-scripts');\nconst folderVar = bru.getVar(\"folder-var-set-by-folder-script\");\nif (shouldTestFolderScripts && folderVar) {\n test(\"folder level test - should get the var that was set by the folder script\", function() {\n expect(folderVar).to.equal(\"folder-var-value-set-by-folder-script\");\n }); \n bru.setVar('folder-var-set-by-folder-script', null); \n bru.setVar('should-test-folder-scripts', null);\n}" - }, - "meta": { - "name": "js" - } - }, - "items": [ - { - "type": "http", - "name": "data types - request vars", - "filename": "data types - request vars.bru", - "seq": 3, - "request": { - "url": "{{host}}/api/echo/json", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"boolean\": false,\n \"number_1\": 1,\n \"number_2\": 0,\n \"number_3\": -1,\n \"string\": \"bruno\",\n \"array\": [1, 2, 3, 4, 5],\n \"object\": {\n \"hello\": \"bruno\"\n },\n \"null\": null\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "req.body.boolean", - "value": "isBoolean false", - "enabled": true, - "uid": "zEDwisxV9J5rpkVFsogOa" - }, - { - "name": "req.body.number_1", - "value": "isNumber 1", - "enabled": true, - "uid": "dl2kC9vNfZZstXR4T7m82" - }, - { - "name": "req.body.undefined", - "value": "isUndefined undefined", - "enabled": true, - "uid": "IgJsHATg2BunQdduIPWj7" - }, - { - "name": "req.body.string", - "value": "isString bruno", - "enabled": true, - "uid": "ZkjsCtU9U3CXoUXQR22wr" - }, - { - "name": "req.body.null", - "value": "isNull null", - "enabled": true, - "uid": "QK3P1uBuD9DwmMgQfeEIU" - }, - { - "name": "req.body.array", - "value": "isArray", - "enabled": true, - "uid": "SS4pel9Lxy2zXJplAwdGl" - }, - { - "name": "req.body.boolean", - "value": "eq false", - "enabled": true, - "uid": "bgDu625CBaYhGfZdDUPW0" - }, - { - "name": "req.body.number_1", - "value": "eq 1", - "enabled": true, - "uid": "H0iOZFFLufmyelF7JT66C" - }, - { - "name": "req.body.undefined", - "value": "eq undefined", - "enabled": true, - "uid": "NH5NrTa3rDBUovinP39vc" - }, - { - "name": "req.body.string", - "value": "eq bruno", - "enabled": true, - "uid": "BWf3Y60ywGiLMP3BdtjF8" - }, - { - "name": "req.body.null", - "value": "eq null", - "enabled": true, - "uid": "mz2qdTyufiVSGmDAsdDJD" - }, - { - "name": "req.body.number_2", - "value": "eq 0", - "enabled": true, - "uid": "Fj8Je4fBjHQaBn9MlcyRY" - }, - { - "name": "req.body.number_3", - "value": "eq -1", - "enabled": true, - "uid": "8nH1gowUVSlPE5B7zXjIu" - }, - { - "name": "req.body.number_2", - "value": "isNumber", - "enabled": true, - "uid": "bZXbYyYOrxtfq3rcK4T0R" - }, - { - "name": "req.body.number_3", - "value": "isNumber", - "enabled": true, - "uid": "WUpdAAGdYgyumiueofKzX" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "data types", - "filename": "data types.bru", - "seq": 2, - "request": { - "url": "{{host}}/api/echo/json", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"boolean\": false,\n \"number\": 1,\n \"string\": \"bruno\",\n \"array\": [1, 2, 3, 4, 5],\n \"object\": {\n \"hello\": \"bruno\"\n },\n \"null\": null\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "const reqBody = req.getBody();\n\nbru.setVar(\"dataTypeVarTest\", {\n ...reqBody,\n \"undefined\": undefined\n});" - }, - "vars": {}, - "assertions": [], - "tests": "test(\"data types check via bru var\", function() {\n let v = bru.getVar(\"dataTypeVarTest\");\n v = {\n ...v,\n \"undefined\": undefined\n };\n expect(v).to.eql({\n \"boolean\": false,\n \"number\": 1,\n \"string\": \"bruno\",\n \"array\": [1, 2, 3, 4, 5],\n \"object\": {\n \"hello\": \"bruno\"\n },\n \"null\": null,\n \"undefined\": undefined\n })\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "folder-collection script-tests pre", - "filename": "folder-collection script-tests pre.bru", - "seq": 4, - "request": { - "url": "{{echo-host}}", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "bru.setVar('should-test-collection-scripts', true);\nbru.setVar('should-test-folder-scripts', true);" - }, - "vars": {}, - "assertions": [], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "folder-collection script-tests", - "filename": "folder-collection script-tests.bru", - "seq": 5, - "request": { - "url": "{{echo-host}}", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "// do not delete - the collection/folder scripts/tests run during this request execution" - }, - "vars": {}, - "assertions": [], - "tests": "const collectionHeader = req.getHeader(\"collection-header\");\nconst folderHeader = req.getHeader(\"folder-header\");\n\ntest(\"should get the header value set at collection level\", function() {\n expect(collectionHeader).to.equal(\"collection-header-value\");\n});\n\ntest(\"should get the header value set at folder level\", function() {\n expect(folderHeader).to.equal(\"folder-header-value\");\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "setTimeout", - "filename": "setTimeout.bru", - "seq": 1, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "bru.setVar(\"test-js-set-timeout\", \"\");\nawait new Promise((resolve, reject) => {\n setTimeout(() => {\n bru.setVar(\"test-js-set-timeout\", \"bruno\");\n resolve();\n }, 1000);\n});\n\nconst v = bru.getVar(\"test-js-set-timeout\");\nbru.setVar(\"test-js-set-timeout\", v + \"-is-awesome\");\n" - }, - "vars": {}, - "assertions": [], - "tests": "test(\"setTimeout()\", function() {\n const v = bru.getVar(\"test-js-set-timeout\")\n expect(v).to.eql(\"bruno-is-awesome\");\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - }, - { - "type": "folder", - "name": "npm modules", - "filename": "npm modules", - "items": [ - { - "type": "http", - "name": "fakerjs", - "filename": "fakerjs.bru", - "seq": 1, - "request": { - "url": "{{host}}/api/echo/json", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"hello\": \"bruno\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "const { faker } = require('@faker-js/faker');\nconst uuid = faker.string.uuid();\n\nconst data = req.getBody();\ndata.uuid = uuid;\n\nreq.setBody(data);" - }, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "lD0O3YJPd70wfjyybkyd5" - } - ], - "tests": "test(\"should return json\", function() {\n const data = res.getBody();\n const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n const isUUID = (inputString) => {\n return uuidRegex.test(inputString);\n };\n \n expect(data.hello).to.equal(\"bruno\");\n expect(isUUID(data.uuid)).to.be.true;\n});\n", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - }, - { - "type": "folder", - "name": "local modules", - "filename": "local modules", - "items": [ - { - "type": "http", - "name": "invalid and valid module imports", - "filename": "invalid and valid module imports.bru", - "seq": 3, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "try {\n bru.setVar('invalid_module_error_thrown', false);\n // should throw an error\n const invalid = require(\"./lib/invalid\");\n}\ncatch(error) {\n bru.setVar('invalid_module_error_thrown', true);\n}\n\n\ntry {\n bru.setVar('valid_module_no_error', true);\n // should not throw an error\n const math = require(\"./lib/math\");\n}\ncatch(error) {\n bru.setVar('valid_module_no_error', false);\n}" - }, - "vars": {}, - "assertions": [ - { - "name": "invalid_module_error_thrown", - "value": "eq true", - "enabled": true, - "uid": "3imk4DIFjOQdXZL7RKBN0" - }, - { - "name": "valid_module_no_error", - "value": "eq true", - "enabled": true, - "uid": "bGJX4qgETYERw2hvg1i3U" - } - ], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "sum (without js extn)", - "filename": "sum (without js extn).bru", - "seq": 2, - "request": { - "url": "{{host}}/api/echo/json", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"a\": 1,\n \"b\": 2\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "const math = require(\"./lib/math\");\nconsole.log(math, 'math');\n\nconst body = req.getBody();\nbody.sum = math.sum(body.a, body.b);\nbody.areaOfCircle = math.areaOfCircle(2);\n\nreq.setBody(body);" - }, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "ckHfAfPNwcmxcCRBrj9sN" - } - ], - "tests": "test(\"should return json\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"a\": 1,\n \"b\": 2,\n \"sum\": 3,\n \"areaOfCircle\": 12.56\n });\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "sum", - "filename": "sum.bru", - "seq": 1, - "request": { - "url": "{{host}}/api/echo/json", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"a\": 1,\n \"b\": 2\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "const math = require(\"./lib/math.js\"); \nconst body = req.getBody();\nbody.sum = math.sum(body.a, body.b);\n\nreq.setBody(body);" - }, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "51KAG1UxDubFYXJrXSLCR" - } - ], - "tests": "test(\"should return json\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"a\": 1,\n \"b\": 2,\n \"sum\": 3\n });\n});\n\ntest(\"should return json\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"a\": 1,\n \"b\": 2,\n \"sum\": 3\n });\n});\n\ntest(\"should return json\", function() {\n const data = res.getBody();\n expect(res.getBody()).to.eql({\n \"a\": 1,\n \"b\": 2,\n \"sum\": 3\n });\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - }, - { - "type": "folder", - "name": "inbuilt modules", - "filename": "inbuilt modules", - "items": [ - { - "type": "folder", - "name": "axios", - "filename": "axios", - "items": [ - { - "type": "http", - "name": "axios-pre-req-script", - "filename": "axios-pre-req-script.bru", - "seq": 1, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "const axios = require(\"axios\");\n\nconst url = \"https://testbench-sanity.usebruno.com/api/echo/json\";\nconst response = await axios.post(url, {\n \"hello\": \"bruno\"\n});\n\nreq.setBody(response.data);\nreq.setMethod(\"POST\");\nreq.setUrl(url);" - }, - "vars": {}, - "assertions": [], - "tests": "test(\"req.getBody()\", function() {\n const data = res.getBody();\n expect(data).to.eql({\n \"hello\": \"bruno\"\n });\n});\n", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - }, - { - "type": "folder", - "name": "cheerio", - "filename": "cheerio", - "items": [ - { - "type": "http", - "name": "cheerio", - "filename": "cheerio.bru", - "seq": 1, - "request": { - "url": "https://echo.usebruno.com", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "text", - "text": "

Hello Bruno!

", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "const cheerio = require('cheerio');\n\nconst $ = cheerio.load('

Hello world

');\n\n$('h2.title').text('Hello there!');\n$('h2').addClass('welcome');\n\nbru.setVar(\"cheerio-test-html\", $.html());" - }, - "vars": {}, - "assertions": [], - "tests": "const cheerio = require('cheerio');\n\ntest(\"cheerio html - from scripts\", function() {\n const expected = '

Hello there!

';\n const html = bru.getVar('cheerio-test-html');\n expect(html).to.eql(expected);\n});\n\ntest(\"cheerio html - from tests\", function() {\n const expected = '

Hello Bruno!

';\n const $ = cheerio.load(res.body);\n expect($.html()).to.eql(expected);\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - }, - { - "type": "folder", - "name": "crypto-js", - "filename": "crypto-js", - "items": [ - { - "type": "http", - "name": "crypto-js-pre-request-script", - "filename": "crypto-js-pre-request-script.bru", - "seq": 1, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "var CryptoJS = require(\"crypto-js\");\n\n// Encrypt\nvar ciphertext = CryptoJS.AES.encrypt('my message', 'secret key 123').toString();\n\n// Decrypt\nvar bytes = CryptoJS.AES.decrypt(ciphertext, 'secret key 123');\nvar originalText = bytes.toString(CryptoJS.enc.Utf8);\n\nbru.setVar('crypto-test-message', originalText);" - }, - "vars": {}, - "assertions": [], - "tests": "test(\"crypto message\", function() {\n const data = bru.getVar('crypto-test-message');\n bru.setVar('crypto-test-message', null);\n expect(data).to.eql('my message');\n});\n", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - }, - { - "type": "folder", - "name": "nanoid", - "filename": "nanoid", - "items": [ - { - "type": "http", - "name": "nanoid", - "filename": "nanoid.bru", - "seq": 1, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "const { nanoid } = require(\"nanoid\");\n \nbru.setVar(\"nanoid-test-id\", nanoid());" - }, - "vars": {}, - "assertions": [], - "tests": "test(\"nanoid var\", function() {\n const id = bru.getVar('nanoid-test-id');\n let isValidNanoid = /^[a-zA-Z0-9_-]{21}$/.test(id)\n bru.setVar('nanoid-test-id', null);\n expect(isValidNanoid).to.eql(true);\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - }, - { - "type": "folder", - "name": "xml2js", - "filename": "xml2js", - "items": [ - { - "type": "http", - "name": "xml2js", - "filename": "xml2js.bru", - "seq": 1, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "var parseString = require('xml2js').parseString;\nvar xml = \"Hello xml2js!\"\nparseString(xml, function (err, result) {\n bru.setVar(\"xml2js-test-result\", result); \n});" - }, - "vars": {}, - "assertions": [], - "tests": "var parseString = require('xml2js').parseString;\n\ntest(\"xml2js parseString in scripts\", function() {\n const expected = {\n root: 'Hello xml2js!'\n };\n const result = bru.getVar('xml2js-test-result');\n expect(result).to.eql(expected);\n});\n\ntest(\"xml2js parseString in tests\", async function() {\n var xml = \"Hello inside test!\"\n const expected = {\n root: 'Hello inside test!'\n };\n parseString(xml, function (err, result) {\n expect(result).to.eql(expected);\n });\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - }, - { - "type": "folder", - "name": "uuid", - "filename": "uuid", - "items": [ - { - "type": "http", - "name": "uuid", - "filename": "uuid.bru", - "seq": 1, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "const { v4 } = require(\"uuid\");\n \nbru.setVar(\"uuid-test-id\", v4());" - }, - "vars": {}, - "assertions": [], - "tests": "test(\"uuid var\", function() {\n const id = bru.getVar('uuid-test-id');\n let isValidUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(id);\n bru.setVar('uuid-test-id', null);\n expect(isValidUuid).to.eql(true);\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - } - ] - }, - { - "type": "folder", - "name": "api", - "filename": "api", - "items": [ - { - "type": "folder", - "name": "bru", - "filename": "bru", - "root": { - "request": { - "vars": { - "req": [ - { - "name": "folder-var", - "value": "folder-var-value", - "enabled": true, - "local": false, - "uid": "AqPWEUdm2LylmjMIt3lkw" - } - ] - } - }, - "meta": { - "name": "bru" - } - }, - "items": [ - { - "type": "http", - "name": "getCollectionVar", - "filename": "getCollectionVar.bru", - "seq": 9, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [], - "tests": "test(\"should get collection var in scripts\", function() {\n const testVar = bru.getCollectionVar(\"collection-var\");\n expect(testVar).to.equal(\"collection-var-value\");\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "getEnvName", - "filename": "getEnvName.bru", - "seq": 1, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "const envName = bru.getEnvName();\nbru.setVar(\"testEnvName\", envName);" - }, - "vars": {}, - "assertions": [], - "tests": "test(\"should get env name in scripts\", function() {\n const testEnvName = bru.getVar(\"testEnvName\");\n expect(testEnvName).to.equal(\"Prod\");\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "getEnvVar", - "filename": "getEnvVar.bru", - "seq": 2, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [], - "tests": "test(\"should get env var in scripts\", function() {\n const host = bru.getEnvVar(\"host\")\n expect(host).to.equal(\"https://testbench-sanity.usebruno.com\");\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "getFolderVar", - "filename": "getFolderVar.bru", - "seq": 8, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [], - "tests": "test(\"should get folder var in scripts\", function() {\n const testVar = bru.getFolderVar(\"folder-var\");\n expect(testVar).to.equal(\"folder-var-value\");\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "getProcessEnv", - "filename": "getProcessEnv.bru", - "seq": 6, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [], - "tests": "test(\"bru.getProcessEnv()\", function() {\n const v = bru.getProcessEnv(\"PROC_ENV_VAR\");\n expect(v).to.equal(\"woof\");\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "getRequestVar", - "filename": "getRequestVar.bru", - "seq": 7, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": { - "req": [ - { - "name": "request-var", - "value": "request-var-value", - "enabled": true, - "local": false - } - ] - }, - "assertions": [], - "tests": "test(\"should get request var in scripts\", function() {\n const testVar = bru.getRequestVar(\"request-var\");\n expect(testVar).to.equal(\"request-var-value\");\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "getVar", - "filename": "getVar.bru", - "seq": 5, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [], - "tests": "test(\"should get var in scripts\", function() {\n const testSetVar = bru.getVar(\"testSetVar\");\n expect(testSetVar).to.equal(\"bruno-test-87267\");\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "runRequest-1", - "filename": "runRequest-1.bru", - "seq": 10, - "request": { - "url": "{{echo-host}}", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "text", - "text": "bruno", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "// reset values\nbru.setVar('run-request-runtime-var', null);\nbru.setEnvVar('run-request-env-var', null);\nbru.setGlobalEnvVar('run-request-global-env-var', null);\n\n// the above vars will be set in the below request\nconst resp = await bru.runRequest('scripting/api/bru/runRequest-2');\n\nbru.setVar('run-request-resp', {\n data: resp?.data,\n statusText: resp?.statusText,\n status: resp?.status\n});" - }, - "vars": {}, - "assertions": [], - "tests": "test(\"should get runtime var set in runRequest-2\", function() {\n const val = bru.getVar(\"run-request-runtime-var\");\n expect(val).to.equal(\"run-request-runtime-var-value\");\n});\n\ntest(\"should get env var set in runRequest-2\", function() {\n const val = bru.getEnvVar(\"run-request-env-var\");\n expect(val).to.equal(\"run-request-env-var-value\");\n});\n\ntest(\"should get global env var set in runRequest-2\", function() {\n const val = bru.getGlobalEnvVar(\"run-request-global-env-var\");\n const executionMode = req.getExecutionMode();\n if (executionMode == 'runner') {\n expect(val).to.equal(\"run-request-global-env-var-value\");\n }\n});\n\ntest(\"should get response of runRequest-2\", function() {\n const val = bru.getVar('run-request-resp');\n expect(JSON.stringify(val)).to.equal(JSON.stringify({\n \"data\": \"bruno\",\n \"statusText\": \"OK\",\n \"status\": 200\n }));\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "runRequest-2", - "filename": "runRequest-2.bru", - "seq": 11, - "request": { - "url": "{{echo-host}}", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "text", - "text": "bruno", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "bru.setVar('run-request-runtime-var', 'run-request-runtime-var-value');\nbru.setEnvVar('run-request-env-var', 'run-request-env-var-value');\nbru.setGlobalEnvVar('run-request-global-env-var', 'run-request-global-env-var-value');" - }, - "vars": {}, - "assertions": [], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "runRequest", - "filename": "runRequest.bru", - "seq": 2, - "request": { - "url": "{{host}}/api/echo/json", - "method": "POST", - "headers": [ - { - "name": "foo", - "value": "bar", - "enabled": true - } - ], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"hello\": \"bruno\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "bru.setVar(\"runRequest-ping-res-1\", null);\nbru.setVar(\"runRequest-ping-res-2\", null);\nbru.setVar(\"runRequest-ping-res-3\", null);\n\nlet pingRes = await bru.runRequest('ping');\nbru.setVar('runRequest-ping-res-1', {\n data: pingRes?.data,\n statusText: pingRes?.statusText,\n status: pingRes?.status\n});", - "res": "let pingRes = await bru.runRequest('ping');\nbru.setVar('runRequest-ping-res-2', {\n data: pingRes?.data,\n statusText: pingRes?.statusText,\n status: pingRes?.status\n});" - }, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "XiYVLMGIQARuIZRmXYS65" - } - ], - "tests": "const pingRes = await bru.runRequest('ping');\nbru.setVar('runRequest-ping-res-3', {\n data: pingRes?.data,\n statusText: pingRes?.statusText,\n status: pingRes?.status\n});\n\ntest(\"should run request and return valid response in pre-request script\", function() {\n const expectedPingRes = {\n data: \"pong\",\n statusText: \"OK\",\n status: 200\n };\n const pingRes = bru.getVar('runRequest-ping-res-1');\n expect(pingRes).to.eql(expectedPingRes);\n});\n\ntest(\"should run request and return valid response in post-response script\", function() {\n const expectedPingRes = {\n data: \"pong\",\n statusText: \"OK\",\n status: 200\n };\n const pingRes = bru.getVar('runRequest-ping-res-2');\n expect(pingRes).to.eql(expectedPingRes);\n});\n\ntest(\"should run request and return valid response in tests script\", function() {\n const expectedPingRes = {\n data: \"pong\",\n statusText: \"OK\",\n status: 200\n };\n const pingRes = bru.getVar('runRequest-ping-res-3');\n expect(pingRes).to.eql(expectedPingRes);\n});\n", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "setEnvVar", - "filename": "setEnvVar.bru", - "seq": 3, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "res": "bru.setEnvVar(\"testSetEnvVar\", \"bruno-29653\")" - }, - "vars": {}, - "assertions": [], - "tests": "test(\"should set env var in scripts\", function() {\n const testSetEnvVar = bru.getEnvVar(\"testSetEnvVar\")\n expect(testSetEnvVar).to.equal(\"bruno-29653\");\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "setVar", - "filename": "setVar.bru", - "seq": 4, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "res": "bru.setVar(\"testSetVar\", \"bruno-test-87267\")" - }, - "vars": {}, - "assertions": [], - "tests": "test(\"should get var in scripts\", function() {\n const testSetVar = bru.getVar(\"testSetVar\");\n expect(testSetVar).to.equal(\"bruno-test-87267\");\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "folder", - "name": "runner", - "filename": "runner", - "items": [ - { - "type": "http", - "name": "1", - "filename": "1.bru", - "seq": 1, - "request": { - "url": "https://echo.usebruno.com", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "bru.setVar('bru-runner-req', 1);", - "res": "bru.setVar('bru.runner.skipRequest', true);" - }, - "vars": {}, - "assertions": [], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "2", - "filename": "2.bru", - "seq": 2, - "request": { - "url": "https://echo.usebruno.com", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "bru.runner.skipRequest();", - "res": "bru.setVar('bru.runner.skipRequest', false);" - }, - "vars": {}, - "assertions": [], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "3", - "filename": "3.bru", - "seq": 3, - "request": { - "url": "https://echo.usebruno.com", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [], - "tests": "", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - } - ] - }, - { - "type": "folder", - "name": "req", - "filename": "req", - "items": [ - { - "type": "http", - "name": "getBody", - "filename": "getBody.bru", - "seq": 9, - "request": { - "url": "{{host}}/api/echo/json", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"hello\": \"bruno\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "YACUsQsYlX6yvIkkHfGeM" - } - ], - "tests": "test(\"req.getBody()\", function() {\n const data = res.getBody();\n expect(data).to.eql({\n \"hello\": \"bruno\"\n });\n});\n", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "getHeader", - "filename": "getHeader.bru", - "seq": 5, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [ - { - "name": "bruno", - "value": "is-awesome", - "enabled": true - } - ], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "1fFLd8VtOZKujvtAkGUZj" - }, - { - "name": "res.body", - "value": "eq pong", - "enabled": true, - "uid": "QD11VDqnqq5jTcL88Y3D1" - } - ], - "tests": "test(\"req.getHeader(name)\", function() {\n const h = req.getHeader('bruno');\n expect(h).to.equal(\"is-awesome\");\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "getHeaders", - "filename": "getHeaders.bru", - "seq": 7, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [ - { - "name": "bruno", - "value": "is-awesome", - "enabled": true - }, - { - "name": "della", - "value": "is-beautiful", - "enabled": true - } - ], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "04R4EJbusCqY89KXTKajO" - }, - { - "name": "res.body", - "value": "eq pong", - "enabled": true, - "uid": "CKd1EZjgvkeFB6a25BpDc" - } - ], - "tests": "test(\"req.getHeaders()\", function() {\n const h = req.getHeaders();\n expect(h.bruno).to.equal(\"is-awesome\");\n expect(h.della).to.equal(\"is-beautiful\");\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "getMethod", - "filename": "getMethod.bru", - "seq": 3, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "5ItoSs1VqOfB0sll7wqpN" - }, - { - "name": "res.body", - "value": "eq pong", - "enabled": true, - "uid": "JdEtqrNa8XTVM8bwHYNLq" - } - ], - "tests": "test(\"req.getMethod()()\", function() {\n const method = req.getMethod();\n expect(method).to.equal(\"GET\");\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "getUrl", - "filename": "getUrl.bru", - "seq": 1, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "OkR2RNGAnwkPvXPex4huK" - }, - { - "name": "res.body", - "value": "eq pong", - "enabled": true, - "uid": "T7L4EFpqrauldg2JOGshM" - } - ], - "tests": "test(\"req.getUrl()\", function() {\n const url = req.getUrl();\n expect(url).to.equal(\"https://testbench-sanity.usebruno.com/ping\");\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "setBody", - "filename": "setBody.bru", - "seq": 10, - "request": { - "url": "{{host}}/api/echo/json", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"hello\": \"bruno\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "req.setBody({\n \"bruno\": \"is awesome\"\n});" - }, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "1tuWeypKcGgbuLEXYF54S" - } - ], - "tests": "test(\"req.setBody()\", function() {\n const data = res.getBody();\n expect(data).to.eql({\n \"bruno\": \"is awesome\"\n });\n});\n", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "setHeader", - "filename": "setHeader.bru", - "seq": 6, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [ - { - "name": "bruno", - "value": "is-awesome", - "enabled": true - } - ], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "req.setHeader('bruno', 'is-the-future');" - }, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "jLHIdvmg0VXn4PLW5Ch3j" - }, - { - "name": "res.body", - "value": "eq pong", - "enabled": true, - "uid": "PLKiqwDU1HsEkwchjyNky" - } - ], - "tests": "test(\"req.setHeader(name)\", function() {\n const h = req.getHeader('bruno');\n expect(h).to.equal(\"is-the-future\");\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "setHeaders", - "filename": "setHeaders.bru", - "seq": 8, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [ - { - "name": "bruno", - "value": "is-awesome", - "enabled": true - }, - { - "name": "della", - "value": "is-beautiful", - "enabled": true - } - ], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "req.setHeaders({\n \"content-type\": \"application/text\",\n \"transaction-id\": \"foobar\"\n});" - }, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "cFZM1lk0lnaR845ZQscl9" - }, - { - "name": "res.body", - "value": "eq pong", - "enabled": true, - "uid": "Gt07qor0o6lnGiMGvtPF3" - } - ], - "tests": "test(\"req.setHeaders()\", function() {\n const h = req.getHeaders();\n expect(h['content-type']).to.equal(\"application/text\");\n expect(h['transaction-id']).to.equal(\"foobar\");\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "setMethod", - "filename": "setMethod.bru", - "seq": 4, - "request": { - "url": "{{host}}/ping", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "req.setMethod(\"GET\");" - }, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "cJZfmbnZVfdaenvhz4wfq" - }, - { - "name": "res.body", - "value": "eq pong", - "enabled": true, - "uid": "wHTmbMRx9ZYWSZ8QivM8h" - } - ], - "tests": "test(\"req.setMethod()()\", function() {\n const method = req.getMethod();\n expect(method).to.equal(\"GET\");\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "setUrl", - "filename": "setUrl.bru", - "seq": 2, - "request": { - "url": "{{host}}/ping/invalid", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": { - "req": "req.setUrl(\"https://testbench-sanity.usebruno.com/ping\");" - }, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "rVolqUH1aCO0NurDPCA0T" - }, - { - "name": "res.body", - "value": "eq pong", - "enabled": true, - "uid": "5ynLdeD42v7nQlvI8ORXZ" - } - ], - "tests": "test(\"req.setUrl()\", function() {\n const url = req.getUrl();\n expect(url).to.equal(\"https://testbench-sanity.usebruno.com/ping\");\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - }, - { - "type": "folder", - "name": "res", - "filename": "res", - "items": [ - { - "type": "http", - "name": "getBody", - "filename": "getBody.bru", - "seq": 4, - "request": { - "url": "{{host}}/api/echo/json", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"hello\": \"bruno\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "QAa35PSfpwk267ompkUyX" - } - ], - "tests": "test(\"res.getBody()\", function() {\n const data = res.getBody();\n expect(data).to.eql({\n \"hello\": \"bruno\"\n });\n});\n", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "getHeader", - "filename": "getHeader.bru", - "seq": 2, - "request": { - "url": "{{host}}/api/echo/json", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"hello\": \"bruno\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "QfXtdGakjK897gTqaU4PE" - } - ], - "tests": "test(\"res.getHeader(name)\", function() {\n const server = res.getHeader('x-powered-by');\n expect(server).to.eql('Express');\n});\n", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "getHeaders", - "filename": "getHeaders.bru", - "seq": 3, - "request": { - "url": "{{host}}/api/echo/json", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"hello\": \"bruno\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "WCmqMcNZlAoJdZ9g2KLVe" - } - ], - "tests": "test(\"res.getHeaders(name)\", function() {\n const h = res.getHeaders();\n expect(h['x-powered-by']).to.eql('Express');\n expect(h['content-length']).to.eql('17');\n});\n", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "getResponseTime", - "filename": "getResponseTime.bru", - "seq": 5, - "request": { - "url": "{{host}}/api/echo/json", - "method": "POST", - "headers": [], - "params": [], - "body": { - "mode": "json", - "json": "{\n \"hello\": \"bruno\"\n}", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "DpDzW3VB5cIFdxtvxe6Og" - } - ], - "tests": "test(\"res.getResponseTime()\", function() {\n const responseTime = res.getResponseTime();\n expect(typeof responseTime).to.eql(\"number\");\n expect(responseTime > 0).to.be.true;\n});\n", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "getStatus", - "filename": "getStatus.bru", - "seq": 1, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.status", - "value": "eq 200", - "enabled": true, - "uid": "9lIBr7KIWkUTYANiSBNAW" - }, - { - "name": "res.body", - "value": "eq pong", - "enabled": true, - "uid": "TnsOCt0EUxB7meZTOkEdb" - } - ], - "tests": "test(\"res.getStatus()\", function() {\n const status = res.getStatus()\n expect(status).to.equal(200);\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - }, - { - "type": "http", - "name": "getStatusText", - "filename": "getStatusText.bru", - "seq": 6, - "request": { - "url": "{{host}}/ping", - "method": "GET", - "headers": [], - "params": [], - "body": { - "mode": "none", - "formUrlEncoded": [], - "multipartForm": [], - "file": [] - }, - "script": {}, - "vars": {}, - "assertions": [ - { - "name": "res.statusText", - "value": "eq OK", - "enabled": true, - "uid": "bhhg2wMYFSh060HKl8Vgq" - }, - { - "name": "res.body", - "value": "eq pong", - "enabled": true, - "uid": "DTYW4zxmKrtsbPxqn8U5E" - } - ], - "tests": "test(\"res.getStatusText()\", function() {\n const statusText = res.getStatusText()\n expect(statusText).to.equal('OK');\n});", - "docs": "", - "auth": { - "mode": "none" - } - } - } - ] - } - ] - } - ] - } - ], - "activeEnvironmentUid": "epJ1gynipcQgb5uJLBHZr", - "environments": [ - { - "variables": [ - { - "name": "host", - "value": "http://localhost:8080", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "httpfaker", - "value": "https://www.httpfaker.org", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "bearer_auth_token", - "value": "your_secret_token", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "basic_auth_password", - "value": "della", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "env.var1", - "value": "envVar1", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "env-var2", - "value": "envVar2", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "bark", - "value": "{{process.env.PROC_ENV_VAR}}", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "foo", - "value": "bar", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "testSetEnvVar", - "value": "bruno-29653", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "echo-host", - "value": "https://echo.usebruno.com", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "client_id", - "value": "client_id_1", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "client_secret", - "value": "client_secret_1", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "auth_url", - "value": "http://localhost:8080/api/auth/oauth2/authorization_code/authorize", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "callback_url", - "value": "http://localhost:8080/api/auth/oauth2/authorization_code/callback", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "access_token_url", - "value": "http://localhost:8080/api/auth/oauth2/authorization_code/token", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "passwordCredentials_username", - "value": "foo", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "passwordCredentials_password", - "value": "bar", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "github_authorize_url", - "value": "https://github.com/login/oauth/authorize", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "github_access_token_url", - "value": "https://github.com/login/oauth/access_token", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "google_auth_url", - "value": "https://accounts.google.com/o/oauth2/auth", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "google_access_token_url", - "value": "https://accounts.google.com/o/oauth2/token", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "google_scope", - "value": "https://www.googleapis.com/auth/userinfo.email", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "github_client_secret", - "value": "", - "enabled": true, - "secret": true, - "type": "text" - }, - { - "name": "github_client_id", - "value": "", - "enabled": true, - "secret": true, - "type": "text" - }, - { - "name": "google_client_id", - "value": "", - "enabled": true, - "secret": true, - "type": "text" - }, - { - "name": "google_client_secret", - "value": "", - "enabled": true, - "secret": true, - "type": "text" - }, - { - "name": "github_authorization_code", - "value": "", - "enabled": true, - "secret": true, - "type": "text" - }, - { - "name": "passwordCredentials_access_token", - "value": "", - "enabled": true, - "secret": true, - "type": "text" - }, - { - "name": "client_credentials_access_token", - "value": "", - "enabled": true, - "secret": true, - "type": "text" - }, - { - "name": "authorization_code_access_token", - "value": "", - "enabled": true, - "secret": true, - "type": "text" - }, - { - "name": "github_access_token", - "value": "", - "enabled": true, - "secret": true, - "type": "text" - } - ], - "name": "Local" - }, - { - "variables": [ - { - "name": "host", - "value": "https://testbench-sanity.usebruno.com", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "httpfaker", - "value": "https://www.httpfaker.org", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "bearer_auth_token", - "value": "your_secret_token", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "basic_auth_password", - "value": "della", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "env.var1", - "value": "envVar1", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "env-var2", - "value": "envVar2", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "bark", - "value": "{{process.env.PROC_ENV_VAR}}", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "foo", - "value": "bar", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "testSetEnvVar", - "value": "bruno-29653", - "enabled": true, - "secret": false, - "type": "text" - }, - { - "name": "echo-host", - "value": "https://echo.usebruno.com", - "enabled": true, - "secret": false, - "type": "text" - } - ], - "name": "Prod" - } - ], - "root": { - "request": { - "auth": { - "mode": "bearer", - "bearer": { - "token": "{{bearer_auth_token}}" - } - }, - "headers": [ - { - "name": "check", - "value": "again", - "enabled": true, - "uid": "x5ic2SWqv4uOlkzzUaK6u" - }, - { - "name": "token", - "value": "{{collection_pre_var_token}}", - "enabled": true, - "uid": "MdFY4Vekah6cfuxuClOCu" - }, - { - "name": "collection-header", - "value": "collection-header-value", - "enabled": true, - "uid": "wCrMSPJUrX9QljaY6kadq" - } - ], - "script": { - "req": "// used by `scripting/js/folder-collection script-tests`\nconst shouldTestCollectionScripts = bru.getVar('should-test-collection-scripts');\nif(shouldTestCollectionScripts) {\n bru.setVar('collection-var-set-by-collection-script', 'collection-var-value-set-by-collection-script');\n}" - }, - "vars": { - "req": [ - { - "name": "collection_pre_var", - "value": "collection_pre_var_value", - "enabled": true, - "local": false, - "uid": "6K19B5ZyhSBTB1ilbx2Sx" - }, - { - "name": "collection_pre_var_token", - "value": "{{request_pre_var_token}}", - "enabled": true, - "local": false, - "uid": "zdoL9ayNeJnNY7ot6RHDj" - }, - { - "name": "collection-var", - "value": "collection-var-value", - "enabled": true, - "local": false, - "uid": "6tgTaZw6HTazsyAMWrVfL" - } - ] - }, - "tests": "// used by `scripting/js/folder-collection script-tests`\nconst shouldTestCollectionScripts = bru.getVar('should-test-collection-scripts');\nconst collectionVar = bru.getVar(\"collection-var-set-by-collection-script\");\nif (shouldTestCollectionScripts && collectionVar) {\n test(\"collection level test - should get the var that was set by the collection script\", function() {\n expect(collectionVar).to.equal(\"collection-var-value-set-by-collection-script\");\n }); \n bru.setVar('collection-var-set-by-collection-script', null); \n bru.setVar('should-test-collection-scripts', null);\n}" - }, - "docs": "# bruno-testbench 🐶\n\nThis is a test collection that I am using to test various functionalities around bruno" - }, - "brunoConfig": { - "version": "1", - "name": "bruno-testbench", - "type": "collection", - "proxy": { - "enabled": false, - "protocol": "http", - "hostname": "{{proxyHostname}}", - "port": 4000, - "auth": { - "enabled": false, - "username": "anoop" - }, - "bypassProxy": "" - }, - "scripts": { - "moduleWhitelist": [ - "crypto", - "buffer", - "form-data" - ], - "filesystemAccess": { - "allow": true - } - }, - "clientCertificates": { - "enabled": true, - "certs": [] - }, - "presets": { - "requestType": "http", - "requestUrl": "http://localhost:6000" - }, - "ignore": [ - "node_modules", - ".git" - ], - "size": 0.046390533447265625, - "filesCount": 104 - } - } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 01e79a1a..87966699 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { - "name": "opencollection", + "name": "bruno-api-docs", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "opencollection", + "name": "bruno-api-docs", "workspaces": [ - "packages/oc-docs" + "packages/bruno-api-docs" ] }, "node_modules/@alloc/quick-lru": { @@ -1427,7 +1427,7 @@ } }, "node_modules/@opencollection/docs": { - "resolved": "packages/oc-docs", + "resolved": "packages/bruno-api-docs", "link": true }, "node_modules/@opencollection/types": { @@ -9614,7 +9614,7 @@ "url": "https://github.com/sponsors/wooorm" } }, - "packages/oc-docs": { + "packages/bruno-api-docs": { "name": "@opencollection/docs", "version": "0.0.1", "license": "MIT", diff --git a/package.json b/package.json index bcd52578..64702080 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { - "name": "opencollection", + "name": "bruno-api-docs", "private": true, "workspaces": [ - "packages/oc-docs" + "packages/bruno-api-docs" ], "homepage": "https://www.opencollection.com" } diff --git a/packages/oc-docs/.gitignore b/packages/bruno-api-docs/.gitignore similarity index 100% rename from packages/oc-docs/.gitignore rename to packages/bruno-api-docs/.gitignore diff --git a/packages/oc-docs/e2e/README.md b/packages/bruno-api-docs/e2e/README.md similarity index 100% rename from packages/oc-docs/e2e/README.md rename to packages/bruno-api-docs/e2e/README.md diff --git a/packages/bruno-api-docs/e2e/components/base.component.ts b/packages/bruno-api-docs/e2e/components/base.component.ts new file mode 100644 index 00000000..fabf37cc --- /dev/null +++ b/packages/bruno-api-docs/e2e/components/base.component.ts @@ -0,0 +1,27 @@ +import type { Page, Locator } from '@playwright/test'; + +export abstract class BaseComponent { + readonly root: Locator; + private dragY = 0; + + constructor(protected readonly page: Page, root?: Locator) { + this.root = root ?? page.locator(':root'); + } + + /** Press the pointer on a resize handle; the drag y is kept for later moves. */ + protected async grabHandle(handle: Locator): Promise { + const box = await handle.boundingBox(); + this.dragY = (box?.y ?? 0) + (box?.height ?? 0) / 2; + await handle.hover(); + await this.page.mouse.down(); + } + + /** Move the held pointer to an absolute x (keeps the grabbed y). */ + async movePointerToX(x: number): Promise { + await this.page.mouse.move(x, this.dragY, { steps: 10 }); + } + + async releasePointer(): Promise { + await this.page.mouse.up(); + } +} diff --git a/packages/oc-docs/e2e/components/breadcrumb.component.ts b/packages/bruno-api-docs/e2e/components/breadcrumb.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/breadcrumb.component.ts rename to packages/bruno-api-docs/e2e/components/breadcrumb.component.ts diff --git a/packages/oc-docs/e2e/components/code-editor/code-editor.component.ts b/packages/bruno-api-docs/e2e/components/code-editor/code-editor.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/code-editor/code-editor.component.ts rename to packages/bruno-api-docs/e2e/components/code-editor/code-editor.component.ts diff --git a/packages/oc-docs/e2e/components/collection-settings/collection-settings.component.ts b/packages/bruno-api-docs/e2e/components/collection-settings/collection-settings.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/collection-settings/collection-settings.component.ts rename to packages/bruno-api-docs/e2e/components/collection-settings/collection-settings.component.ts diff --git a/packages/bruno-api-docs/e2e/components/environments/env-editor.component.ts b/packages/bruno-api-docs/e2e/components/environments/env-editor.component.ts new file mode 100644 index 00000000..25d4342b --- /dev/null +++ b/packages/bruno-api-docs/e2e/components/environments/env-editor.component.ts @@ -0,0 +1,19 @@ +import type { Locator } from '@playwright/test'; +import { BaseComponent } from '../base.component'; + +export class EnvEditorComponent extends BaseComponent { + readonly cards = this.page.getByTestId('env-var-cards'); + readonly cardItems = this.cards.locator('.env-card'); + readonly nameInputs = this.cards.getByPlaceholder('Name'); + readonly valueInputs = this.cards.getByPlaceholder('Value'); + + /** The per-variable enable/disable checkbox, addressed by the variable name via its aria-label. */ + enableToggle(name: string): Locator { + return this.cards.getByRole('checkbox', { name: `Enable ${name}` }); + } + + /** The card that owns the named variable, matched via its enable checkbox. */ + cardFor(name: string): Locator { + return this.cardItems.filter({ has: this.page.getByRole('checkbox', { name: `Enable ${name}` }) }); + } +} diff --git a/packages/oc-docs/e2e/components/environments/environment-table.component.ts b/packages/bruno-api-docs/e2e/components/environments/environment-table.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/environments/environment-table.component.ts rename to packages/bruno-api-docs/e2e/components/environments/environment-table.component.ts diff --git a/packages/oc-docs/e2e/components/folder/folder-configuration.component.ts b/packages/bruno-api-docs/e2e/components/folder/folder-configuration.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/folder/folder-configuration.component.ts rename to packages/bruno-api-docs/e2e/components/folder/folder-configuration.component.ts diff --git a/packages/oc-docs/e2e/components/key-value-table/key-value-table.component.ts b/packages/bruno-api-docs/e2e/components/key-value-table/key-value-table.component.ts similarity index 81% rename from packages/oc-docs/e2e/components/key-value-table/key-value-table.component.ts rename to packages/bruno-api-docs/e2e/components/key-value-table/key-value-table.component.ts index 41b671db..ab45e001 100644 --- a/packages/oc-docs/e2e/components/key-value-table/key-value-table.component.ts +++ b/packages/bruno-api-docs/e2e/components/key-value-table/key-value-table.component.ts @@ -19,4 +19,9 @@ export class KeyValueTableComponent extends BaseComponent { this.cellErrors = page.getByTestId(`${testId}-error`); this.autocomplete = page.getByTestId('variable-autocomplete'); } + + /** The per-row enable/disable checkbox, addressed by the row name via its aria-label. */ + enableToggle(name: string): Locator { + return this.table.getByRole('checkbox', { name: `Enable ${name}` }); + } } diff --git a/packages/oc-docs/e2e/components/layout/env-switcher.component.ts b/packages/bruno-api-docs/e2e/components/layout/env-switcher.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/layout/env-switcher.component.ts rename to packages/bruno-api-docs/e2e/components/layout/env-switcher.component.ts diff --git a/packages/oc-docs/e2e/components/layout/page-header.component.ts b/packages/bruno-api-docs/e2e/components/layout/page-header.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/layout/page-header.component.ts rename to packages/bruno-api-docs/e2e/components/layout/page-header.component.ts diff --git a/packages/oc-docs/e2e/components/layout/theme-toggle.component.ts b/packages/bruno-api-docs/e2e/components/layout/theme-toggle.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/layout/theme-toggle.component.ts rename to packages/bruno-api-docs/e2e/components/layout/theme-toggle.component.ts diff --git a/packages/oc-docs/e2e/components/markdown.component.ts b/packages/bruno-api-docs/e2e/components/markdown.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/markdown.component.ts rename to packages/bruno-api-docs/e2e/components/markdown.component.ts diff --git a/packages/oc-docs/e2e/components/overview/collection-configuration.component.ts b/packages/bruno-api-docs/e2e/components/overview/collection-configuration.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/overview/collection-configuration.component.ts rename to packages/bruno-api-docs/e2e/components/overview/collection-configuration.component.ts diff --git a/packages/oc-docs/e2e/components/overview/collection-stats.component.ts b/packages/bruno-api-docs/e2e/components/overview/collection-stats.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/overview/collection-stats.component.ts rename to packages/bruno-api-docs/e2e/components/overview/collection-stats.component.ts diff --git a/packages/oc-docs/e2e/components/overview/environments.component.ts b/packages/bruno-api-docs/e2e/components/overview/environments.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/overview/environments.component.ts rename to packages/bruno-api-docs/e2e/components/overview/environments.component.ts diff --git a/packages/oc-docs/e2e/components/overview/header.component.ts b/packages/bruno-api-docs/e2e/components/overview/header.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/overview/header.component.ts rename to packages/bruno-api-docs/e2e/components/overview/header.component.ts diff --git a/packages/oc-docs/e2e/components/playground.component.ts b/packages/bruno-api-docs/e2e/components/playground.component.ts similarity index 86% rename from packages/oc-docs/e2e/components/playground.component.ts rename to packages/bruno-api-docs/e2e/components/playground.component.ts index ea549374..75f42bcb 100644 --- a/packages/oc-docs/e2e/components/playground.component.ts +++ b/packages/bruno-api-docs/e2e/components/playground.component.ts @@ -8,6 +8,8 @@ export class PlaygroundComponent extends BaseComponent { readonly keyValueTable = new KeyValueTableComponent(this.page); readonly preRequestScriptEditor = new CodeEditorComponent(this.page, 'scripts-editor-pre-request'); readonly postResponseScriptEditor = new CodeEditorComponent(this.page, 'scripts-editor-post-response'); + readonly bodyEditor = new CodeEditorComponent(this.page, 'body-editor'); + readonly testsEditor = new CodeEditorComponent(this.page, 'tests-editor'); readonly header = this.page.getByTestId('playground-header'); readonly switcher = this.page.getByTestId('playground-dock-switcher'); @@ -15,6 +17,7 @@ export class PlaygroundComponent extends BaseComponent { readonly runner = this.page.getByTestId('playground-runner'); readonly loadError = this.page.getByTestId('playground-load-error'); readonly sidebarPanel = this.page.getByTestId('playground-sidebar-panel'); + readonly sidebarResizer = this.page.getByTestId('playground-sidebar-resizer'); readonly sidebarBackdrop = this.page.getByTestId('playground-sidebar-backdrop'); readonly collectionNode = this.page.getByTestId('sidebar-collection-root'); readonly collectionCollapseToggle = this.collectionNode.getByRole('button', { @@ -93,6 +96,7 @@ export class PlaygroundComponent extends BaseComponent { async openRequest(name: string): Promise { await this.treeItems.filter({ hasText: name }).first().click(); + await this.view.waitFor({ state: 'visible' }); } async openEnvironments(): Promise { @@ -111,7 +115,13 @@ export class PlaygroundComponent extends BaseComponent { } async selectTab(id: string): Promise { - await this.tab(id).click(); + const direct = this.tab(id); + if ((await direct.count()) > 0 && (await direct.isVisible())) { + await direct.click(); + return; + } + await this.page.getByTestId('tabs-more').click(); + await this.page.getByTestId(`tabs-more-${id}`).click(); } async close(): Promise { @@ -121,4 +131,13 @@ export class PlaygroundComponent extends BaseComponent { async toggleCollapse(): Promise { await this.collapseButton.click(); } + + async sidebarWidth(): Promise { + const box = await this.sidebarPanel.boundingBox(); + return box?.width ?? 0; + } + + async grabSidebarResizer(): Promise { + await this.grabHandle(this.sidebarResizer); + } } diff --git a/packages/oc-docs/e2e/components/playground/request-body.component.ts b/packages/bruno-api-docs/e2e/components/playground/request-body.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/playground/request-body.component.ts rename to packages/bruno-api-docs/e2e/components/playground/request-body.component.ts diff --git a/packages/oc-docs/e2e/components/request/code-snippet.component.ts b/packages/bruno-api-docs/e2e/components/request/code-snippet.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/request/code-snippet.component.ts rename to packages/bruno-api-docs/e2e/components/request/code-snippet.component.ts diff --git a/packages/oc-docs/e2e/components/request/examples.component.ts b/packages/bruno-api-docs/e2e/components/request/examples.component.ts similarity index 92% rename from packages/oc-docs/e2e/components/request/examples.component.ts rename to packages/bruno-api-docs/e2e/components/request/examples.component.ts index c4b81ab6..8c03e3bf 100644 --- a/packages/oc-docs/e2e/components/request/examples.component.ts +++ b/packages/bruno-api-docs/e2e/components/request/examples.component.ts @@ -29,10 +29,6 @@ export class ExamplesComponent extends BaseComponent { await this.example(name).getByTestId('example-toggle').click(); } - async try(name: string): Promise { - await this.example(name).getByTestId('example-try').click(); - } - async selectRequestTab(name: string, tab: string): Promise { await this.example(name).getByTestId(`example-request-pane-tab-${tab}`).click(); } diff --git a/packages/oc-docs/e2e/components/request/execution-context.component.ts b/packages/bruno-api-docs/e2e/components/request/execution-context.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/request/execution-context.component.ts rename to packages/bruno-api-docs/e2e/components/request/execution-context.component.ts diff --git a/packages/oc-docs/e2e/components/request/url-bar.component.ts b/packages/bruno-api-docs/e2e/components/request/url-bar.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/request/url-bar.component.ts rename to packages/bruno-api-docs/e2e/components/request/url-bar.component.ts diff --git a/packages/oc-docs/e2e/components/script/script-content.component.ts b/packages/bruno-api-docs/e2e/components/script/script-content.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/script/script-content.component.ts rename to packages/bruno-api-docs/e2e/components/script/script-content.component.ts diff --git a/packages/oc-docs/e2e/components/search/search.component.ts b/packages/bruno-api-docs/e2e/components/search/search.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/search/search.component.ts rename to packages/bruno-api-docs/e2e/components/search/search.component.ts diff --git a/packages/oc-docs/e2e/components/secret-value.component.ts b/packages/bruno-api-docs/e2e/components/secret-value.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/secret-value.component.ts rename to packages/bruno-api-docs/e2e/components/secret-value.component.ts diff --git a/packages/oc-docs/e2e/components/sidebar.component.ts b/packages/bruno-api-docs/e2e/components/sidebar.component.ts similarity index 87% rename from packages/oc-docs/e2e/components/sidebar.component.ts rename to packages/bruno-api-docs/e2e/components/sidebar.component.ts index 03ee5a5b..95231e5c 100644 --- a/packages/oc-docs/e2e/components/sidebar.component.ts +++ b/packages/bruno-api-docs/e2e/components/sidebar.component.ts @@ -8,6 +8,7 @@ export class SidebarComponent extends BaseComponent { readonly environments = this.page.getByTestId('sidebar-environments'); readonly collapseButton = this.page.getByTestId('sidebar-collapse'); readonly expandButton = this.page.getByTestId('sidebar-expand'); + readonly resizer = this.page.getByTestId('sidebar-resizer'); readonly drawer = this.page.getByTestId('sidebar-drawer'); readonly backdrop = this.page.getByTestId('sidebar-backdrop'); readonly hamburger = this.page.getByTestId('topbar-menu'); @@ -42,6 +43,15 @@ export class SidebarComponent extends BaseComponent { } } + async width(): Promise { + const box = await this.inline.boundingBox(); + return box?.width ?? 0; + } + + async grabResizer(): Promise { + await this.grabHandle(this.resizer); + } + async collapse(): Promise { await this.inline.hover(); await this.collapseButton.click(); diff --git a/packages/oc-docs/e2e/components/tooltip.component.ts b/packages/bruno-api-docs/e2e/components/tooltip.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/tooltip.component.ts rename to packages/bruno-api-docs/e2e/components/tooltip.component.ts diff --git a/packages/oc-docs/e2e/components/variable-card/variable-card.component.ts b/packages/bruno-api-docs/e2e/components/variable-card/variable-card.component.ts similarity index 100% rename from packages/oc-docs/e2e/components/variable-card/variable-card.component.ts rename to packages/bruno-api-docs/e2e/components/variable-card/variable-card.component.ts diff --git a/packages/oc-docs/e2e/config/app.config.ts b/packages/bruno-api-docs/e2e/config/app.config.ts similarity index 100% rename from packages/oc-docs/e2e/config/app.config.ts rename to packages/bruno-api-docs/e2e/config/app.config.ts diff --git a/packages/oc-docs/e2e/pages/base.page.ts b/packages/bruno-api-docs/e2e/pages/base.page.ts similarity index 100% rename from packages/oc-docs/e2e/pages/base.page.ts rename to packages/bruno-api-docs/e2e/pages/base.page.ts diff --git a/packages/oc-docs/e2e/pages/environments.page.ts b/packages/bruno-api-docs/e2e/pages/environments.page.ts similarity index 100% rename from packages/oc-docs/e2e/pages/environments.page.ts rename to packages/bruno-api-docs/e2e/pages/environments.page.ts diff --git a/packages/oc-docs/e2e/pages/folder.page.ts b/packages/bruno-api-docs/e2e/pages/folder.page.ts similarity index 100% rename from packages/oc-docs/e2e/pages/folder.page.ts rename to packages/bruno-api-docs/e2e/pages/folder.page.ts diff --git a/packages/oc-docs/e2e/pages/overview.page.ts b/packages/bruno-api-docs/e2e/pages/overview.page.ts similarity index 100% rename from packages/oc-docs/e2e/pages/overview.page.ts rename to packages/bruno-api-docs/e2e/pages/overview.page.ts diff --git a/packages/oc-docs/e2e/pages/request.page.ts b/packages/bruno-api-docs/e2e/pages/request.page.ts similarity index 100% rename from packages/oc-docs/e2e/pages/request.page.ts rename to packages/bruno-api-docs/e2e/pages/request.page.ts diff --git a/packages/oc-docs/e2e/pages/script.page.ts b/packages/bruno-api-docs/e2e/pages/script.page.ts similarity index 100% rename from packages/oc-docs/e2e/pages/script.page.ts rename to packages/bruno-api-docs/e2e/pages/script.page.ts diff --git a/packages/oc-docs/e2e/pages/unsupported-request.page.ts b/packages/bruno-api-docs/e2e/pages/unsupported-request.page.ts similarity index 100% rename from packages/oc-docs/e2e/pages/unsupported-request.page.ts rename to packages/bruno-api-docs/e2e/pages/unsupported-request.page.ts diff --git a/packages/oc-docs/e2e/playwright/index.ts b/packages/bruno-api-docs/e2e/playwright/index.ts similarity index 100% rename from packages/oc-docs/e2e/playwright/index.ts rename to packages/bruno-api-docs/e2e/playwright/index.ts diff --git a/packages/oc-docs/e2e/playwright/pages.fixture.ts b/packages/bruno-api-docs/e2e/playwright/pages.fixture.ts similarity index 100% rename from packages/oc-docs/e2e/playwright/pages.fixture.ts rename to packages/bruno-api-docs/e2e/playwright/pages.fixture.ts diff --git a/packages/oc-docs/e2e/tests/app/app.spec.ts b/packages/bruno-api-docs/e2e/tests/app/app.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/app/app.spec.ts rename to packages/bruno-api-docs/e2e/tests/app/app.spec.ts diff --git a/packages/oc-docs/e2e/tests/collection-settings/collection-settings.spec.ts b/packages/bruno-api-docs/e2e/tests/collection-settings/collection-settings.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/collection-settings/collection-settings.spec.ts rename to packages/bruno-api-docs/e2e/tests/collection-settings/collection-settings.spec.ts diff --git a/packages/oc-docs/e2e/tests/environments/environments.spec.ts b/packages/bruno-api-docs/e2e/tests/environments/environments.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/environments/environments.spec.ts rename to packages/bruno-api-docs/e2e/tests/environments/environments.spec.ts diff --git a/packages/oc-docs/e2e/tests/folder/folder.spec.ts b/packages/bruno-api-docs/e2e/tests/folder/folder.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/folder/folder.spec.ts rename to packages/bruno-api-docs/e2e/tests/folder/folder.spec.ts diff --git a/packages/oc-docs/e2e/tests/layout/page-header.spec.ts b/packages/bruno-api-docs/e2e/tests/layout/page-header.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/layout/page-header.spec.ts rename to packages/bruno-api-docs/e2e/tests/layout/page-header.spec.ts diff --git a/packages/oc-docs/e2e/tests/overview/overview-documentation.spec.ts b/packages/bruno-api-docs/e2e/tests/overview/overview-documentation.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/overview/overview-documentation.spec.ts rename to packages/bruno-api-docs/e2e/tests/overview/overview-documentation.spec.ts diff --git a/packages/oc-docs/e2e/tests/overview/overview.spec.ts b/packages/bruno-api-docs/e2e/tests/overview/overview.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/overview/overview.spec.ts rename to packages/bruno-api-docs/e2e/tests/overview/overview.spec.ts diff --git a/packages/oc-docs/e2e/tests/playground/dropdown-stacking.spec.ts b/packages/bruno-api-docs/e2e/tests/playground/dropdown-stacking.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/playground/dropdown-stacking.spec.ts rename to packages/bruno-api-docs/e2e/tests/playground/dropdown-stacking.spec.ts diff --git a/packages/bruno-api-docs/e2e/tests/playground/editor-fill-height.spec.ts b/packages/bruno-api-docs/e2e/tests/playground/editor-fill-height.spec.ts new file mode 100644 index 00000000..4e8e4002 --- /dev/null +++ b/packages/bruno-api-docs/e2e/tests/playground/editor-fill-height.spec.ts @@ -0,0 +1,49 @@ +import type { Locator } from '@playwright/test'; +import { test, expect } from '../../playwright'; + +// The Body / Tests / Scripts editors in the request pane opt into `fillHeight`, so they stretch to +// fill the pane and stop ~1rem above its bottom, instead of a short fixed-height box that either +// leaves a large empty area or overflows the pane. We assert the editor's bottom sits just above +// the view's bottom: a fixed-height editor in this dock would overflow (negative gap) or fall well +// short (large gap). +async function expectFillsPane(editor: Locator, view: Locator): Promise { + await expect(editor).toBeVisible(); + const gapBelow = async (): Promise => { + const e = await editor.boundingBox(); + const v = await view.boundingBox(); + if (!e || !v) return Number.NaN; + return Math.round(v.y + v.height - (e.y + e.height)); + }; + // Monaco relays out after the tab becomes active; retry until the gap settles to ~1rem. + await expect.poll(gapBelow, { message: 'editor should fill to ~1rem above the pane bottom' }).toBeLessThanOrEqual(48); + expect(await gapBelow()).toBeGreaterThanOrEqual(4); + + const editorBox = await editor.boundingBox(); + expect(editorBox!.height).toBeGreaterThan(40); +} + +test.describe('Playground request editors fill height', () => { + // A wide viewport keeps the request-pane tabs on one row (no responsive "⋯" overflow), + // so selecting Body/Tests/Scripts is a direct click rather than a flaky dropdown step. + test.use({ viewport: { width: 1600, height: 900 } }); + + test.beforeEach(async ({ playground }) => { + await playground.open('bottom'); + await playground.openRequest('echo json'); + }); + + test('body editor fills the request pane', async ({ playground }) => { + await playground.selectTab('body'); + await expectFillsPane(playground.bodyEditor.root, playground.view); + }); + + test('tests editor fills the request pane', async ({ playground }) => { + await playground.selectTab('tests'); + await expectFillsPane(playground.testsEditor.root, playground.view); + }); + + test('pre-request script editor fills the request pane', async ({ playground }) => { + await playground.selectTab('scripts'); + await expectFillsPane(playground.preRequestScriptEditor.root, playground.view); + }); +}); diff --git a/packages/oc-docs/e2e/tests/playground/env-add-variable.spec.ts b/packages/bruno-api-docs/e2e/tests/playground/env-add-variable.spec.ts similarity index 58% rename from packages/oc-docs/e2e/tests/playground/env-add-variable.spec.ts rename to packages/bruno-api-docs/e2e/tests/playground/env-add-variable.spec.ts index 50e5938d..cdaea6bc 100644 --- a/packages/oc-docs/e2e/tests/playground/env-add-variable.spec.ts +++ b/packages/bruno-api-docs/e2e/tests/playground/env-add-variable.spec.ts @@ -18,4 +18,24 @@ test.describe('Environment variables — adding rows (card view)', () => { await expect(envEditor.nameInputs.nth(before - 1)).toHaveValue('newVariable'); await expect(envEditor.valueInputs.nth(before - 1)).toHaveValue('newValue'); }); + + test('toggling a variable checkbox enables/disables its card', async ({ playground, envEditor }) => { + await playground.open('inline'); + await playground.openEnvironments(); + + const toggle = envEditor.enableToggle('host'); + const card = envEditor.cardFor('host'); + const disabled = /(^|\s)disabled(\s|$)/; + + await expect(toggle).toBeChecked(); + await expect(card).not.toHaveClass(disabled); + + await toggle.uncheck(); + await expect(toggle).not.toBeChecked(); + await expect(card).toHaveClass(disabled); + + await toggle.check(); + await expect(toggle).toBeChecked(); + await expect(card).not.toHaveClass(disabled); + }); }); diff --git a/packages/oc-docs/e2e/tests/playground/keyvalue-table.spec.ts b/packages/bruno-api-docs/e2e/tests/playground/keyvalue-table.spec.ts similarity index 84% rename from packages/oc-docs/e2e/tests/playground/keyvalue-table.spec.ts rename to packages/bruno-api-docs/e2e/tests/playground/keyvalue-table.spec.ts index ecf07b77..fa98c474 100644 --- a/packages/oc-docs/e2e/tests/playground/keyvalue-table.spec.ts +++ b/packages/bruno-api-docs/e2e/tests/playground/keyvalue-table.spec.ts @@ -56,4 +56,19 @@ test.describe('KeyValueTable — tooltips & mobile scroll', () => { await expect(error).toBeVisible(); await expect(error).toHaveAttribute('aria-label', 'Header name cannot contain spaces or newlines'); }); + + test('a named row can be enabled and disabled via its checkbox', async ({ playground }) => { + const { keyValueTable } = playground; + // The trailing blank row has no checkbox; naming a row promotes it to a real row with one. + await keyValueTable.nameInputs.last().fill('X-Custom'); + + const toggle = keyValueTable.enableToggle('X-Custom'); + await expect(toggle).toBeChecked(); + + await toggle.uncheck(); + await expect(toggle).not.toBeChecked(); + + await toggle.check(); + await expect(toggle).toBeChecked(); + }); }); diff --git a/packages/oc-docs/e2e/tests/playground/playground-examples.spec.ts b/packages/bruno-api-docs/e2e/tests/playground/playground-examples.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/playground/playground-examples.spec.ts rename to packages/bruno-api-docs/e2e/tests/playground/playground-examples.spec.ts diff --git a/packages/oc-docs/e2e/tests/playground/playground-mobile.spec.ts b/packages/bruno-api-docs/e2e/tests/playground/playground-mobile.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/playground/playground-mobile.spec.ts rename to packages/bruno-api-docs/e2e/tests/playground/playground-mobile.spec.ts diff --git a/packages/bruno-api-docs/e2e/tests/playground/playground-tabs.spec.ts b/packages/bruno-api-docs/e2e/tests/playground/playground-tabs.spec.ts new file mode 100644 index 00000000..33377ddb --- /dev/null +++ b/packages/bruno-api-docs/e2e/tests/playground/playground-tabs.spec.ts @@ -0,0 +1,15 @@ +import { test, expect } from '../../playwright'; + +test.describe('Playground request tabs — responsive overflow', () => { + test.use({ viewport: { width: 900, height: 800 } }); + + test('collapses overflowing tabs into a ⋯ dropdown and selects from it', async ({ page, playground }) => { + await playground.open('bottom'); + await playground.openRequest('get users'); + + await expect(page.getByTestId('tabs-more')).toBeVisible(); + + await playground.selectTab('tests'); + await expect(page.getByTestId('tabs-tab-tests')).toHaveAttribute('aria-selected', 'true'); + }); +}); diff --git a/packages/oc-docs/e2e/tests/playground/playground.spec.ts b/packages/bruno-api-docs/e2e/tests/playground/playground.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/playground/playground.spec.ts rename to packages/bruno-api-docs/e2e/tests/playground/playground.spec.ts diff --git a/packages/oc-docs/e2e/tests/playground/request-body.spec.ts b/packages/bruno-api-docs/e2e/tests/playground/request-body.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/playground/request-body.spec.ts rename to packages/bruno-api-docs/e2e/tests/playground/request-body.spec.ts diff --git a/packages/oc-docs/e2e/tests/playground/unsupported-request.spec.ts b/packages/bruno-api-docs/e2e/tests/playground/unsupported-request.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/playground/unsupported-request.spec.ts rename to packages/bruno-api-docs/e2e/tests/playground/unsupported-request.spec.ts diff --git a/packages/oc-docs/e2e/tests/request/request-details.spec.ts b/packages/bruno-api-docs/e2e/tests/request/request-details.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/request/request-details.spec.ts rename to packages/bruno-api-docs/e2e/tests/request/request-details.spec.ts diff --git a/packages/oc-docs/e2e/tests/request/request-examples.spec.ts b/packages/bruno-api-docs/e2e/tests/request/request-examples.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/request/request-examples.spec.ts rename to packages/bruno-api-docs/e2e/tests/request/request-examples.spec.ts diff --git a/packages/oc-docs/e2e/tests/request/request-execution-context.spec.ts b/packages/bruno-api-docs/e2e/tests/request/request-execution-context.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/request/request-execution-context.spec.ts rename to packages/bruno-api-docs/e2e/tests/request/request-execution-context.spec.ts diff --git a/packages/oc-docs/e2e/tests/request/unsupported-request.spec.ts b/packages/bruno-api-docs/e2e/tests/request/unsupported-request.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/request/unsupported-request.spec.ts rename to packages/bruno-api-docs/e2e/tests/request/unsupported-request.spec.ts diff --git a/packages/oc-docs/e2e/tests/routing/routing.spec.ts b/packages/bruno-api-docs/e2e/tests/routing/routing.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/routing/routing.spec.ts rename to packages/bruno-api-docs/e2e/tests/routing/routing.spec.ts diff --git a/packages/oc-docs/e2e/tests/script/script.spec.ts b/packages/bruno-api-docs/e2e/tests/script/script.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/script/script.spec.ts rename to packages/bruno-api-docs/e2e/tests/script/script.spec.ts diff --git a/packages/oc-docs/e2e/tests/scripts/code-editor-copy.spec.ts b/packages/bruno-api-docs/e2e/tests/scripts/code-editor-copy.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/scripts/code-editor-copy.spec.ts rename to packages/bruno-api-docs/e2e/tests/scripts/code-editor-copy.spec.ts diff --git a/packages/oc-docs/e2e/tests/scripts/scripts-autocomplete.spec.ts b/packages/bruno-api-docs/e2e/tests/scripts/scripts-autocomplete.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/scripts/scripts-autocomplete.spec.ts rename to packages/bruno-api-docs/e2e/tests/scripts/scripts-autocomplete.spec.ts diff --git a/packages/oc-docs/e2e/tests/search/search.spec.ts b/packages/bruno-api-docs/e2e/tests/search/search.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/search/search.spec.ts rename to packages/bruno-api-docs/e2e/tests/search/search.spec.ts diff --git a/packages/oc-docs/e2e/tests/sidebar/sidebar-examples.spec.ts b/packages/bruno-api-docs/e2e/tests/sidebar/sidebar-examples.spec.ts similarity index 91% rename from packages/oc-docs/e2e/tests/sidebar/sidebar-examples.spec.ts rename to packages/bruno-api-docs/e2e/tests/sidebar/sidebar-examples.spec.ts index 107981d8..805602de 100644 --- a/packages/oc-docs/e2e/tests/sidebar/sidebar-examples.spec.ts +++ b/packages/bruno-api-docs/e2e/tests/sidebar/sidebar-examples.spec.ts @@ -84,11 +84,4 @@ test.describe('Sidebar - Examples (docs)', () => { await expect(requestPage.examples.activeCard).toHaveCount(0); }); - test('Try on an example opens the playground on that example, deep-linked', async ({ requestPage, playground, page }) => { - await requestPage.examples.try(OK_EXAMPLE); - - await expect(playground.exampleView).toBeVisible(); - await expect(page).toHaveURL(new RegExp(`[?&]pgEx=${OK_EXAMPLE_SLUG}(?:&|$)`)); - await expect(playground.exampleViewControls).toHaveCount(0); - }); }); diff --git a/packages/bruno-api-docs/e2e/tests/sidebar/sidebar-resize.spec.ts b/packages/bruno-api-docs/e2e/tests/sidebar/sidebar-resize.spec.ts new file mode 100644 index 00000000..fef3b84a --- /dev/null +++ b/packages/bruno-api-docs/e2e/tests/sidebar/sidebar-resize.spec.ts @@ -0,0 +1,109 @@ +import { test, expect } from '../../playwright'; + +const FOLDERS = '/?fixture=folders'; +const DESKTOP = { width: 1280, height: 900 }; + +// The resize handle sits at the sidebar's right edge (left: var(--sidebar-width), +// default 260px), and the drag is delta-based from where it is grabbed, so moving +// the pointer to an absolute x lands the width near that x. Collapse fires when the +// pointer is dragged ~100px past the 200px min (i.e. below x=100); re-expand fires +// once it climbs back to the min (x>=200) within the same held gesture. + +test.describe('docs sidebar - resize (desktop)', () => { + test.use({ viewport: DESKTOP }); + + test('widens when the handle is dragged right', async ({ page, sidebar }) => { + await page.goto(FOLDERS); + await expect(sidebar.inline).toBeVisible(); + const before = await sidebar.width(); + + await sidebar.grabResizer(); + await sidebar.movePointerToX(400); + await sidebar.releasePointer(); + + const after = await sidebar.width(); + expect(after).toBeGreaterThan(before); + expect(after).toBeGreaterThan(360); + }); + + test('clamps to the max width (480px)', async ({ page, sidebar }) => { + await page.goto(FOLDERS); + await sidebar.grabResizer(); + await sidebar.movePointerToX(900); + await sidebar.releasePointer(); + + const after = await sidebar.width(); + expect(after).toBeGreaterThan(470); + expect(after).toBeLessThanOrEqual(482); + }); + + test('persists the resized width across a reload (sessionStorage)', async ({ page, sidebar }) => { + await page.goto(FOLDERS); + await sidebar.grabResizer(); + await sidebar.movePointerToX(380); + await sidebar.releasePointer(); + const resized = await sidebar.width(); + expect(resized).toBeGreaterThan(360); + + await page.reload(); + await expect(sidebar.inline).toBeVisible(); + expect(Math.abs((await sidebar.width()) - resized)).toBeLessThan(5); + }); + + test('collapses when dragged past the min, and can be re-opened', async ({ page, sidebar }) => { + await page.goto(FOLDERS); + await sidebar.grabResizer(); + await sidebar.movePointerToX(60); + await sidebar.releasePointer(); + + await expect(sidebar.inline).toHaveCount(0); + await expect(sidebar.expandButton).toBeVisible(); + + await sidebar.expand(); + await expect(sidebar.inline).toBeVisible(); + }); + + test('re-expands within the same held drag after collapsing', async ({ page, sidebar }) => { + await page.goto(FOLDERS); + await sidebar.grabResizer(); + + await sidebar.movePointerToX(60); + await expect(sidebar.inline).toHaveCount(0); + + await sidebar.movePointerToX(320); + await expect(sidebar.inline).toBeVisible(); + + await sidebar.releasePointer(); + await expect(sidebar.inline).toBeVisible(); + }); +}); + +test.describe('playground sidebar - resize (bottom dock)', () => { + test.use({ viewport: DESKTOP }); + + test('widens when the handle is dragged right', async ({ playground }) => { + await playground.open('bottom'); + await expect(playground.sidebarPanel).toBeVisible(); + const before = await playground.sidebarWidth(); + + await playground.grabSidebarResizer(); + await playground.movePointerToX(400); + await playground.releasePointer(); + + expect(await playground.sidebarWidth()).toBeGreaterThan(before); + }); + + test('collapses when dragged past the min, and re-opens from the toggle', async ({ playground }) => { + await playground.open('bottom'); + await expect(playground.sidebarPanel).toBeVisible(); + + await playground.grabSidebarResizer(); + await playground.movePointerToX(60); + await playground.releasePointer(); + + await expect(playground.sidebarPanel).toHaveCount(0); + + await playground.sidebarToggle.click(); + await expect(playground.sidebarPanel).toBeVisible(); + }); +}); diff --git a/packages/oc-docs/e2e/tests/sidebar/sidebar.spec.ts b/packages/bruno-api-docs/e2e/tests/sidebar/sidebar.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/sidebar/sidebar.spec.ts rename to packages/bruno-api-docs/e2e/tests/sidebar/sidebar.spec.ts diff --git a/packages/oc-docs/e2e/tests/theming/theme-toggle.spec.ts b/packages/bruno-api-docs/e2e/tests/theming/theme-toggle.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/theming/theme-toggle.spec.ts rename to packages/bruno-api-docs/e2e/tests/theming/theme-toggle.spec.ts diff --git a/packages/oc-docs/e2e/tests/tooltip/truncation-tooltip.spec.ts b/packages/bruno-api-docs/e2e/tests/tooltip/truncation-tooltip.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/tooltip/truncation-tooltip.spec.ts rename to packages/bruno-api-docs/e2e/tests/tooltip/truncation-tooltip.spec.ts diff --git a/packages/oc-docs/e2e/tests/variableInfoPopup/variableInfoPopup.spec.ts b/packages/bruno-api-docs/e2e/tests/variableInfoPopup/variableInfoPopup.spec.ts similarity index 100% rename from packages/oc-docs/e2e/tests/variableInfoPopup/variableInfoPopup.spec.ts rename to packages/bruno-api-docs/e2e/tests/variableInfoPopup/variableInfoPopup.spec.ts diff --git a/packages/oc-docs/e2e/tsconfig.json b/packages/bruno-api-docs/e2e/tsconfig.json similarity index 100% rename from packages/oc-docs/e2e/tsconfig.json rename to packages/bruno-api-docs/e2e/tsconfig.json diff --git a/packages/oc-docs/eslint.config.js b/packages/bruno-api-docs/eslint.config.js similarity index 100% rename from packages/oc-docs/eslint.config.js rename to packages/bruno-api-docs/eslint.config.js diff --git a/packages/oc-docs/index.html b/packages/bruno-api-docs/index.html similarity index 100% rename from packages/oc-docs/index.html rename to packages/bruno-api-docs/index.html diff --git a/packages/oc-docs/package.json b/packages/bruno-api-docs/package.json similarity index 100% rename from packages/oc-docs/package.json rename to packages/bruno-api-docs/package.json diff --git a/packages/oc-docs/playwright.config.ts b/packages/bruno-api-docs/playwright.config.ts similarity index 100% rename from packages/oc-docs/playwright.config.ts rename to packages/bruno-api-docs/playwright.config.ts diff --git a/packages/oc-docs/postcss.config.cjs b/packages/bruno-api-docs/postcss.config.cjs similarity index 100% rename from packages/oc-docs/postcss.config.cjs rename to packages/bruno-api-docs/postcss.config.cjs diff --git a/packages/oc-docs/scripts/generate-theme-css.ts b/packages/bruno-api-docs/scripts/generate-theme-css.ts similarity index 100% rename from packages/oc-docs/scripts/generate-theme-css.ts rename to packages/bruno-api-docs/scripts/generate-theme-css.ts diff --git a/packages/oc-docs/src/assets/icons/BookIcon.tsx b/packages/bruno-api-docs/src/assets/icons/BookIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/BookIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/BookIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/BrunoGlyph.tsx b/packages/bruno-api-docs/src/assets/icons/BrunoGlyph.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/BrunoGlyph.tsx rename to packages/bruno-api-docs/src/assets/icons/BrunoGlyph.tsx diff --git a/packages/oc-docs/src/assets/icons/CaretIcon.tsx b/packages/bruno-api-docs/src/assets/icons/CaretIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/CaretIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/CaretIcon.tsx diff --git a/packages/bruno-api-docs/src/assets/icons/CheckIcon.tsx b/packages/bruno-api-docs/src/assets/icons/CheckIcon.tsx new file mode 100644 index 00000000..20bad838 --- /dev/null +++ b/packages/bruno-api-docs/src/assets/icons/CheckIcon.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { baseIconProps } from './baseIconProps'; + +interface CheckIconProps { + className?: string; + width?: number; + height?: number; +} + +export const CheckIcon: React.FC = ({ className, width=24, height=24 }) => ( + + + +); diff --git a/packages/oc-docs/src/assets/icons/ChevronDownIcon.tsx b/packages/bruno-api-docs/src/assets/icons/ChevronDownIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/ChevronDownIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/ChevronDownIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/ChevronLeftIcon.tsx b/packages/bruno-api-docs/src/assets/icons/ChevronLeftIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/ChevronLeftIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/ChevronLeftIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/ChevronRightIcon.tsx b/packages/bruno-api-docs/src/assets/icons/ChevronRightIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/ChevronRightIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/ChevronRightIcon.tsx diff --git a/packages/bruno-api-docs/src/assets/icons/ChevronsRightIcon.tsx b/packages/bruno-api-docs/src/assets/icons/ChevronsRightIcon.tsx new file mode 100644 index 00000000..44630e24 --- /dev/null +++ b/packages/bruno-api-docs/src/assets/icons/ChevronsRightIcon.tsx @@ -0,0 +1,22 @@ +import React from 'react'; + +export const ChevronsRightIcon: React.FC<{ size?: number }> = ({ size = 18 }) => ( + +); + +export default ChevronsRightIcon; diff --git a/packages/oc-docs/src/assets/icons/CloseIcon.tsx b/packages/bruno-api-docs/src/assets/icons/CloseIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/CloseIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/CloseIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/CubeIcon.tsx b/packages/bruno-api-docs/src/assets/icons/CubeIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/CubeIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/CubeIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/DockBottomIcon.tsx b/packages/bruno-api-docs/src/assets/icons/DockBottomIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/DockBottomIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/DockBottomIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/DockInlineIcon.tsx b/packages/bruno-api-docs/src/assets/icons/DockInlineIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/DockInlineIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/DockInlineIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/DockModalIcon.tsx b/packages/bruno-api-docs/src/assets/icons/DockModalIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/DockModalIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/DockModalIcon.tsx diff --git a/packages/bruno-api-docs/src/assets/icons/DotIcon.tsx b/packages/bruno-api-docs/src/assets/icons/DotIcon.tsx new file mode 100644 index 00000000..9eab4afb --- /dev/null +++ b/packages/bruno-api-docs/src/assets/icons/DotIcon.tsx @@ -0,0 +1,26 @@ +import React from 'react'; + +export const DotIcon: React.FC<{ width?: number | string }> = ({ width = 10 }) => ( + +); + +export default DotIcon; diff --git a/packages/oc-docs/src/assets/icons/ExampleIcon.spec.tsx b/packages/bruno-api-docs/src/assets/icons/ExampleIcon.spec.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/ExampleIcon.spec.tsx rename to packages/bruno-api-docs/src/assets/icons/ExampleIcon.spec.tsx diff --git a/packages/oc-docs/src/assets/icons/ExampleIcon.tsx b/packages/bruno-api-docs/src/assets/icons/ExampleIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/ExampleIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/ExampleIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/ExpandIcon.tsx b/packages/bruno-api-docs/src/assets/icons/ExpandIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/ExpandIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/ExpandIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/EyeIcon.tsx b/packages/bruno-api-docs/src/assets/icons/EyeIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/EyeIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/EyeIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/EyeOffIcon.tsx b/packages/bruno-api-docs/src/assets/icons/EyeOffIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/EyeOffIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/EyeOffIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/FileIcon.tsx b/packages/bruno-api-docs/src/assets/icons/FileIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/FileIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/FileIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/FileNotFoundIcon.tsx b/packages/bruno-api-docs/src/assets/icons/FileNotFoundIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/FileNotFoundIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/FileNotFoundIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/FolderIcon.tsx b/packages/bruno-api-docs/src/assets/icons/FolderIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/FolderIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/FolderIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/GlobeIcon.tsx b/packages/bruno-api-docs/src/assets/icons/GlobeIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/GlobeIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/GlobeIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/HamburgerIcon.tsx b/packages/bruno-api-docs/src/assets/icons/HamburgerIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/HamburgerIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/HamburgerIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/OverflowIcon.tsx b/packages/bruno-api-docs/src/assets/icons/OverflowIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/OverflowIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/OverflowIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/PlayIcon.tsx b/packages/bruno-api-docs/src/assets/icons/PlayIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/PlayIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/PlayIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/RefreshIcon.tsx b/packages/bruno-api-docs/src/assets/icons/RefreshIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/RefreshIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/RefreshIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/SearchIcon.tsx b/packages/bruno-api-docs/src/assets/icons/SearchIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/SearchIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/SearchIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/SendIcon.tsx b/packages/bruno-api-docs/src/assets/icons/SendIcon.tsx similarity index 53% rename from packages/oc-docs/src/assets/icons/SendIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/SendIcon.tsx index 19a6b4dd..739e5c5d 100644 --- a/packages/oc-docs/src/assets/icons/SendIcon.tsx +++ b/packages/bruno-api-docs/src/assets/icons/SendIcon.tsx @@ -1,9 +1,14 @@ import React from 'react'; import { baseIconProps } from './baseIconProps'; +interface SendIconProps { + width?: number; + height?: number; +} + /** Paper-plane "send" icon used by the Try action. */ -export const SendIcon: React.FC = () => ( - +export const SendIcon: React.FC = ({ width = 11, height = 11 }) => ( + diff --git a/packages/oc-docs/src/assets/icons/SettingsIcon.tsx b/packages/bruno-api-docs/src/assets/icons/SettingsIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/SettingsIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/SettingsIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/SidebarToggleIcon.tsx b/packages/bruno-api-docs/src/assets/icons/SidebarToggleIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/SidebarToggleIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/SidebarToggleIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/TrashIcon.tsx b/packages/bruno-api-docs/src/assets/icons/TrashIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/TrashIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/TrashIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/WarningIcon.tsx b/packages/bruno-api-docs/src/assets/icons/WarningIcon.tsx similarity index 100% rename from packages/oc-docs/src/assets/icons/WarningIcon.tsx rename to packages/bruno-api-docs/src/assets/icons/WarningIcon.tsx diff --git a/packages/oc-docs/src/assets/icons/baseIconProps.ts b/packages/bruno-api-docs/src/assets/icons/baseIconProps.ts similarity index 100% rename from packages/oc-docs/src/assets/icons/baseIconProps.ts rename to packages/bruno-api-docs/src/assets/icons/baseIconProps.ts diff --git a/packages/oc-docs/src/assets/icons/index.ts b/packages/bruno-api-docs/src/assets/icons/index.ts similarity index 90% rename from packages/oc-docs/src/assets/icons/index.ts rename to packages/bruno-api-docs/src/assets/icons/index.ts index a54d4b20..12d225de 100644 --- a/packages/oc-docs/src/assets/icons/index.ts +++ b/packages/bruno-api-docs/src/assets/icons/index.ts @@ -27,3 +27,6 @@ export * from './SidebarToggleIcon'; export * from './SettingsIcon'; export * from './TrashIcon'; export * from './ExampleIcon'; +export * from './DotIcon'; +export * from './ChevronsRightIcon'; +export * from './CheckIcon'; diff --git a/packages/oc-docs/src/assets/opencollection-logo.svg b/packages/bruno-api-docs/src/assets/opencollection-logo.svg similarity index 100% rename from packages/oc-docs/src/assets/opencollection-logo.svg rename to packages/bruno-api-docs/src/assets/opencollection-logo.svg diff --git a/packages/oc-docs/src/assets/react.svg b/packages/bruno-api-docs/src/assets/react.svg similarity index 100% rename from packages/oc-docs/src/assets/react.svg rename to packages/bruno-api-docs/src/assets/react.svg diff --git a/packages/oc-docs/src/components/AppShell/AppShell.tsx b/packages/bruno-api-docs/src/components/AppShell/AppShell.tsx similarity index 88% rename from packages/oc-docs/src/components/AppShell/AppShell.tsx rename to packages/bruno-api-docs/src/components/AppShell/AppShell.tsx index aec675fd..398802e9 100644 --- a/packages/oc-docs/src/components/AppShell/AppShell.tsx +++ b/packages/bruno-api-docs/src/components/AppShell/AppShell.tsx @@ -11,13 +11,11 @@ import { ChevronLeftIcon, ChevronRightIcon } from '../../assets/icons'; import PageRouter from '../PageRouter/PageRouter'; import Playground from '../Playground/Playground'; import SearchBar from '../Search/SearchBar/SearchBar'; -import { useSearchHotkey, usePlaygroundUrlState, useElementWidth } from '../../hooks'; +import { useSearchHotkey, usePlaygroundUrlState, useElementWidth, useResizableSidebar } from '../../hooks'; import { useAppSelector } from '../../store/hooks'; import { selectDocsCollection } from '../../store/slices/docs'; import { selectGitCollectionUrl } from '../../store/slices/app'; import { useActiveResolution } from '../../routing/hooks'; -import { exampleSlugForIndex } from '../../routing/slug'; -import type { HttpRequest } from '@opencollection/types/requests/http'; import { layoutModeForWidth } from '../../hooks/useTopbarLayout'; import { buildFetchInBrunoUrl } from '../../utils/buildFetchInBrunoUrl'; import { StyledWrapper } from './StyledWrapper'; @@ -56,9 +54,14 @@ const AppShell: React.FC = ({ logo, testId = 'app-shell' }) => { const isDesktop = mode === 'desktop'; const [sidebarCollapsed, setSidebarCollapsed] = useState(false); const [drawerOpen, setDrawerOpen] = useState(false); + const { width: sidebarWidth, dragging: sidebarDragging, startDrag: startSidebarResize } = useResizableSidebar( + 'oc-docs:docsSidebarWidth', + () => setSidebarCollapsed(true), + () => setSidebarCollapsed(false) + ); const { pathname } = useLocation(); - const { open: playgroundOpen, dock: playgroundDock, openPlayground, setRequestExample } = usePlaygroundUrlState(); + const { open: playgroundOpen, dock: playgroundDock, openPlayground } = usePlaygroundUrlState(); // Bumped on every Try click so the bottom sheet re-expands from collapsed even // when the requested slug is unchanged (a slug change alone wouldn't signal it). const [playgroundOpenNonce, setPlaygroundOpenNonce] = useState(0); @@ -89,22 +92,17 @@ const AppShell: React.FC = ({ logo, testId = 'app-shell' }) => { setPlaygroundOpenNonce((nonce) => nonce + 1); }, [openPlayground, resolution]); - // Open the playground on a specific example of the current request (its Try - // action): pgReq keeps the request, pgEx the example, so a share/reload lands - // on the same read-only example view. - const handleTryExample = (index: number) => { - const entry = resolution?.entry; - if (!entry) return; - setRequestExample(entry.slug, exampleSlugForIndex(entry.item as HttpRequest | null, index)); - }; - return ( -
+
= ({ logo, testId = 'app-shell' }) => { +
= ({ logo, testId = 'app-shell' }) => { )}
- +
diff --git a/packages/oc-docs/src/components/AppShell/StyledWrapper.ts b/packages/bruno-api-docs/src/components/AppShell/StyledWrapper.ts similarity index 78% rename from packages/oc-docs/src/components/AppShell/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/AppShell/StyledWrapper.ts index a7c7d333..f53b8815 100644 --- a/packages/oc-docs/src/components/AppShell/StyledWrapper.ts +++ b/packages/bruno-api-docs/src/components/AppShell/StyledWrapper.ts @@ -44,6 +44,35 @@ export const StyledWrapper = styled.div` background-color: var(--oc-background-base); } + .appshell-sidebar-resizer { + position: absolute; + top: 0; + bottom: 0; + left: var(--sidebar-width); + width: 0.5625rem; + transform: translateX(-0.25rem); + z-index: calc(var(--z-sidebar, 5) + 1); + cursor: col-resize; + touch-action: none; + } + + .appshell-sidebar-resizer::before { + content: ''; + position: absolute; + top: 0; + bottom: 0; + left: 50%; + width: 0.0625rem; + transform: translateX(-50%); + background-color: transparent; + } + + .appshell-sidebar-resizer:hover::before, + .appshell-sidebar-resizer[data-dragging='true']::before { + width: 0.125rem; + background-color: var(--oc-border-border2); + } + .appshell-content { flex: 1; min-width: 0; diff --git a/packages/oc-docs/src/components/AuthDetails/AuthDetails.spec.tsx b/packages/bruno-api-docs/src/components/AuthDetails/AuthDetails.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/AuthDetails/AuthDetails.spec.tsx rename to packages/bruno-api-docs/src/components/AuthDetails/AuthDetails.spec.tsx diff --git a/packages/oc-docs/src/components/AuthDetails/AuthDetails.tsx b/packages/bruno-api-docs/src/components/AuthDetails/AuthDetails.tsx similarity index 100% rename from packages/oc-docs/src/components/AuthDetails/AuthDetails.tsx rename to packages/bruno-api-docs/src/components/AuthDetails/AuthDetails.tsx diff --git a/packages/oc-docs/src/components/ChevronArrow/ChevronArrow.tsx b/packages/bruno-api-docs/src/components/ChevronArrow/ChevronArrow.tsx similarity index 100% rename from packages/oc-docs/src/components/ChevronArrow/ChevronArrow.tsx rename to packages/bruno-api-docs/src/components/ChevronArrow/ChevronArrow.tsx diff --git a/packages/oc-docs/src/components/ChevronArrow/StyledWrapper.ts b/packages/bruno-api-docs/src/components/ChevronArrow/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/ChevronArrow/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/ChevronArrow/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/Code/Code.spec.tsx b/packages/bruno-api-docs/src/components/Code/Code.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/Code/Code.spec.tsx rename to packages/bruno-api-docs/src/components/Code/Code.spec.tsx diff --git a/packages/oc-docs/src/components/Code/Code.tsx b/packages/bruno-api-docs/src/components/Code/Code.tsx similarity index 100% rename from packages/oc-docs/src/components/Code/Code.tsx rename to packages/bruno-api-docs/src/components/Code/Code.tsx diff --git a/packages/oc-docs/src/components/Code/CodeViewer/CodeViewer.tsx b/packages/bruno-api-docs/src/components/Code/CodeViewer/CodeViewer.tsx similarity index 100% rename from packages/oc-docs/src/components/Code/CodeViewer/CodeViewer.tsx rename to packages/bruno-api-docs/src/components/Code/CodeViewer/CodeViewer.tsx diff --git a/packages/oc-docs/src/components/Code/CodeViewer/StyledWrapper.ts b/packages/bruno-api-docs/src/components/Code/CodeViewer/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/Code/CodeViewer/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/Code/CodeViewer/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/Code/HighlightedCode.spec.tsx b/packages/bruno-api-docs/src/components/Code/HighlightedCode.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/Code/HighlightedCode.spec.tsx rename to packages/bruno-api-docs/src/components/Code/HighlightedCode.spec.tsx diff --git a/packages/oc-docs/src/components/Code/HighlightedCode.tsx b/packages/bruno-api-docs/src/components/Code/HighlightedCode.tsx similarity index 100% rename from packages/oc-docs/src/components/Code/HighlightedCode.tsx rename to packages/bruno-api-docs/src/components/Code/HighlightedCode.tsx diff --git a/packages/oc-docs/src/components/CodeSnippetTabs/CodeSnippetTabs.spec.tsx b/packages/bruno-api-docs/src/components/CodeSnippetTabs/CodeSnippetTabs.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/CodeSnippetTabs/CodeSnippetTabs.spec.tsx rename to packages/bruno-api-docs/src/components/CodeSnippetTabs/CodeSnippetTabs.spec.tsx diff --git a/packages/oc-docs/src/components/CodeSnippetTabs/CodeSnippetTabs.tsx b/packages/bruno-api-docs/src/components/CodeSnippetTabs/CodeSnippetTabs.tsx similarity index 100% rename from packages/oc-docs/src/components/CodeSnippetTabs/CodeSnippetTabs.tsx rename to packages/bruno-api-docs/src/components/CodeSnippetTabs/CodeSnippetTabs.tsx diff --git a/packages/oc-docs/src/components/CodeSnippetTabs/StyledWrapper.ts b/packages/bruno-api-docs/src/components/CodeSnippetTabs/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/CodeSnippetTabs/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/CodeSnippetTabs/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/CollectionStats/CollectionStats.spec.tsx b/packages/bruno-api-docs/src/components/CollectionStats/CollectionStats.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/CollectionStats/CollectionStats.spec.tsx rename to packages/bruno-api-docs/src/components/CollectionStats/CollectionStats.spec.tsx diff --git a/packages/oc-docs/src/components/CollectionStats/CollectionStats.tsx b/packages/bruno-api-docs/src/components/CollectionStats/CollectionStats.tsx similarity index 100% rename from packages/oc-docs/src/components/CollectionStats/CollectionStats.tsx rename to packages/bruno-api-docs/src/components/CollectionStats/CollectionStats.tsx diff --git a/packages/oc-docs/src/components/CollectionStats/Stat/Stat.spec.tsx b/packages/bruno-api-docs/src/components/CollectionStats/Stat/Stat.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/CollectionStats/Stat/Stat.spec.tsx rename to packages/bruno-api-docs/src/components/CollectionStats/Stat/Stat.spec.tsx diff --git a/packages/oc-docs/src/components/CollectionStats/Stat/Stat.tsx b/packages/bruno-api-docs/src/components/CollectionStats/Stat/Stat.tsx similarity index 100% rename from packages/oc-docs/src/components/CollectionStats/Stat/Stat.tsx rename to packages/bruno-api-docs/src/components/CollectionStats/Stat/Stat.tsx diff --git a/packages/oc-docs/src/components/CollectionStats/Stat/StyledWrapper.ts b/packages/bruno-api-docs/src/components/CollectionStats/Stat/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/CollectionStats/Stat/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/CollectionStats/Stat/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/CollectionStats/StyledWrapper.ts b/packages/bruno-api-docs/src/components/CollectionStats/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/CollectionStats/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/CollectionStats/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/ContentTypeBadge/ContentTypeBadge.spec.tsx b/packages/bruno-api-docs/src/components/ContentTypeBadge/ContentTypeBadge.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/ContentTypeBadge/ContentTypeBadge.spec.tsx rename to packages/bruno-api-docs/src/components/ContentTypeBadge/ContentTypeBadge.spec.tsx diff --git a/packages/oc-docs/src/components/ContentTypeBadge/ContentTypeBadge.tsx b/packages/bruno-api-docs/src/components/ContentTypeBadge/ContentTypeBadge.tsx similarity index 100% rename from packages/oc-docs/src/components/ContentTypeBadge/ContentTypeBadge.tsx rename to packages/bruno-api-docs/src/components/ContentTypeBadge/ContentTypeBadge.tsx diff --git a/packages/oc-docs/src/components/ContentTypeBadge/StyledWrapper.ts b/packages/bruno-api-docs/src/components/ContentTypeBadge/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/ContentTypeBadge/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/ContentTypeBadge/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/Description/Description.spec.tsx b/packages/bruno-api-docs/src/components/Description/Description.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/Description/Description.spec.tsx rename to packages/bruno-api-docs/src/components/Description/Description.spec.tsx diff --git a/packages/oc-docs/src/components/Description/Description.tsx b/packages/bruno-api-docs/src/components/Description/Description.tsx similarity index 100% rename from packages/oc-docs/src/components/Description/Description.tsx rename to packages/bruno-api-docs/src/components/Description/Description.tsx diff --git a/packages/oc-docs/src/components/Description/StyledWrapper.ts b/packages/bruno-api-docs/src/components/Description/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/Description/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/Description/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/DisabledBadge/DisabledBadge.spec.tsx b/packages/bruno-api-docs/src/components/DisabledBadge/DisabledBadge.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/DisabledBadge/DisabledBadge.spec.tsx rename to packages/bruno-api-docs/src/components/DisabledBadge/DisabledBadge.spec.tsx diff --git a/packages/oc-docs/src/components/DisabledBadge/DisabledBadge.tsx b/packages/bruno-api-docs/src/components/DisabledBadge/DisabledBadge.tsx similarity index 100% rename from packages/oc-docs/src/components/DisabledBadge/DisabledBadge.tsx rename to packages/bruno-api-docs/src/components/DisabledBadge/DisabledBadge.tsx diff --git a/packages/oc-docs/src/components/DisabledBadge/StyledWrapper.ts b/packages/bruno-api-docs/src/components/DisabledBadge/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/DisabledBadge/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/DisabledBadge/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/Docs/Method/Method.tsx b/packages/bruno-api-docs/src/components/Docs/Method/Method.tsx similarity index 100% rename from packages/oc-docs/src/components/Docs/Method/Method.tsx rename to packages/bruno-api-docs/src/components/Docs/Method/Method.tsx diff --git a/packages/oc-docs/src/components/Docs/Method/StyledWrapper.ts b/packages/bruno-api-docs/src/components/Docs/Method/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/Docs/Method/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/Docs/Method/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/Docs/Sidebar/Sidebar.spec.tsx b/packages/bruno-api-docs/src/components/Docs/Sidebar/Sidebar.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/Docs/Sidebar/Sidebar.spec.tsx rename to packages/bruno-api-docs/src/components/Docs/Sidebar/Sidebar.spec.tsx diff --git a/packages/oc-docs/src/components/Docs/Sidebar/Sidebar.tsx b/packages/bruno-api-docs/src/components/Docs/Sidebar/Sidebar.tsx similarity index 100% rename from packages/oc-docs/src/components/Docs/Sidebar/Sidebar.tsx rename to packages/bruno-api-docs/src/components/Docs/Sidebar/Sidebar.tsx diff --git a/packages/oc-docs/src/components/Docs/Sidebar/SidebarNavLink/SidebarNavLink.spec.tsx b/packages/bruno-api-docs/src/components/Docs/Sidebar/SidebarNavLink/SidebarNavLink.spec.tsx similarity index 84% rename from packages/oc-docs/src/components/Docs/Sidebar/SidebarNavLink/SidebarNavLink.spec.tsx rename to packages/bruno-api-docs/src/components/Docs/Sidebar/SidebarNavLink/SidebarNavLink.spec.tsx index 0363a937..1b4f0021 100644 --- a/packages/oc-docs/src/components/Docs/Sidebar/SidebarNavLink/SidebarNavLink.spec.tsx +++ b/packages/bruno-api-docs/src/components/Docs/Sidebar/SidebarNavLink/SidebarNavLink.spec.tsx @@ -52,11 +52,12 @@ describe('SidebarNavLink', () => { expect(html).not.toContain('navlink-label mono'); }); - it('indents by level via margin (chevron + gap step of 19px) with a 4px inner pad', () => { + it('indents by level via margin (one 19px chevron+gap step per level) with a uniform 8px inner pad', () => { const html = renderToStaticMarkup(); - // level*19 + 4 = 42px -> 42/16 = 2.625rem margin; the fixed 4px (0.25rem) pad - // restores the level*19+8 glyph offset. - expect(html).toContain('margin-left:2.625rem'); - expect(html).toContain('padding-left:0.25rem'); + // Each level is one 19px chevron+gap step: level*19 = 38px -> 38/16 = 2.375rem margin. + // The 8px (0.5rem) pad is uniform across folders and leaves so glyphs line up + // under their parent. + expect(html).toContain('margin-left:2.375rem'); + expect(html).toContain('padding-left:0.5rem'); }); }); diff --git a/packages/oc-docs/src/components/Docs/Sidebar/SidebarNavLink/SidebarNavLink.tsx b/packages/bruno-api-docs/src/components/Docs/Sidebar/SidebarNavLink/SidebarNavLink.tsx similarity index 77% rename from packages/oc-docs/src/components/Docs/Sidebar/SidebarNavLink/SidebarNavLink.tsx rename to packages/bruno-api-docs/src/components/Docs/Sidebar/SidebarNavLink/SidebarNavLink.tsx index d70e0bc2..f552b664 100644 --- a/packages/oc-docs/src/components/Docs/Sidebar/SidebarNavLink/SidebarNavLink.tsx +++ b/packages/bruno-api-docs/src/components/Docs/Sidebar/SidebarNavLink/SidebarNavLink.tsx @@ -52,13 +52,15 @@ const SidebarNavLink: React.FC = ({ return ( { - it('shows the name, status and a Try button when collapsed', () => { - const html = renderToStaticMarkup( {}} />); + it('shows the name and status when collapsed', () => { + const html = renderToStaticMarkup(); expect(html).toContain('Successful login'); expect(html).toContain('200'); - expect(html).toContain('>Try<'); expect(html).toContain('--oc-status-success-text'); expect(html).not.toContain('REQUEST'); }); @@ -43,11 +42,10 @@ describe('ExampleCard', () => { expect(html).toContain('B'); }); - it('falls back to a default name and omits Try without a handler', () => { + it('falls back to a default name when the example has none', () => { const html = renderToStaticMarkup(); expect(html).toContain('Example'); expect(html).toContain('--oc-status-danger-text'); - expect(html).not.toContain('>Try<'); }); it('colours the status badge by tone: danger for 4xx/5xx, info for 3xx redirects', () => { @@ -171,13 +169,11 @@ describe('ExampleCard', () => { }} method="post" url="/x" - onTry={() => {}} defaultExpanded /> ); expect(html).toContain('A described example'); expect(html).toContain('class="example-toggle"'); - expect(html).toContain('class="example-try"'); expect(html).toContain('aria-expanded="true"'); // WAI-ARIA tabs. expect(html).toContain('role="tablist"'); diff --git a/packages/oc-docs/src/components/Examples/ExampleCard/ExampleCard.tsx b/packages/bruno-api-docs/src/components/Examples/ExampleCard/ExampleCard.tsx similarity index 96% rename from packages/oc-docs/src/components/Examples/ExampleCard/ExampleCard.tsx rename to packages/bruno-api-docs/src/components/Examples/ExampleCard/ExampleCard.tsx index 87404e40..249b0316 100644 --- a/packages/oc-docs/src/components/Examples/ExampleCard/ExampleCard.tsx +++ b/packages/bruno-api-docs/src/components/Examples/ExampleCard/ExampleCard.tsx @@ -10,7 +10,6 @@ import { Description } from '../../Description/Description'; import { RequestParams } from '../../Request/RequestParams/RequestParams'; import { RequestBody } from '../../Request/RequestBody/RequestBody'; import { Code } from '../../Code/Code'; -import { PlayIcon } from '../../../assets/icons'; import { resolvePathAndQueryParams } from '../../../utils/pathParams'; import { getBodyView, getDescription, headerRows } from '../../../utils/request'; import { computeBodySize, formatBytes, responseBodyLanguage, responseBodyContentType, statusCodePhrase } from '../../../utils/exampleResponse'; @@ -21,7 +20,6 @@ interface ExampleCardProps { example: HttpRequestExample; method: string; url: string; - onTry?: () => void; defaultExpanded?: boolean; active?: boolean; testId?: string; @@ -165,7 +163,7 @@ const Pane: React.FC<{ ); }; -export const ExampleCard: React.FC = ({ example, method, url, onTry, defaultExpanded, active, testId = 'example-card' }) => { +export const ExampleCard: React.FC = ({ example, method, url, defaultExpanded, active, testId = 'example-card' }) => { const [expanded, setExpanded] = useState(Boolean(defaultExpanded)); const [mounted, setMounted] = useState(Boolean(defaultExpanded)); const detailId = useId(); @@ -284,12 +282,6 @@ export const ExampleCard: React.FC = ({ example, method, url, ) : undefined; - const handleTry = () => { - setMounted(true); - setExpanded(true); - onTry?.(); - }; - return ( = ({ example, method, url, ) : null} {name} - {onTry && ( - - )}
{/* Grid-rows 0fr→1fr animates the height open/close with no fixed max-height. */} diff --git a/packages/oc-docs/src/components/Examples/ExampleCard/StyledWrapper.ts b/packages/bruno-api-docs/src/components/Examples/ExampleCard/StyledWrapper.ts similarity index 91% rename from packages/oc-docs/src/components/Examples/ExampleCard/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/Examples/ExampleCard/StyledWrapper.ts index 7e326794..293e67d9 100644 --- a/packages/oc-docs/src/components/Examples/ExampleCard/StyledWrapper.ts +++ b/packages/bruno-api-docs/src/components/Examples/ExampleCard/StyledWrapper.ts @@ -79,28 +79,6 @@ export const StyledWrapper = styled.div` text-overflow: ellipsis; } - .example-try { - flex: 0 0 auto; - display: inline-flex; - align-items: center; - gap: 5px; - height: 24px; - padding: 0 9px; - box-sizing: border-box; - background: var(--brand-soft); - color: var(--primary-text); - border: 1px solid var(--primary-color); - border-radius: var(--oc-radius); - font-family: var(--font-sans); - font-size: 11.5px; - font-weight: 600; - cursor: pointer; - } - .example-try:focus-visible { - outline: 2px solid var(--primary-color); - outline-offset: 2px; - } - .example-detail { display: grid; grid-template-rows: 0fr; diff --git a/packages/oc-docs/src/components/Examples/Examples.spec.tsx b/packages/bruno-api-docs/src/components/Examples/Examples.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/Examples/Examples.spec.tsx rename to packages/bruno-api-docs/src/components/Examples/Examples.spec.tsx diff --git a/packages/oc-docs/src/components/Examples/Examples.tsx b/packages/bruno-api-docs/src/components/Examples/Examples.tsx similarity index 83% rename from packages/oc-docs/src/components/Examples/Examples.tsx rename to packages/bruno-api-docs/src/components/Examples/Examples.tsx index 033aa5ac..1ef606af 100644 --- a/packages/oc-docs/src/components/Examples/Examples.tsx +++ b/packages/bruno-api-docs/src/components/Examples/Examples.tsx @@ -7,14 +7,12 @@ interface ExamplesProps { examples?: HttpRequestExample[]; method: string; url: string; - // Open the playground on a given example (its Try action). - onTryExample?: (index: number) => void; highlightedIndex?: number; className?: string; testId?: string; } -export const Examples: React.FC = ({ examples, method, url, onTryExample, highlightedIndex, className, testId = 'request-examples' }) => { +export const Examples: React.FC = ({ examples, method, url, highlightedIndex, className, testId = 'request-examples' }) => { if (!examples || examples.length === 0) return null; // A highlight that no longer resolves (out of range) falls back to the @@ -30,7 +28,6 @@ export const Examples: React.FC = ({ examples, method, url, onTry example={example} method={method} url={url} - onTry={onTryExample ? () => onTryExample(index) : undefined} defaultExpanded={validHighlight ? highlightedIndex === index : index === 0} active={validHighlight && highlightedIndex === index} /> diff --git a/packages/oc-docs/src/components/Examples/StyledWrapper.ts b/packages/bruno-api-docs/src/components/Examples/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/Examples/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/Examples/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/ExecutionContext/AssertList/AssertList.spec.tsx b/packages/bruno-api-docs/src/components/ExecutionContext/AssertList/AssertList.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/AssertList/AssertList.spec.tsx rename to packages/bruno-api-docs/src/components/ExecutionContext/AssertList/AssertList.spec.tsx diff --git a/packages/oc-docs/src/components/ExecutionContext/AssertList/AssertList.tsx b/packages/bruno-api-docs/src/components/ExecutionContext/AssertList/AssertList.tsx similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/AssertList/AssertList.tsx rename to packages/bruno-api-docs/src/components/ExecutionContext/AssertList/AssertList.tsx diff --git a/packages/oc-docs/src/components/ExecutionContext/AssertList/StyledWrapper.ts b/packages/bruno-api-docs/src/components/ExecutionContext/AssertList/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/AssertList/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/ExecutionContext/AssertList/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/ExecutionContext/ExecutionContext.spec.tsx b/packages/bruno-api-docs/src/components/ExecutionContext/ExecutionContext.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/ExecutionContext.spec.tsx rename to packages/bruno-api-docs/src/components/ExecutionContext/ExecutionContext.spec.tsx diff --git a/packages/oc-docs/src/components/ExecutionContext/ExecutionContext.tsx b/packages/bruno-api-docs/src/components/ExecutionContext/ExecutionContext.tsx similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/ExecutionContext.tsx rename to packages/bruno-api-docs/src/components/ExecutionContext/ExecutionContext.tsx diff --git a/packages/oc-docs/src/components/ExecutionContext/ScopeTag/ScopeTag.spec.tsx b/packages/bruno-api-docs/src/components/ExecutionContext/ScopeTag/ScopeTag.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/ScopeTag/ScopeTag.spec.tsx rename to packages/bruno-api-docs/src/components/ExecutionContext/ScopeTag/ScopeTag.spec.tsx diff --git a/packages/oc-docs/src/components/ExecutionContext/ScopeTag/ScopeTag.tsx b/packages/bruno-api-docs/src/components/ExecutionContext/ScopeTag/ScopeTag.tsx similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/ScopeTag/ScopeTag.tsx rename to packages/bruno-api-docs/src/components/ExecutionContext/ScopeTag/ScopeTag.tsx diff --git a/packages/oc-docs/src/components/ExecutionContext/ScopeTag/StyledWrapper.ts b/packages/bruno-api-docs/src/components/ExecutionContext/ScopeTag/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/ScopeTag/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/ExecutionContext/ScopeTag/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/ExecutionContext/ScriptChain/ScriptChain.spec.tsx b/packages/bruno-api-docs/src/components/ExecutionContext/ScriptChain/ScriptChain.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/ScriptChain/ScriptChain.spec.tsx rename to packages/bruno-api-docs/src/components/ExecutionContext/ScriptChain/ScriptChain.spec.tsx diff --git a/packages/oc-docs/src/components/ExecutionContext/ScriptChain/ScriptChain.tsx b/packages/bruno-api-docs/src/components/ExecutionContext/ScriptChain/ScriptChain.tsx similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/ScriptChain/ScriptChain.tsx rename to packages/bruno-api-docs/src/components/ExecutionContext/ScriptChain/ScriptChain.tsx diff --git a/packages/oc-docs/src/components/ExecutionContext/ScriptChain/StyledWrapper.ts b/packages/bruno-api-docs/src/components/ExecutionContext/ScriptChain/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/ScriptChain/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/ExecutionContext/ScriptChain/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/ExecutionContext/ScriptStep/ScriptStep.spec.tsx b/packages/bruno-api-docs/src/components/ExecutionContext/ScriptStep/ScriptStep.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/ScriptStep/ScriptStep.spec.tsx rename to packages/bruno-api-docs/src/components/ExecutionContext/ScriptStep/ScriptStep.spec.tsx diff --git a/packages/oc-docs/src/components/ExecutionContext/ScriptStep/ScriptStep.tsx b/packages/bruno-api-docs/src/components/ExecutionContext/ScriptStep/ScriptStep.tsx similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/ScriptStep/ScriptStep.tsx rename to packages/bruno-api-docs/src/components/ExecutionContext/ScriptStep/ScriptStep.tsx diff --git a/packages/oc-docs/src/components/ExecutionContext/ScriptStep/StyledWrapper.ts b/packages/bruno-api-docs/src/components/ExecutionContext/ScriptStep/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/ScriptStep/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/ExecutionContext/ScriptStep/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/ExecutionContext/StyledWrapper.ts b/packages/bruno-api-docs/src/components/ExecutionContext/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/ExecutionContext/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/ExecutionContext/TestList/StyledWrapper.ts b/packages/bruno-api-docs/src/components/ExecutionContext/TestList/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/TestList/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/ExecutionContext/TestList/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/ExecutionContext/TestList/TestList.spec.tsx b/packages/bruno-api-docs/src/components/ExecutionContext/TestList/TestList.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/TestList/TestList.spec.tsx rename to packages/bruno-api-docs/src/components/ExecutionContext/TestList/TestList.spec.tsx diff --git a/packages/oc-docs/src/components/ExecutionContext/TestList/TestList.tsx b/packages/bruno-api-docs/src/components/ExecutionContext/TestList/TestList.tsx similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/TestList/TestList.tsx rename to packages/bruno-api-docs/src/components/ExecutionContext/TestList/TestList.tsx diff --git a/packages/oc-docs/src/components/ExecutionContext/VariablesPanel/StyledWrapper.ts b/packages/bruno-api-docs/src/components/ExecutionContext/VariablesPanel/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/VariablesPanel/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/ExecutionContext/VariablesPanel/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/ExecutionContext/VariablesPanel/VariablesPanel.spec.tsx b/packages/bruno-api-docs/src/components/ExecutionContext/VariablesPanel/VariablesPanel.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/VariablesPanel/VariablesPanel.spec.tsx rename to packages/bruno-api-docs/src/components/ExecutionContext/VariablesPanel/VariablesPanel.spec.tsx diff --git a/packages/oc-docs/src/components/ExecutionContext/VariablesPanel/VariablesPanel.tsx b/packages/bruno-api-docs/src/components/ExecutionContext/VariablesPanel/VariablesPanel.tsx similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/VariablesPanel/VariablesPanel.tsx rename to packages/bruno-api-docs/src/components/ExecutionContext/VariablesPanel/VariablesPanel.tsx diff --git a/packages/oc-docs/src/components/ExecutionContext/ViewAllTests/StyledWrapper.ts b/packages/bruno-api-docs/src/components/ExecutionContext/ViewAllTests/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/ViewAllTests/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/ExecutionContext/ViewAllTests/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/ExecutionContext/ViewAllTests/ViewAllTests.spec.tsx b/packages/bruno-api-docs/src/components/ExecutionContext/ViewAllTests/ViewAllTests.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/ViewAllTests/ViewAllTests.spec.tsx rename to packages/bruno-api-docs/src/components/ExecutionContext/ViewAllTests/ViewAllTests.spec.tsx diff --git a/packages/oc-docs/src/components/ExecutionContext/ViewAllTests/ViewAllTests.tsx b/packages/bruno-api-docs/src/components/ExecutionContext/ViewAllTests/ViewAllTests.tsx similarity index 100% rename from packages/oc-docs/src/components/ExecutionContext/ViewAllTests/ViewAllTests.tsx rename to packages/bruno-api-docs/src/components/ExecutionContext/ViewAllTests/ViewAllTests.tsx diff --git a/packages/oc-docs/src/components/FolderConfiguration/FolderConfiguration.spec.tsx b/packages/bruno-api-docs/src/components/FolderConfiguration/FolderConfiguration.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/FolderConfiguration/FolderConfiguration.spec.tsx rename to packages/bruno-api-docs/src/components/FolderConfiguration/FolderConfiguration.spec.tsx diff --git a/packages/oc-docs/src/components/FolderConfiguration/FolderConfiguration.tsx b/packages/bruno-api-docs/src/components/FolderConfiguration/FolderConfiguration.tsx similarity index 100% rename from packages/oc-docs/src/components/FolderConfiguration/FolderConfiguration.tsx rename to packages/bruno-api-docs/src/components/FolderConfiguration/FolderConfiguration.tsx diff --git a/packages/oc-docs/src/components/FolderConfiguration/StyledWrapper.ts b/packages/bruno-api-docs/src/components/FolderConfiguration/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/FolderConfiguration/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/FolderConfiguration/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/Heading/Heading.spec.tsx b/packages/bruno-api-docs/src/components/Heading/Heading.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/Heading/Heading.spec.tsx rename to packages/bruno-api-docs/src/components/Heading/Heading.spec.tsx diff --git a/packages/oc-docs/src/components/Heading/Heading.tsx b/packages/bruno-api-docs/src/components/Heading/Heading.tsx similarity index 100% rename from packages/oc-docs/src/components/Heading/Heading.tsx rename to packages/bruno-api-docs/src/components/Heading/Heading.tsx diff --git a/packages/oc-docs/src/components/Heading/StyledWrapper.ts b/packages/bruno-api-docs/src/components/Heading/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/Heading/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/Heading/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/HighlightedInput/HighlightedInput.spec.tsx b/packages/bruno-api-docs/src/components/HighlightedInput/HighlightedInput.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/HighlightedInput/HighlightedInput.spec.tsx rename to packages/bruno-api-docs/src/components/HighlightedInput/HighlightedInput.spec.tsx diff --git a/packages/oc-docs/src/components/HighlightedInput/HighlightedInput.tsx b/packages/bruno-api-docs/src/components/HighlightedInput/HighlightedInput.tsx similarity index 100% rename from packages/oc-docs/src/components/HighlightedInput/HighlightedInput.tsx rename to packages/bruno-api-docs/src/components/HighlightedInput/HighlightedInput.tsx diff --git a/packages/oc-docs/src/components/HighlightedInput/StyledWrapper.ts b/packages/bruno-api-docs/src/components/HighlightedInput/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/HighlightedInput/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/HighlightedInput/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/InfoTip/InfoTip.spec.tsx b/packages/bruno-api-docs/src/components/InfoTip/InfoTip.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/InfoTip/InfoTip.spec.tsx rename to packages/bruno-api-docs/src/components/InfoTip/InfoTip.spec.tsx diff --git a/packages/oc-docs/src/components/InfoTip/InfoTip.tsx b/packages/bruno-api-docs/src/components/InfoTip/InfoTip.tsx similarity index 100% rename from packages/oc-docs/src/components/InfoTip/InfoTip.tsx rename to packages/bruno-api-docs/src/components/InfoTip/InfoTip.tsx diff --git a/packages/oc-docs/src/components/InfoTip/StyledWrapper.ts b/packages/bruno-api-docs/src/components/InfoTip/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/InfoTip/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/InfoTip/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/InitialsAvatar/InitialsAvatar.spec.tsx b/packages/bruno-api-docs/src/components/InitialsAvatar/InitialsAvatar.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/InitialsAvatar/InitialsAvatar.spec.tsx rename to packages/bruno-api-docs/src/components/InitialsAvatar/InitialsAvatar.spec.tsx diff --git a/packages/oc-docs/src/components/InitialsAvatar/InitialsAvatar.tsx b/packages/bruno-api-docs/src/components/InitialsAvatar/InitialsAvatar.tsx similarity index 100% rename from packages/oc-docs/src/components/InitialsAvatar/InitialsAvatar.tsx rename to packages/bruno-api-docs/src/components/InitialsAvatar/InitialsAvatar.tsx diff --git a/packages/oc-docs/src/components/InitialsAvatar/StyledWrapper.ts b/packages/bruno-api-docs/src/components/InitialsAvatar/StyledWrapper.ts similarity index 92% rename from packages/oc-docs/src/components/InitialsAvatar/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/InitialsAvatar/StyledWrapper.ts index b3eda359..dfe28bc0 100644 --- a/packages/oc-docs/src/components/InitialsAvatar/StyledWrapper.ts +++ b/packages/bruno-api-docs/src/components/InitialsAvatar/StyledWrapper.ts @@ -9,7 +9,7 @@ export const StyledWrapper = styled.span` flex: none; border-radius: var(--oc-radius); background: linear-gradient(135deg, #d37f17 0%, #dc9741 100%); - color: #fff; + color: var(--oc-background-base); font-family: var(--font-mono); font-size: var(--oc-font-size-xs); font-weight: 700; diff --git a/packages/oc-docs/src/components/KeyValueTable/KeyValueTable.css b/packages/bruno-api-docs/src/components/KeyValueTable/KeyValueTable.css similarity index 87% rename from packages/oc-docs/src/components/KeyValueTable/KeyValueTable.css rename to packages/bruno-api-docs/src/components/KeyValueTable/KeyValueTable.css index 79c8b08c..7b7a522b 100644 --- a/packages/oc-docs/src/components/KeyValueTable/KeyValueTable.css +++ b/packages/bruno-api-docs/src/components/KeyValueTable/KeyValueTable.css @@ -109,7 +109,6 @@ .key-value-table .checkbox-slot { flex: none; display: inline-flex; - align-items: center; width: 1rem; height: 1rem; } @@ -140,26 +139,6 @@ vertical-align: middle; } -.key-value-table .checkbox-input { - appearance: none; - -webkit-appearance: none; - margin: 0; - width: 1rem; - height: 1rem; - border: 0.0625rem solid var(--oc-table-border); - border-radius: 0.1875rem; - background-color: transparent; - background-repeat: no-repeat; - background-position: center; - cursor: pointer; -} - -.key-value-table .checkbox-input:checked { - background-color: var(--primary-color); - border-color: var(--primary-color); - background-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='12'%20height='12'%20viewBox='0%200%2012%2012'%3E%3Cpath%20fill='none'%20stroke='%23fff'%20stroke-width='1.67'%20stroke-linecap='round'%20stroke-linejoin='round'%20d='M3%206.2%205%208.4%209%203.8'/%3E%3C/svg%3E"); -} - .key-value-table .text-input { width: 100%; border: 0.0625rem solid transparent; diff --git a/packages/oc-docs/src/components/KeyValueTable/KeyValueTable.tsx b/packages/bruno-api-docs/src/components/KeyValueTable/KeyValueTable.tsx similarity index 97% rename from packages/oc-docs/src/components/KeyValueTable/KeyValueTable.tsx rename to packages/bruno-api-docs/src/components/KeyValueTable/KeyValueTable.tsx index 237807e3..dea08e61 100644 --- a/packages/oc-docs/src/components/KeyValueTable/KeyValueTable.tsx +++ b/packages/bruno-api-docs/src/components/KeyValueTable/KeyValueTable.tsx @@ -6,6 +6,7 @@ import { WarningIcon } from '../../assets/icons'; import HighlightedInput from '../HighlightedInput/HighlightedInput'; import { SecretValue } from '../../ui/SecretValue/SecretValue'; import './KeyValueTable.css'; +import Checkbox from '../../ui/Checkbox/Checkbox'; export interface KeyValueRow { id: string; @@ -179,11 +180,9 @@ const KeyValueTable: React.FC = ({ {showEnabled && ( {!isLastEmptyRow && ( - updateField(index, 'enabled', e.target.checked)} /> )} diff --git a/packages/oc-docs/src/components/MethodBadge/MethodBadge.spec.tsx b/packages/bruno-api-docs/src/components/MethodBadge/MethodBadge.spec.tsx similarity index 50% rename from packages/oc-docs/src/components/MethodBadge/MethodBadge.spec.tsx rename to packages/bruno-api-docs/src/components/MethodBadge/MethodBadge.spec.tsx index 1fed42bf..81424585 100644 --- a/packages/oc-docs/src/components/MethodBadge/MethodBadge.spec.tsx +++ b/packages/bruno-api-docs/src/components/MethodBadge/MethodBadge.spec.tsx @@ -3,6 +3,12 @@ import { renderToStaticMarkup } from 'react-dom/server'; import { describe, it, expect } from 'vitest'; import { MethodBadge } from './MethodBadge'; +const badgeText = (element: React.ReactElement): string => + renderToStaticMarkup(element) + .replace(/]*>[\s\S]*?<\/style>/g, '') + .replace(/<[^>]*>/g, '') + .trim(); + describe('MethodBadge', () => { it('renders the method uppercased', () => { expect(renderToStaticMarkup()).toContain('POST'); @@ -11,4 +17,12 @@ describe('MethodBadge', () => { it('defaults to GET when no method is given', () => { expect(renderToStaticMarkup()).toContain('GET'); }); + + it('renders the abbreviated method when short is set', () => { + expect(badgeText()).toBe('DEL'); + }); + + it('keeps short methods intact when short is set', () => { + expect(badgeText()).toBe('GET'); + }); }); diff --git a/packages/bruno-api-docs/src/components/MethodBadge/MethodBadge.tsx b/packages/bruno-api-docs/src/components/MethodBadge/MethodBadge.tsx new file mode 100644 index 00000000..26aa260b --- /dev/null +++ b/packages/bruno-api-docs/src/components/MethodBadge/MethodBadge.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import cx from '../../utils/cx'; +import { getMethodColorVar } from '../../theme/methodColors'; +import { getShortMethod } from '../../utils/request'; +import { StyledWrapper } from './StyledWrapper'; + +interface MethodBadgeProps { + method: string; + className?: string; + /** Render the abbreviated method (DELETE -> DEL, OPTIONS -> OPT) for tight spaces like the query bar. */ + short?: boolean; +} + +export const MethodBadge: React.FC = ({ method, className, short = false }) => { + const resolvedMethod = method || 'GET'; + return ( + + {short ? getShortMethod(resolvedMethod) : resolvedMethod.toUpperCase()} + + ); +}; + +export default MethodBadge; diff --git a/packages/oc-docs/src/components/MethodBadge/StyledWrapper.ts b/packages/bruno-api-docs/src/components/MethodBadge/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/MethodBadge/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/MethodBadge/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/OpenCollection/OpenCollection.tsx b/packages/bruno-api-docs/src/components/OpenCollection/OpenCollection.tsx similarity index 99% rename from packages/oc-docs/src/components/OpenCollection/OpenCollection.tsx rename to packages/bruno-api-docs/src/components/OpenCollection/OpenCollection.tsx index 196d27fa..e3838111 100644 --- a/packages/oc-docs/src/components/OpenCollection/OpenCollection.tsx +++ b/packages/bruno-api-docs/src/components/OpenCollection/OpenCollection.tsx @@ -158,7 +158,7 @@ const OpenCollection: React.FC = (props) => { } return ( - + diff --git a/packages/oc-docs/src/components/OpenInBrunoButton/OpenInBrunoButton.spec.tsx b/packages/bruno-api-docs/src/components/OpenInBrunoButton/OpenInBrunoButton.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/OpenInBrunoButton/OpenInBrunoButton.spec.tsx rename to packages/bruno-api-docs/src/components/OpenInBrunoButton/OpenInBrunoButton.spec.tsx diff --git a/packages/oc-docs/src/components/OpenInBrunoButton/OpenInBrunoButton.tsx b/packages/bruno-api-docs/src/components/OpenInBrunoButton/OpenInBrunoButton.tsx similarity index 100% rename from packages/oc-docs/src/components/OpenInBrunoButton/OpenInBrunoButton.tsx rename to packages/bruno-api-docs/src/components/OpenInBrunoButton/OpenInBrunoButton.tsx diff --git a/packages/oc-docs/src/components/OpenInBrunoButton/StyledWrapper.ts b/packages/bruno-api-docs/src/components/OpenInBrunoButton/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/OpenInBrunoButton/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/OpenInBrunoButton/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/OverviewCollectionConfiguration/CollectionConfiguration.spec.tsx b/packages/bruno-api-docs/src/components/OverviewCollectionConfiguration/CollectionConfiguration.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/OverviewCollectionConfiguration/CollectionConfiguration.spec.tsx rename to packages/bruno-api-docs/src/components/OverviewCollectionConfiguration/CollectionConfiguration.spec.tsx diff --git a/packages/oc-docs/src/components/OverviewCollectionConfiguration/CollectionConfiguration.tsx b/packages/bruno-api-docs/src/components/OverviewCollectionConfiguration/CollectionConfiguration.tsx similarity index 100% rename from packages/oc-docs/src/components/OverviewCollectionConfiguration/CollectionConfiguration.tsx rename to packages/bruno-api-docs/src/components/OverviewCollectionConfiguration/CollectionConfiguration.tsx diff --git a/packages/oc-docs/src/components/OverviewCollectionConfiguration/StyledWrapper.ts b/packages/bruno-api-docs/src/components/OverviewCollectionConfiguration/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/OverviewCollectionConfiguration/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/OverviewCollectionConfiguration/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/OverviewEnvironments/EnvironmentSummary/EnvironmentSummary.spec.tsx b/packages/bruno-api-docs/src/components/OverviewEnvironments/EnvironmentSummary/EnvironmentSummary.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/OverviewEnvironments/EnvironmentSummary/EnvironmentSummary.spec.tsx rename to packages/bruno-api-docs/src/components/OverviewEnvironments/EnvironmentSummary/EnvironmentSummary.spec.tsx diff --git a/packages/oc-docs/src/components/OverviewEnvironments/EnvironmentSummary/EnvironmentSummary.tsx b/packages/bruno-api-docs/src/components/OverviewEnvironments/EnvironmentSummary/EnvironmentSummary.tsx similarity index 100% rename from packages/oc-docs/src/components/OverviewEnvironments/EnvironmentSummary/EnvironmentSummary.tsx rename to packages/bruno-api-docs/src/components/OverviewEnvironments/EnvironmentSummary/EnvironmentSummary.tsx diff --git a/packages/oc-docs/src/components/OverviewEnvironments/EnvironmentSummary/StyledWrapper.ts b/packages/bruno-api-docs/src/components/OverviewEnvironments/EnvironmentSummary/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/OverviewEnvironments/EnvironmentSummary/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/OverviewEnvironments/EnvironmentSummary/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/OverviewEnvironments/EnvironmentSummaryItem/EnvironmentSummaryItem.spec.tsx b/packages/bruno-api-docs/src/components/OverviewEnvironments/EnvironmentSummaryItem/EnvironmentSummaryItem.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/OverviewEnvironments/EnvironmentSummaryItem/EnvironmentSummaryItem.spec.tsx rename to packages/bruno-api-docs/src/components/OverviewEnvironments/EnvironmentSummaryItem/EnvironmentSummaryItem.spec.tsx diff --git a/packages/oc-docs/src/components/OverviewEnvironments/EnvironmentSummaryItem/EnvironmentSummaryItem.tsx b/packages/bruno-api-docs/src/components/OverviewEnvironments/EnvironmentSummaryItem/EnvironmentSummaryItem.tsx similarity index 100% rename from packages/oc-docs/src/components/OverviewEnvironments/EnvironmentSummaryItem/EnvironmentSummaryItem.tsx rename to packages/bruno-api-docs/src/components/OverviewEnvironments/EnvironmentSummaryItem/EnvironmentSummaryItem.tsx diff --git a/packages/oc-docs/src/components/OverviewEnvironments/EnvironmentSummaryItem/StyledWrapper.ts b/packages/bruno-api-docs/src/components/OverviewEnvironments/EnvironmentSummaryItem/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/OverviewEnvironments/EnvironmentSummaryItem/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/OverviewEnvironments/EnvironmentSummaryItem/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/PageRouter/PageRouter.tsx b/packages/bruno-api-docs/src/components/PageRouter/PageRouter.tsx similarity index 97% rename from packages/oc-docs/src/components/PageRouter/PageRouter.tsx rename to packages/bruno-api-docs/src/components/PageRouter/PageRouter.tsx index 00e111dd..79cab83e 100644 --- a/packages/oc-docs/src/components/PageRouter/PageRouter.tsx +++ b/packages/bruno-api-docs/src/components/PageRouter/PageRouter.tsx @@ -24,11 +24,10 @@ import { useDocsNavigate } from '../../hooks'; interface PageRouterProps { onOpenPlayground?: () => void; - onTryExample?: (index: number) => void; testId?: string; } -const PageRouter: React.FC = ({ onOpenPlayground, onTryExample, testId = 'page' }) => { +const PageRouter: React.FC = ({ onOpenPlayground, testId = 'page' }) => { const resolution = useActiveResolution(); const model = useNavModel(); const collection = useAppSelector(selectDocsCollection); @@ -93,7 +92,6 @@ const PageRouter: React.FC = ({ onOpenPlayground, onTryExample, onTryClick={onOpenPlayground} onBreadcrumbClick={goToUuid} highlightedExampleIndex={resolution.example?.index} - onTryExample={onTryExample} /> ) : null; diff --git a/packages/oc-docs/src/components/PageRouter/StyledWrapper.ts b/packages/bruno-api-docs/src/components/PageRouter/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/PageRouter/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/PageRouter/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/PageWrapper/PageWrapper.spec.tsx b/packages/bruno-api-docs/src/components/PageWrapper/PageWrapper.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/PageWrapper/PageWrapper.spec.tsx rename to packages/bruno-api-docs/src/components/PageWrapper/PageWrapper.spec.tsx diff --git a/packages/oc-docs/src/components/PageWrapper/PageWrapper.tsx b/packages/bruno-api-docs/src/components/PageWrapper/PageWrapper.tsx similarity index 100% rename from packages/oc-docs/src/components/PageWrapper/PageWrapper.tsx rename to packages/bruno-api-docs/src/components/PageWrapper/PageWrapper.tsx diff --git a/packages/oc-docs/src/components/PageWrapper/StyledWrapper.ts b/packages/bruno-api-docs/src/components/PageWrapper/StyledWrapper.ts similarity index 90% rename from packages/oc-docs/src/components/PageWrapper/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/PageWrapper/StyledWrapper.ts index 9983c7a1..3f25c5e0 100644 --- a/packages/oc-docs/src/components/PageWrapper/StyledWrapper.ts +++ b/packages/bruno-api-docs/src/components/PageWrapper/StyledWrapper.ts @@ -3,7 +3,7 @@ import styled from '@emotion/styled'; export const StyledWrapper = styled.div` max-width: 100rem; margin-inline: auto; - padding: 2rem 3rem; + padding: 1rem 3rem; @container docs (max-width: 768px) { padding: 0.9375rem 1.25rem; diff --git a/packages/oc-docs/src/components/Playground/Content/Views/CollectionSettingsView/CollectionSettingsView.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/CollectionSettingsView/CollectionSettingsView.tsx similarity index 96% rename from packages/oc-docs/src/components/Playground/Content/Views/CollectionSettingsView/CollectionSettingsView.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/CollectionSettingsView/CollectionSettingsView.tsx index 2357b52f..a743c5cc 100644 --- a/packages/oc-docs/src/components/Playground/Content/Views/CollectionSettingsView/CollectionSettingsView.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/CollectionSettingsView/CollectionSettingsView.tsx @@ -1,6 +1,7 @@ import React, { useState } from 'react'; import type { OpenCollection } from '@opencollection/types'; import Tabs from '../../../../../ui/Tabs/Tabs'; +import TitleLabel from '../../../../TitleLabel/TitleLabel'; import { type KeyValueRow } from '../../../../../components/KeyValueTable/KeyValueTable'; import HeadersTab from '../Common/HeadersTab/HeadersTab'; import VariablesTab from '../Common/VariablesTab/VariablesTab'; @@ -93,7 +94,6 @@ const CollectionSettings: React.FC = ({ collection }) = ) @@ -109,7 +109,6 @@ const CollectionSettings: React.FC = ({ collection }) = postResponseVars={postResponseVars} onPostResponseVarsChange={handlePostResponseVarsChange} exprHelp="You can write any valid JS Template Literal here" - title="" /> ) }, @@ -122,7 +121,6 @@ const CollectionSettings: React.FC = ({ collection }) = onAuthChange={handleAuthChange} onItemChange={handleCollectionChange} item={collection} - title="" description="Configures authentication for the entire collection. This applies to all requests using the Inherit option in the Auth tab." showInherit={false} showFullAuth={true} @@ -137,7 +135,6 @@ const CollectionSettings: React.FC = ({ collection }) = @@ -158,15 +155,14 @@ const CollectionSettings: React.FC = ({ collection }) = return ( -
-

- {collection.info?.name || 'Collection Settings'} -

+
+ {collection.info?.name || 'Collection Settings'} {version && Version {version}}
({ ...tab, content:
{tab.content}
diff --git a/packages/oc-docs/src/components/Playground/Content/Views/CollectionSettingsView/StyledWrapper.ts b/packages/bruno-api-docs/src/components/Playground/Content/Views/CollectionSettingsView/StyledWrapper.ts similarity index 79% rename from packages/oc-docs/src/components/Playground/Content/Views/CollectionSettingsView/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/Playground/Content/Views/CollectionSettingsView/StyledWrapper.ts index 7388fde8..282f49f3 100644 --- a/packages/oc-docs/src/components/Playground/Content/Views/CollectionSettingsView/StyledWrapper.ts +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/CollectionSettingsView/StyledWrapper.ts @@ -4,7 +4,7 @@ export const StyledWrapper = styled.div` height: 100%; display: flex; flex-direction: column; - padding: 0.75rem 1rem; + padding: 1.25rem 1.25rem 0; .collection-settings-header { display: flex; @@ -12,14 +12,6 @@ export const StyledWrapper = styled.div` gap: 0.5rem; } - .collection-settings-title { - color: var(--text-primary); - font-size: 0.875rem; - font-weight: 500; - line-height: 1; - letter-spacing: 0; - } - .collection-settings-version { color: var(--text-tertiary); font-size: 0.75rem; @@ -32,7 +24,6 @@ export const StyledWrapper = styled.div` flex: 1; min-height: 0; overflow-y: auto; - margin-top: 1.25rem; .tabs { gap: 1rem; diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/AssertsTab/AssertsTab.spec.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/AssertsTab/AssertsTab.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/AssertsTab/AssertsTab.spec.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/AssertsTab/AssertsTab.spec.tsx diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/AssertsTab/AssertsTab.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/AssertsTab/AssertsTab.tsx similarity index 99% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/AssertsTab/AssertsTab.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/AssertsTab/AssertsTab.tsx index c6dd415d..d3ee459b 100644 --- a/packages/oc-docs/src/components/Playground/Content/Views/Common/AssertsTab/AssertsTab.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/AssertsTab/AssertsTab.tsx @@ -104,7 +104,7 @@ interface AssertsTabProps { export const AssertsTab: React.FC = ({ assertions, onAssertionsChange, - title = 'Assertions', + title, description }) => { const assertionsData: KeyValueRow[] = (assertions || []).map((assertion, index) => ({ diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/AssertsTab/StyledWrapper.ts b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/AssertsTab/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/AssertsTab/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/AssertsTab/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/AuthTab/AuthTab.spec.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/AuthTab/AuthTab.spec.tsx similarity index 95% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/AuthTab/AuthTab.spec.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/AuthTab/AuthTab.spec.tsx index 0fa07417..f878b687 100644 --- a/packages/oc-docs/src/components/Playground/Content/Views/Common/AuthTab/AuthTab.spec.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/AuthTab/AuthTab.spec.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { renderToStaticMarkup } from 'react-dom/server'; import { parse } from 'node-html-parser'; import { describe, it, expect } from 'vitest'; -import { query } from '../../../../../../test-utils/dom'; +import { getByTestId, query } from '../../../../../../test-utils/dom'; import { AUTH_DEFAULTS, AUTH_MODE_LABELS, PLACEMENT_OPTIONS } from '../../../../../../constants'; import { AuthTab } from './AuthTab'; @@ -48,12 +48,12 @@ describe('AuthTab', () => { const { root, byTestId } = renderAuth(undefined); expect(root.querySelector('.auth-form')).toBeNull(); expect(byTestId('auth-username')).toBeNull(); - expect(query(root, '.auth-empty').text.trim()).toBe('No authentication configured.'); + expect(getByTestId(root, 'no-content-text').text.trim()).toBe('No authentication configured.'); }); it('shows an inherit note for inherited auth', () => { const { root } = renderAuth('inherit', { showInherit: true }); - expect(query(root, '.auth-empty').text.trim()).toBe('Inherits auth from parent collection.'); + expect(getByTestId(root, 'no-content-text').text.trim()).toBe('Inherits auth from parent collection.'); }); it('renders basic auth with a plain username and a masked, revealable password', () => { diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/AuthTab/AuthTab.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/AuthTab/AuthTab.tsx similarity index 92% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/AuthTab/AuthTab.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/AuthTab/AuthTab.tsx index f94abe52..d062097f 100644 --- a/packages/oc-docs/src/components/Playground/Content/Views/Common/AuthTab/AuthTab.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/AuthTab/AuthTab.tsx @@ -3,6 +3,7 @@ import { Field, type SelectOption } from '../../../../../../ui/Field'; import { AUTH_DEFAULTS, AUTH_MODE_LABELS, PLACEMENT_OPTIONS } from '../../../../../../constants'; import { REQUEST_PROTOCOL_KEYS } from '../../../../../../utils/schemaHelpers'; import { StyledWrapper } from './StyledWrapper'; +import NoContentText from '../../../../../../ui/NoContentText/NoContentText'; interface AuthTabProps { auth: any; @@ -20,7 +21,7 @@ export const AuthTab: React.FC = ({ onAuthChange, onItemChange, item, - title = 'Authentication', + title, description, showInherit = false, showFullAuth = false @@ -135,22 +136,22 @@ export const AuthTab: React.FC = ({ const renderBody = () => { if (!auth) { - return

No authentication configured.

; + return } if (auth === 'inherit') { - return

Inherits auth from parent collection.

; + return } if (showFullAuth) { return
{renderForm()}
; } - return

{title} auth is configured elsewhere.

; + return }; return ( {(Boolean(title) || Boolean(description)) && (
- {Boolean(title) && {title}} + {title && {title}} {description && {description}}
)} diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/AuthTab/StyledWrapper.ts b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/AuthTab/StyledWrapper.ts similarity index 79% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/AuthTab/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/AuthTab/StyledWrapper.ts index 48f7a6f8..b7364401 100644 --- a/packages/oc-docs/src/components/Playground/Content/Views/Common/AuthTab/StyledWrapper.ts +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/AuthTab/StyledWrapper.ts @@ -22,13 +22,6 @@ export const StyledWrapper = styled.div` gap: 1rem; } - .auth-empty { - margin: 0; - font-style: italic; - font-size: 0.8125rem; - color: var(--text-muted); - } - .auth-form { display: flex; flex-direction: column; diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/BodyModeSelector/BodyModeSelector.spec.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/BodyModeSelector/BodyModeSelector.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/BodyModeSelector/BodyModeSelector.spec.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/BodyModeSelector/BodyModeSelector.spec.tsx diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/BodyModeSelector/BodyModeSelector.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/BodyModeSelector/BodyModeSelector.tsx similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/BodyModeSelector/BodyModeSelector.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/BodyModeSelector/BodyModeSelector.tsx diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/BodyModeSelector/StyledWrapper.ts b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/BodyModeSelector/StyledWrapper.ts similarity index 84% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/BodyModeSelector/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/BodyModeSelector/StyledWrapper.ts index c2d2c1db..244548d5 100644 --- a/packages/oc-docs/src/components/Playground/Content/Views/Common/BodyModeSelector/StyledWrapper.ts +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/BodyModeSelector/StyledWrapper.ts @@ -7,12 +7,13 @@ import styled from '@emotion/styled'; export const TriggerButton = styled.button` display: inline-flex; align-items: center; - padding: 0.25rem 0; + padding: 0 0 0.25rem; background: transparent; border: none; font-family: inherit; - font-size: 0.875rem; - font-weight: 500; + font-size: 0.75rem; + line-height: 1.125rem; + letter-spacing: 0; color: var(--oc-primary-text); cursor: pointer; user-select: none; diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/BodyTab.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/BodyTab.tsx similarity index 84% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/BodyTab.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/BodyTab.tsx index 34a2d831..89d11c2f 100644 --- a/packages/oc-docs/src/components/Playground/Content/Views/Common/BodyTab.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/BodyTab.tsx @@ -8,12 +8,14 @@ interface BodyTabProps { body: RequestBody; onItemChange: (item: HttpRequest) => void; item: HttpRequest; + fillHeight?: boolean; } export const BodyTab: React.FC = ({ body, onItemChange, - item + item, + fillHeight = false }) => { const handleFormBodyChange = (formData: KeyValueRow[]) => { const updatedBody = { @@ -52,36 +54,39 @@ export const BodyTab: React.FC = ({ }; return ( -
+
{!body ? (
No body content. Select a body type to add content.
) : 'data' in body && typeof body.data === 'string' ? ( - { - if ('data' in body && typeof body.data === 'string') { - onItemChange({ - ...item, - http: { - ...item.http, - body: { ...body, data: value } as typeof body - } - }); +
+ { + if ('data' in body && typeof body.data === 'string') { + onItemChange({ + ...item, + http: { + ...item.http, + body: { ...body, data: value } as typeof body + } + }); + } + }} + language={ + body.type === 'json' + ? 'jsonc' + : body.type === 'xml' + ? 'xml' + : body.type === 'sparql' + ? 'sparql' + : 'text' } - }} - language={ - body.type === 'json' - ? 'jsonc' - : body.type === 'xml' - ? 'xml' - : body.type === 'sparql' - ? 'sparql' - : 'text' - } - height="300px" - /> + height={fillHeight ? '100%' : '300px'} + testId="body-editor" + /> +
) : Array.isArray(body) || (body?.type === 'form-urlencoded' && Array.isArray(body?.data)) ? ( (() => { const formDataArray = Array.isArray(body) ? body : (body?.data || []); diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/BulkEdit/BulkEdit.spec.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/BulkEdit/BulkEdit.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/BulkEdit/BulkEdit.spec.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/BulkEdit/BulkEdit.spec.tsx diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/BulkEdit/BulkEdit.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/BulkEdit/BulkEdit.tsx similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/BulkEdit/BulkEdit.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/BulkEdit/BulkEdit.tsx diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/BulkEdit/StyledWrapper.ts b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/BulkEdit/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/BulkEdit/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/BulkEdit/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/HeadersTab/HeadersTab.spec.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/HeadersTab/HeadersTab.spec.tsx similarity index 85% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/HeadersTab/HeadersTab.spec.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/HeadersTab/HeadersTab.spec.tsx index 232580be..53b3eb8d 100644 --- a/packages/oc-docs/src/components/Playground/Content/Views/Common/HeadersTab/HeadersTab.spec.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/HeadersTab/HeadersTab.spec.tsx @@ -24,11 +24,16 @@ describe('HeadersTab', () => { expect(values).toContain('text/html'); }); - it('renders the default title and a provided description', () => { + it('renders the provided description with no standalone title heading', () => { const root = useRenderToDom( - + ); - expect(query(root, '.title').text.trim()).toBe('Headers'); + // With no title prop, the tab shows only the description — no separate title heading. + expect(root.querySelector('.title')).toBeNull(); expect(query(root, '.description').text.trim()).toBe('Request headers sent with the call'); expect(root.querySelector('[data-testid="bulk-edit-toggle"]')).toBeTruthy(); }); diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/HeadersTab/HeadersTab.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/HeadersTab/HeadersTab.tsx similarity index 88% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/HeadersTab/HeadersTab.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/HeadersTab/HeadersTab.tsx index d4e3821e..c68b9edd 100644 --- a/packages/oc-docs/src/components/Playground/Content/Views/Common/HeadersTab/HeadersTab.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/HeadersTab/HeadersTab.tsx @@ -68,13 +68,15 @@ const HeadersDisplay: React.FC> = ); }; -export const HeadersTab: React.FC = ({ headers, onHeadersChange, title = 'Headers', description }) => { +export const HeadersTab: React.FC = ({ headers, onHeadersChange, title, description }) => { return ( -
- {Boolean(title) && {title}} - {description && {description}} -
+ {(Boolean(title) || Boolean(description)) && ( +
+ {title && {title}} + {description && {description}} +
+ )}
); diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/HeadersTab/StyledWrapper.ts b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/HeadersTab/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/HeadersTab/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/HeadersTab/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/OverviewTab/OverviewTab.spec.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/OverviewTab/OverviewTab.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/OverviewTab/OverviewTab.spec.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/OverviewTab/OverviewTab.spec.tsx diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/OverviewTab/OverviewTab.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/OverviewTab/OverviewTab.tsx similarity index 68% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/OverviewTab/OverviewTab.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/OverviewTab/OverviewTab.tsx index 5bcbbaf2..22c69229 100644 --- a/packages/oc-docs/src/components/Playground/Content/Views/Common/OverviewTab/OverviewTab.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/OverviewTab/OverviewTab.tsx @@ -3,10 +3,18 @@ import { useMemo } from 'react'; import { StyledWrapper } from './StyledWrapper'; import { EmptyState } from '../../../../../../ui/EmptyState/EmptyState'; import { BookIcon } from '../../../../../../assets/icons'; +import NoContentText from '../../../../../../ui/NoContentText/NoContentText'; -const OverviewTab: React.FC<{ docs?: string; emptyStateSubheading: string }> = ({ +interface OverviewTabProps { + docs?: string; + emptyStateSubheading: string; + displayEmptyStateBox?: boolean; +} + +const OverviewTab: React.FC = ({ docs, - emptyStateSubheading + emptyStateSubheading, + displayEmptyStateBox = true }) => { const md = useMarkdownRenderer(); const docsHtml = useMemo(() => { @@ -14,13 +22,15 @@ const OverviewTab: React.FC<{ docs?: string; emptyStateSubheading: string }> = ( }, [md, docs]); if (!docsHtml) { - return ( + return displayEmptyStateBox ? ( } heading="No overview content yet" subheading={emptyStateSubheading} /> + ) : ( + ); } diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/OverviewTab/StyledWrapper.ts b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/OverviewTab/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/OverviewTab/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/OverviewTab/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/ParamsTab.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/ParamsTab/ParamsTab.tsx similarity index 92% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/ParamsTab.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/ParamsTab/ParamsTab.tsx index d2e4b9db..ab64f4f7 100644 --- a/packages/oc-docs/src/components/Playground/Content/Views/Common/ParamsTab.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/ParamsTab/ParamsTab.tsx @@ -1,5 +1,6 @@ import React, { useCallback, useMemo } from 'react'; -import KeyValueTable, { type KeyValueRow } from '../../../../../components/KeyValueTable/KeyValueTable'; +import KeyValueTable, { type KeyValueRow } from '../../../../../KeyValueTable/KeyValueTable'; +import { StyledWrapper } from './StyledWrapper'; interface ParamsTabProps { params: Array<{ name?: string; value?: string; disabled?: boolean; type?: string }>; @@ -38,11 +39,11 @@ const ParamsSection: React.FC = React.memo(({ }) => (
- + {title} {description && ( - + {description} )} @@ -51,7 +52,6 @@ const ParamsSection: React.FC = React.memo(({ data={data} onChange={onChange} keyPlaceholder={keyLabel} - valuePlaceholder="Value" showEnabled={showEnabled} showActions={showActions} disableNewRow={disableNewRow} @@ -109,7 +109,7 @@ export const ParamsTab: React.FC = ({ const hasPath = pathData.length > 0; return ( -
+ {/* Query table: always shown so query params can be viewed/added regardless of whether the request currently has any. */} = ({ readOnlyKey={true} /> )} -
+ ); }; diff --git a/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/ParamsTab/StyledWrapper.ts b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/ParamsTab/StyledWrapper.ts new file mode 100644 index 00000000..c3836d38 --- /dev/null +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/ParamsTab/StyledWrapper.ts @@ -0,0 +1,17 @@ +import styled from '@emotion/styled'; + +export const StyledWrapper = styled.div` + + .description { + color: 'var(--text-secondary)' + } + + .params-section-title { + margin: 0 0 0.5rem; + font-size: 0.75rem; + font-weight: 500; + line-height: 1; + letter-spacing: 0; + color: var(--oc-colors-text-subtext2); + } +`; diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/ResponseBodyTab.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/ResponseBodyTab.tsx similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/ResponseBodyTab.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/ResponseBodyTab.tsx diff --git a/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/ResponseHeadersTab.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/ResponseHeadersTab.tsx new file mode 100644 index 00000000..e3a2b995 --- /dev/null +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/ResponseHeadersTab.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import NoContentText from '../../../../../ui/NoContentText/NoContentText'; + +interface ResponseHeadersTabProps { + headers?: Record; +} + +const ResponseHeadersTab: React.FC = ({ headers }) => { + + if(!headers) { + return ( + + ) + } + + return ( +
+
+
+ {Object.entries(headers).map(([key, value], index) => ( +
+ + {key} + + + {String(value)} + +
+ ))} +
+
+
+ ); +}; + +export default ResponseHeadersTab; + diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/ScriptsTab/ScriptsTab.spec.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/ScriptsTab/ScriptsTab.spec.tsx similarity index 92% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/ScriptsTab/ScriptsTab.spec.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/ScriptsTab/ScriptsTab.spec.tsx index 8e38a97e..b4d86885 100644 --- a/packages/oc-docs/src/components/Playground/Content/Views/Common/ScriptsTab/ScriptsTab.spec.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/ScriptsTab/ScriptsTab.spec.tsx @@ -18,9 +18,9 @@ describe('ScriptsTab', () => { expect(query(root, '[data-testid="scripts-tabs-tab-post-response"]').text.trim()).toBe('Post response'); }); - it('renders the default title and the Tests section', () => { + it('renders the Tests section with no standalone title heading', () => { const root = useRenderToDom(); - expect(query(root, '.title').text.trim()).toBe('Scripts'); + expect(root.querySelector('.title')).toBeNull(); expect(query(root, '.label').text.trim()).toBe('Tests'); }); diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/ScriptsTab/ScriptsTab.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/ScriptsTab/ScriptsTab.tsx similarity index 78% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/ScriptsTab/ScriptsTab.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/ScriptsTab/ScriptsTab.tsx index 2e891565..f89af072 100644 --- a/packages/oc-docs/src/components/Playground/Content/Views/Common/ScriptsTab/ScriptsTab.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/ScriptsTab/ScriptsTab.tsx @@ -15,14 +15,16 @@ interface ScriptsTabProps { title?: string; description?: string; showTests?: boolean; + fillHeight?: boolean; } export const ScriptsTab: React.FC = ({ scripts, onScriptChange, - title = 'Scripts', + title, description, - showTests = true + showTests = true, + fillHeight = false }) => { const [activeScriptTab, setActiveScriptTab] = useState('pre-request'); @@ -39,7 +41,7 @@ export const ScriptsTab: React.FC = ({ value={scripts.preRequest || ''} onChange={(value: string) => onScriptChange('preRequest', value)} language="javascript" - height="300px" + height={fillHeight ? '100%' : '300px'} hintsFor={['req', 'bru']} active={activeScriptTab === 'pre-request'} testId="scripts-editor-pre-request" @@ -54,7 +56,7 @@ export const ScriptsTab: React.FC = ({ value={scripts.postResponse || ''} onChange={(value: string) => onScriptChange('postResponse', value)} language="javascript" - height="300px" + height={fillHeight ? '100%' : '300px'} hintsFor={['req', 'res', 'bru']} active={activeScriptTab === 'post-response'} testId="scripts-editor-post-response" @@ -64,13 +66,15 @@ export const ScriptsTab: React.FC = ({ ]; return ( - -
- {Boolean(title) && {title}} - {description && {description}} -
+ + {(Boolean(title) || Boolean(description)) && ( +
+ {title && {title}} + {description && {description}} +
+ )} -
+
= ({ testResults, assertionR if (!hasTests && !hasAssertions) { return ( -
-
-
- - - -
-

No tests or assertions were run

-
-
+ ); } diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/TestsTab/StyledWrapper.ts b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/TestsTab/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/TestsTab/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/TestsTab/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/TestsTab/TestsTab.spec.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/TestsTab/TestsTab.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/TestsTab/TestsTab.spec.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/TestsTab/TestsTab.spec.tsx diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/TestsTab/TestsTab.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/TestsTab/TestsTab.tsx similarity index 52% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/TestsTab/TestsTab.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/TestsTab/TestsTab.tsx index 1bc4b7ac..c1e17838 100644 --- a/packages/oc-docs/src/components/Playground/Content/Views/Common/TestsTab/TestsTab.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/TestsTab/TestsTab.tsx @@ -9,24 +9,28 @@ interface TestsTabProps { onScriptChange: (scriptType: 'tests', value: string) => void; title?: string; description?: string; + fillHeight?: boolean; } -export const TestsTab: React.FC = ({ scripts, onScriptChange, title, description }) => { +export const TestsTab: React.FC = ({ scripts, onScriptChange, title, description, fillHeight = false }) => { return ( - + {(Boolean(title) || Boolean(description)) && (
- {Boolean(title) && {title}} + {title && {title}} {description && {description}}
)} - onScriptChange('tests', value)} - language="javascript" - height="400px" - hintsFor={['req', 'res', 'bru']} - /> +
+ onScriptChange('tests', value)} + language="javascript" + height={fillHeight ? '100%' : '400px'} + hintsFor={['req', 'res', 'bru']} + testId="tests-editor" + /> +
); }; diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/VariableTypeControl/StyledWrapper.ts b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/VariableTypeControl/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/VariableTypeControl/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/VariableTypeControl/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/VariableTypeControl/VariableTypeControl.spec.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/VariableTypeControl/VariableTypeControl.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/VariableTypeControl/VariableTypeControl.spec.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/VariableTypeControl/VariableTypeControl.spec.tsx diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/VariableTypeControl/VariableTypeControl.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/VariableTypeControl/VariableTypeControl.tsx similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/VariableTypeControl/VariableTypeControl.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/VariableTypeControl/VariableTypeControl.tsx diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/VariableTypeControl/variableTypeColumn.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/VariableTypeControl/variableTypeColumn.tsx similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/VariableTypeControl/variableTypeColumn.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/VariableTypeControl/variableTypeColumn.tsx diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/VariablesTab/StyledWrapper.ts b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/VariablesTab/StyledWrapper.ts similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/VariablesTab/StyledWrapper.ts rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/VariablesTab/StyledWrapper.ts diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/VariablesTab/VariablesTab.spec.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/VariablesTab/VariablesTab.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/VariablesTab/VariablesTab.spec.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/VariablesTab/VariablesTab.spec.tsx diff --git a/packages/oc-docs/src/components/Playground/Content/Views/Common/VariablesTab/VariablesTab.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/Common/VariablesTab/VariablesTab.tsx similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/Common/VariablesTab/VariablesTab.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/Common/VariablesTab/VariablesTab.tsx diff --git a/packages/oc-docs/src/components/Playground/Content/Views/EnvironmentsView/EnvVarCards/EnvVarCards.spec.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/EnvironmentsView/EnvVarCards/EnvVarCards.spec.tsx similarity index 100% rename from packages/oc-docs/src/components/Playground/Content/Views/EnvironmentsView/EnvVarCards/EnvVarCards.spec.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/EnvironmentsView/EnvVarCards/EnvVarCards.spec.tsx diff --git a/packages/oc-docs/src/components/Playground/Content/Views/EnvironmentsView/EnvVarCards/EnvVarCards.tsx b/packages/bruno-api-docs/src/components/Playground/Content/Views/EnvironmentsView/EnvVarCards/EnvVarCards.tsx similarity index 84% rename from packages/oc-docs/src/components/Playground/Content/Views/EnvironmentsView/EnvVarCards/EnvVarCards.tsx rename to packages/bruno-api-docs/src/components/Playground/Content/Views/EnvironmentsView/EnvVarCards/EnvVarCards.tsx index d6af0b14..b0a5534a 100644 --- a/packages/oc-docs/src/components/Playground/Content/Views/EnvironmentsView/EnvVarCards/EnvVarCards.tsx +++ b/packages/bruno-api-docs/src/components/Playground/Content/Views/EnvironmentsView/EnvVarCards/EnvVarCards.tsx @@ -7,6 +7,7 @@ import { cx } from '../../../../../../utils/cx'; import { toDataType } from '../../../../../../utils/variableDataType'; import { VariableTypeControl } from '../../Common/VariableTypeControl/VariableTypeControl'; import { StyledWrapper } from './StyledWrapper'; +import Checkbox from '../../../../../../ui/Checkbox/Checkbox'; interface EnvVarCardsProps { rows: KeyValueRow[]; @@ -38,11 +39,10 @@ const EnvVarCards: React.FC = ({ return (
{!isBlankRow && ( - updateRow(index, { enabled: e.target.checked })} /> )} @@ -69,7 +69,14 @@ const EnvVarCards: React.FC = ({
{row.secret ? ( - updateRow(index, { value: v })} className="value-secret" /> + updateRow(index, { value: v })} + className="value-secret" + /> ) : (