# Templates Postman SmartStack

> **Note:** Ces templates sont utilisés pour générer automatiquement les tests Postman
> après la création d'un controller.

---

## Structure Collection Postman

```json
{
  "name": "{Module} API",
  "item": [
    // Tests GET list
    // Tests GET single
    // Tests POST create
    // Tests PUT update
    // Tests PATCH activate/deactivate
    // Tests DELETE
  ]
}
```

---

## Users de Test Disponibles

| User | Email | Password | Permissions |
|------|-------|----------|-------------|
| SuperAdmin | `superadmin@smartstack.test` | `SuperAdmin123!` | `*` (toutes) |
| PlatformAdmin | `platformadmin@smartstack.test` | `PlatformAdmin123!` | `platform.administration.*` |
| User | `user@smartstack.test` | `User123!` | Standard |
| ReadOnly | `readonly@smartstack.test` | `ReadOnly123!` | `*.read` uniquement |
| NoPerm | `noperm@smartstack.test` | `NoPerm123!` | Aucune |
| Inactive | `inactive@smartstack.test` | `Inactive123!` | Compte désactivé |

---

## Template Test GET List (200)

```json
{
  "name": "GET {module} - With SuperAdmin Token (200)",
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "exec": [
          "const baseUrl = pm.collectionVariables.get('baseUrl');",
          "",
          "pm.sendRequest({",
          "    url: baseUrl + '/api/auth/login',",
          "    method: 'POST',",
          "    header: { 'Content-Type': 'application/json' },",
          "    body: {",
          "        mode: 'raw',",
          "        raw: JSON.stringify({",
          "            email: 'superadmin@smartstack.test',",
          "            password: 'SuperAdmin123!'",
          "        })",
          "    }",
          "}, function (err, res) {",
          "    if (err) {",
          "        console.error('Login failed:', err);",
          "        return;",
          "    }",
          "    const response = res.json();",
          "    pm.collectionVariables.set('accessToken', response.token);",
          "    pm.collectionVariables.set('currentUser', 'superadmin');",
          "});"
        ],
        "type": "text/javascript"
      }
    },
    {
      "listen": "test",
      "script": {
        "exec": [
          "pm.test('Status code is 200', function () {",
          "    pm.response.to.have.status(200);",
          "});",
          "",
          "pm.test('Response has items array', function () {",
          "    const response = pm.response.json();",
          "    pm.expect(response).to.have.property('items');",
          "    pm.expect(response.items).to.be.an('array');",
          "});",
          "",
          "pm.test('Response has pagination info', function () {",
          "    const response = pm.response.json();",
          "    pm.expect(response).to.have.property('totalCount');",
          "    pm.expect(response).to.have.property('page');",
          "    pm.expect(response).to.have.property('pageSize');",
          "});"
        ],
        "type": "text/javascript"
      }
    }
  ],
  "request": {
    "method": "GET",
    "header": [
      {
        "key": "Authorization",
        "value": "Bearer {{accessToken}}",
        "type": "text"
      }
    ],
    "url": {
      "raw": "{{baseUrl}}/api/{area}/{module}",
      "host": ["{{baseUrl}}"],
      "path": ["api", "{area}", "{module}"]
    }
  }
}
```

---

## Template Test GET (403 - Permission Denied)

```json
{
  "name": "GET {module} - With NoPerm Token (403)",
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "exec": [
          "const baseUrl = pm.collectionVariables.get('baseUrl');",
          "",
          "pm.sendRequest({",
          "    url: baseUrl + '/api/auth/login',",
          "    method: 'POST',",
          "    header: { 'Content-Type': 'application/json' },",
          "    body: {",
          "        mode: 'raw',",
          "        raw: JSON.stringify({",
          "            email: 'noperm@smartstack.test',",
          "            password: 'NoPerm123!'",
          "        })",
          "    }",
          "}, function (err, res) {",
          "    if (err) {",
          "        console.error('Login failed:', err);",
          "        return;",
          "    }",
          "    const response = res.json();",
          "    pm.collectionVariables.set('accessToken', response.token);",
          "    pm.collectionVariables.set('currentUser', 'noperm');",
          "});"
        ],
        "type": "text/javascript"
      }
    },
    {
      "listen": "test",
      "script": {
        "exec": [
          "pm.test('Status code is 403 Forbidden', function () {",
          "    pm.response.to.have.status(403);",
          "});",
          "",
          "pm.test('Response indicates permission denied', function () {",
          "    // 403 responses may have empty body or error message",
          "    pm.expect(pm.response.code).to.equal(403);",
          "});"
        ],
        "type": "text/javascript"
      }
    }
  ],
  "request": {
    "method": "GET",
    "header": [
      {
        "key": "Authorization",
        "value": "Bearer {{accessToken}}",
        "type": "text"
      }
    ],
    "url": {
      "raw": "{{baseUrl}}/api/{area}/{module}",
      "host": ["{{baseUrl}}"],
      "path": ["api", "{area}", "{module}"]
    }
  }
}
```

