Repository: Redocly/openapi-cli (ts)

Issue:
no-server-trailing-slash shows error for `/` for oas3
## Describe the bug

Using the below YAML I get this error
```
validating demo.yaml...
[1] demo.yaml:10:10 at #/servers/0/url

Server `url` should not have a trailing slash.

 8 |     url: https://demo.com/domain/path
 9 | servers:
10 |   - url: /
11 |     description: The Server
12 | paths:

Error was generated by the no-server-trailing-slash rule.
```

Reading up on the openapi specs this should actually be valid.

### Source
  * https://spec.openapis.org/oas/latest.html#fixed-fields
    * `servers` field name says
      > (...) If the servers property is not provided, or is an empty array, the default value would be a Server Object with a url value of /.


Looking into your oas3 rule `NoServerTrailingSlash` I see that you only check if the url string ends with a `/`. I think this needs to be adjusted to allow also a single `/` as root (same like in this PR but for openapi 3.x.x specs https://github.com/Redocly/openapi-cli/pull/162)

https://github.com/Redocly/openapi-cli/blob/e6f99e57da339d89bba7f4a1ba897282d7cebbd2/packages/core/src/rules/oas3/no-server-trailing-slash.ts#L7


## Demo YAML to reproduce

<details>
  <summary>Expande</summary>

```
openapi: 3.0.0
info:
  title: Demo API
  description: Showcase trailing slash error.
  version: 1.0.0
  license:
    name: "Demo 1.0.0"
    url: https://demo.com/domain/path
servers:
  - url: /
    description: The Server
paths:
  /v1/some/path:
    get:
      summary: Returns a list of things.
      tags:
        - Demo
      description: My demo
      operationId: getDemo
      responses:
        '200':
          description: A JSON array of demo things
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/DemoThings'
        '400':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BadRequest'
components:
  schemas:
    DemoThings:
      required:
        - id
      properties:
        id:
          type: string
          description: The id of the thing
    BadRequest:
      required:
        - message
      type: object
      properties:
        message:
          type: string
```
</details>


Pull request description:
fix: should not throw error when server url is root
fixes #446

Patch:
diff --git a/packages/core/src/rules/oas3/no-server-trailing-slash.ts b/packages/core/src/rules/oas3/no-server-trailing-slash.ts
index 0f90b341..7656d587 100644
--- a/packages/core/src/rules/oas3/no-server-trailing-slash.ts
+++ b/packages/core/src/rules/oas3/no-server-trailing-slash.ts
@@ -4,7 +4,7 @@ export const NoServerTrailingSlash: Oas3Rule = () => {
   return {
     Server(server, { report, location }) {
       if (!server.url) return;
-      if (server.url.endsWith('/')) {
+      if (server.url.endsWith('/') && server.url !== '/') {
         report({
           message: 'Server `url` should not have a trailing slash.',
           location: location.child(['url']),


Test patch:
diff --git a/packages/core/src/rules/oas3/__tests__/no-server-trailing-slash.test.ts b/packages/core/src/rules/oas3/__tests__/no-server-trailing-slash.test.ts
index d899e662..7fa85608 100644
--- a/packages/core/src/rules/oas3/__tests__/no-server-trailing-slash.test.ts
+++ b/packages/core/src/rules/oas3/__tests__/no-server-trailing-slash.test.ts
@@ -58,4 +58,23 @@ describe('Oas3 oas3-no-server-trailing-slash', () => {
 
     expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`Array []`);
   });
+
+  it('oas3-no-server-trailing-slash: should not report on server object with no trailing slash if the url is root', async () => {
+    const document = parseYamlToDocument(
+      outdent`
+          openapi: 3.0.0
+          servers:
+            - url: /
+        `,
+      'foobar.yaml',
+    );
+
+    const results = await lintDocument({
+      externalRefResolver: new BaseResolver(),
+      document,
+      config: makeConfig({ 'no-server-trailing-slash': 'error' }),
+    });
+
+    expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`Array []`);
+  });
 });