StepCI+Jest+OpenAPIを試してみたメモ

## 概要
Step CIを試用してみたメモ。
下記のフローを行った。

OpenAPIで定義 → 定義ファイルをバンドル（Step CIが $ref を解釈できないため) → Step CIでテストymlを作成 → 手動でテスト作成 → jestで実行

[ソースコード](https://github.com/hibohiboo/Yakumi/tree/ce96df024bbfccc893d55082fb5ca623ab244f9b)

## Step CIの開発準備
### npm ライブラリ
[Jest](https://docs.stepci.com/integration/jest.html)

```
npm i -D @redocly/cli @stepci/runner
```

<details><summary>package.json</summary><div>

redoclyまでは入れていた状態からのStepCIの追加の差分。
[自動収集](https://docs.stepci.com/legal/privacy.html)をオフにするなら`STEPCI_DISABLE_ANALYTICS=1`にしておくこと。([CLIでは匿名の情報を収集するのがデフォルトになっている。環境変数で切り替え可能。](https://docs.stepci.com/reference/cli.html))


```diff:api/package.json
{
  "name": "api",
  "version": "1.0.0",
  "scripts": {
    "prebuild": "cd ../packages/prisma && npm run build",
    "build": "tsc && tsc-alias",
    "watch": "tsc -w",
    "clean": "rimraf dist",
    "local-init": "bash ../infrastructure/local-db/bin/up.sh",
    "predev": "npm run clean && npm run build",
    "dev": "func start --port 7071",
    "lint": "eslint",
    "test": "jest",
+   "prestepci-generate": "npm run openapi-bundle",
+   "stepci-generate": "cross-env STEPCI_DISABLE_ANALYTICS=0 npx stepci generate ./openapi/dist/bundle.yml ./tests/e2e/geranated.stepci.yml",
+   "poststepci-generate": "npm run stepci-run",
+   "stepci-run": "cross-env STEPCI_DISABLE_ANALYTICS=0 npx stepci run ./tests/e2e/geranated.stepci.yml",
    "ncu": "ncu -u",
    "openapi": "redocly preview-docs",
    "openapi-build": "redocly build-docs core@v1 --disableGoogleFont -o ../docs/public/openapi/index.html",
+   "openapi-bundle": "redocly bundle -o ./openapi/dist/bundle.yml"
  },
  "dependencies": {
    "@azure/functions": "^4.5.0",
    "@azure/storage-blob": "^12.18.0",
    "date-fns": "^3.6.0",
    "mssql": "^10.0.2"
  },
  "devDependencies": {
    "@redocly/cli": "^1.12.2",
    "@stepci/runner": "^2.0.3",
    "@types/jest": "^29.5.12",
    "@types/mssql": "^9.1.5",
    "@types/node": "^20.x",
    "cross-env": "^7.0.3",
    "jest": "^29.7.0",
    "jest-html-reporters": "^3.1.7",
    "rimraf": "^5.0.7",
    "ts-jest": "^29.1.3",
    "tsc-alias": "^1.8.10",
    "typescript": "^5.4.5"
  },
  "main": "dist/api/src/functions/*.js"
}

```

</div></details>

### コード補完
[Editor Integration](https://docs.stepci.com/guides/editor-integration.html)

```
redhat.vscode-yaml
```

[.vscode/settings.json](https://github.com/hibohiboo/Yakumi/blob/develop/.vscode/settings.json)
```json
  "yaml.completion": true,
  "yaml.schemas": {
    "https://raw.githubusercontent.com/stepci/stepci/main/schema.json": "*.stepci.yml"
  }
```

## 自動生成してテスト実行
[Importing from OpenAPI](https://docs.stepci.com/import/openapi.html)

下記が追加したスクリプト。

[openapi/api.yaml](https://github.com/hibohiboo/Yakumi/blob/develop/api/openapi/api.yml)をバンドルし、dist/bundle.ymlに保存。
dist/bundle.ymlからStepCIのコードを生成し、`tests/e2e/generated.stepci.yml`に保存。
[stepci run](https://docs.stepci.com/reference/cli.html#run-workflow)で作成したテストを実行となっている。

```diff:api/package.json
  "scripts": {
    "test": "jest",
+   "prestepci-generate": "npm run openapi-bundle",
+   "stepci-generate": "cross-env STEPCI_DISABLE_ANALYTICS=0 npx stepci generate ./openapi/dist/bundle.yml ./tests/e2e/geranated.stepci.yml",
+   "poststepci-generate": "npm run stepci-run",
+   "stepci-run": "cross-env STEPCI_DISABLE_ANALYTICS=0 npx stepci run ./tests/e2e/geranated.stepci.yml",
+   "openapi-bundle": "redocly bundle -o ./openapi/dist/bundle.yml"
  },
```

### 生成結果
[tests/e2e/generated.stepci.yml](https://github.com/hibohiboo/Yakumi/blob/ce96df024bbfccc893d55082fb5ca623ab244f9b/api/tests/e2e/geranated.stepci.yml)を確認。

OpenAPIのserversがbaseURLに使われるみたい。

```api.yaml
servers:
  - url: http://localhost:7071/api
```

```generated.stepci.yml
config:
  http:
    baseURL: http://localhost:7071/api
```

パラメータについては、formatは反映されるけど、exampleは使われず、ランダムな文字列が入れられるみたい。

```api.yaml
      parameters:
        - in: query
          name: file
          schema:
            type: string
            description: アップロードするファイル名。/は%2Fにエンコードすること。/はフォルダ名となる
            example: icons%2Fflame.png
        - in: query
          name: permission
          schema:
            type: string
            enum:
              - w
            example: w
            description: ' w: 書き込み'
        - in: query
          name: timerange
          schema:
            type: string
            pattern: ^\d+$
            example: 5
            description: 単位は分(minute)
        - in: query
          name: container
          schema:
            type: string
            enum:
              - $web
            example: $web
            description: ストレージアカウントのコンテナ名
```

```genereted.stepci.yml
        http:
          url: /credentials
          method: POST
          params:
            file: Lorem sed tempor
            permission: w
            timerange: "86"
            container: $web
            
```

### 手動でテスト記載
自動生成ではスキーマチェックくらいしかしないので、他のテストは手動で書く必要がある。

```yml:api/tests/e2e/workflow.stepci.yml
version: "1.1"
name: My Workflow
env:
  host: http://localhost:7071
tests:
  example:
    name: パスを間違えた時に404が返ること
    steps:
      - name: Example step
        http:
          url: ${{env.host}}/api/get-character-cards/
          method: GET
          headers:
            Content-Type: application/json
          check:
            status: 404
```


### Jestのテストコード作成
[Jest](https://docs.stepci.com/integration/jest.html)

```api/tests/e2e/stepci.test.ts
import * as path from 'path';
import { runFromFile } from '@stepci/runner';

describe('Test Workflow', () => {
  test('Check Open API Schema', async () => {
    const { result } = await runFromFile(
      path.join(__dirname, './geranated.stepci.yml'),
    );
    expect(result.passed).toBe(true);
  });
  test('Check Response Status', async () => {
    const { result } = await runFromFile(
      path.join(__dirname, './workflow.stepci.yml'),
    );
    expect(result.passed).toBe(true);
  });
});
```

### 実行
```
npm run test
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99876/e3222cd6-dca4-e2c1-de4e-e0a266936233.png)

## 参考
[Step CI で手軽に API をテストする](https://zenn.dev/kou_pg_0131/articles/stepci-introduction)
[Step CIを用いたAPI自動テストのすゝめ](https://zenn.dev/d2c_mtech_blog/articles/bdf4bad83e7d0b)
[Step CI をアプリケーション開発に適用してみた流れを紹介](https://developer.mamezou-tech.com/blogs/2023/09/15/apply-stepci-to-app-dev/)