---

## Template Test GET (401 - No Auth)

```json
{
  "name": "GET {module} - Without Token (401)",
  "event": [
    {
      "listen": "test",
      "script": {
        "exec": [
          "pm.test('Status code is 401 Unauthorized', function () {",
          "    pm.response.to.have.status(401);",
          "});"
        ],
        "type": "text/javascript"
      }
    }
  ],
  "request": {
    "method": "GET",
    "header": [],
    "url": {
      "raw": "{{baseUrl}}/api/{area}/{module}",
      "host": ["{{baseUrl}}"],
      "path": ["api", "{area}", "{module}"]
    }
  }
}
```

---

## Template Test POST Create (201)

```json
{
  "name": "POST {module} - With Admin Token (201)",
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "exec": [
          "const baseUrl = pm.collectionVariables.get('baseUrl');",
          "",
          "pm.sendRequest({",
          "    url: baseUrl + '/api/auth/login',",
          "    method: 'POST',",
          "    header: { 'Content-Type': 'application/json' },",
          "    body: {",
          "        mode: 'raw',",
          "        raw: JSON.stringify({",
          "            email: 'superadmin@smartstack.test',",
          "            password: 'SuperAdmin123!'",
          "        })",
          "    }",
          "}, function (err, res) {",
          "    if (err) return console.error('Login failed:', err);",
          "    const response = res.json();",
          "    pm.collectionVariables.set('accessToken', response.token);",
          "});"
        ],
        "type": "text/javascript"
      }
    },
    {
      "listen": "test",
      "script": {
        "exec": [
          "pm.test('Status code is 201 Created', function () {",
          "    pm.response.to.have.status(201);",
          "});",
          "",
          "pm.test('Response has created entity with ID', function () {",
          "    const response = pm.response.json();",
          "    pm.expect(response).to.have.property('id');",
          "    // Store for subsequent tests",
          "    pm.collectionVariables.set('test{Entity}Id', response.id);",
          "});",
          "",
          "pm.test('Response has Location header', function () {",
          "    pm.expect(pm.response.headers.has('Location')).to.be.true;",
          "});"
        ],
        "type": "text/javascript"
      }
    }
  ],
  "request": {
    "method": "POST",
    "header": [
      {
        "key": "Authorization",
        "value": "Bearer {{accessToken}}",
        "type": "text"
      },
      {
        "key": "Content-Type",
        "value": "application/json",
        "type": "text"
      }
    ],
    "body": {
      "mode": "raw",
      "raw": "{\n    \"name\": \"Test {Entity} {{$timestamp}}\",\n    \"description\": \"Created via Postman test\"\n}"
    },
    "url": {
      "raw": "{{baseUrl}}/api/{area}/{module}",
      "host": ["{{baseUrl}}"],
      "path": ["api", "{area}", "{module}"]
    }
  }
}
```

---

## Template Test POST (403 - ReadOnly)

```json
{
  "name": "POST {module} - With ReadOnly Token (403)",
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "exec": [
          "const baseUrl = pm.collectionVariables.get('baseUrl');",
          "",
          "pm.sendRequest({",
          "    url: baseUrl + '/api/auth/login',",
          "    method: 'POST',",
          "    header: { 'Content-Type': 'application/json' },",
          "    body: {",
          "        mode: 'raw',",
          "        raw: JSON.stringify({",
          "            email: 'readonly@smartstack.test',",
          "            password: 'ReadOnly123!'",
          "        })",
          "    }",
          "}, function (err, res) {",
          "    if (err) return console.error('Login failed:', err);",
          "    const response = res.json();",
          "    pm.collectionVariables.set('accessToken', response.token);",
          "});"
        ],
        "type": "text/javascript"
      }
    },
    {
      "listen": "test",
      "script": {
        "exec": [
          "pm.test('Status code is 403 Forbidden', function () {",
          "    pm.response.to.have.status(403);",
          "});"
        ],
        "type": "text/javascript"
      }
    }
  ],
  "request": {
    "method": "POST",
    "header": [
      {
        "key": "Authorization",
        "value": "Bearer {{accessToken}}",
        "type": "text"
      },
      {
        "key": "Content-Type",
        "value": "application/json",
        "type": "text"
      }
    ],
    "body": {
      "mode": "raw",
      "raw": "{\n    \"name\": \"Should Fail\",\n    \"description\": \"ReadOnly cannot create\"\n}"
    },
    "url": {
      "raw": "{{baseUrl}}/api/{area}/{module}",
      "host": ["{{baseUrl}}"],
      "path": ["api", "{area}", "{module}"]
    }
  }
}
```

---

## Template Test DELETE (403)

```json
{
  "name": "DELETE {module} - With ReadOnly Token (403)",
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "exec": [
          "const baseUrl = pm.collectionVariables.get('baseUrl');",
          "",
          "pm.sendRequest({",
          "    url: baseUrl + '/api/auth/login',",
          "    method: 'POST',",
          "    header: { 'Content-Type': 'application/json' },",
          "    body: {",
          "        mode: 'raw',",
          "        raw: JSON.stringify({",
          "            email: 'readonly@smartstack.test',",
          "            password: 'ReadOnly123!'",
          "        })",
          "    }",
          "}, function (err, res) {",
          "    if (err) return console.error('Login failed:', err);",
          "    const response = res.json();",
          "    pm.collectionVariables.set('accessToken', response.token);",
          "});"
        ],
        "type": "text/javascript"
      }
    },
    {
      "listen": "test",
      "script": {
        "exec": [
          "pm.test('Status code is 403 Forbidden', function () {",
          "    pm.response.to.have.status(403);",
          "});"
        ],
        "type": "text/javascript"
      }
    }
  ],
  "request": {
    "method": "DELETE",
    "header": [
      {
        "key": "Authorization",
        "value": "Bearer {{accessToken}}",
        "type": "text"
      }
    ],
    "url": {
      "raw": "{{baseUrl}}/api/{area}/{module}/{{test{Entity}Id}}",
      "host": ["{{baseUrl}}"],
      "path": ["api", "{area}", "{module}", "{{test{Entity}Id}}"]
    }
  }
}
```

---

## Template Test Auth - Login Success

```json
{
  "name": "Login - Valid Credentials (200)",
  "event": [
    {
      "listen": "test",
      "script": {
        "exec": [
          "pm.test('Status code is 200', function () {",
          "    pm.response.to.have.status(200);",
          "});",
          "",
          "pm.test('Response has access token', function () {",
          "    const response = pm.response.json();",
          "    pm.expect(response).to.have.property('token');",
          "    pm.expect(response.token).to.be.a('string');",
          "});",
          "",
          "pm.test('Response has user info', function () {",
          "    const response = pm.response.json();",
          "    pm.expect(response).to.have.property('user');",
          "    pm.expect(response.user).to.have.property('email');",
          "    pm.expect(response.user).to.have.property('roles');",
          "    pm.expect(response.user).to.have.property('permissions');",
          "});"
        ],
        "type": "text/javascript"
      }
    }
  ],
  "request": {
    "method": "POST",
    "header": [
      {
        "key": "Content-Type",
        "value": "application/json",
        "type": "text"
      }
    ],
    "body": {
      "mode": "raw",
      "raw": "{\n    \"email\": \"superadmin@smartstack.test\",\n    \"password\": \"SuperAdmin123!\"\n}"
    },
    "url": {
      "raw": "{{baseUrl}}/api/auth/login",
      "host": ["{{baseUrl}}"],
      "path": ["api", "auth", "login"]
    }
  }
}
```

---

## Génération Automatique

Pour générer les tests d'un nouveau controller, remplacer :

| Variable | Exemple |
|----------|---------|
| `{area}` | `support`, `admin`, `business` |
| `{module}` | `tickets`, `sla`, `users` |
| `{Entity}` | `Ticket`, `SlaDefinition`, `User` |

### Tests Minimum par Controller

1. GET list - SuperAdmin (200)
2. GET list - NoPerm (403)
3. GET list - No Token (401)
4. POST create - Admin (201)
5. POST create - ReadOnly (403)
6. DELETE - ReadOnly (403)

### Tests Optionnels

- GET by ID - (200)
- GET by ID - Not Found (404)
- PUT update - (200)
- PATCH activate/deactivate - (204)
- POST avec données invalides - (400)
- POST doublon - (409)
