Ctrl K
ComunidadGuías…

tests/session_list_test.go

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package main

import (
	"context"
	"encoding/base64"
	"encoding/json"
	"testing"

	"github.com/shellhub-io/shellhub/pkg/api/query"
	"github.com/shellhub-io/shellhub/pkg/api/responses"
	"github.com/shellhub-io/shellhub/pkg/models"
	"github.com/shellhub-io/shellhub/tests/environment"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func propertyFilter(t *testing.T, name, operator string, value any) string {
	t.Helper()

	encoded, err := json.Marshal([]query.Filter{{
		Type:   query.FilterTypeProperty,
		Params: &query.FilterProperty{Name: name, Operator: operator, Value: value},
	}})
	require.NoError(t, err)

	return base64.RawURLEncoding.EncodeToString(encoded)
}

func requireSessionsListed(t *testing.T, ctx context.Context, compose *environment.DockerCompose, filter string, want ...string) {
	t.Helper()

	sessions := []models.Session{}

	resp, err := compose.R(ctx).
		SetQueryParams(map[string]string{"filter": filter, "per_page": "100"}).
		SetResult(&sessions).
		Get("/api/sessions")
	require.NoError(t, err)
	require.Equal(t, 200, resp.StatusCode(), resp.String())

	uids := make([]string, 0, len(sessions))
	for _, session := range sessions {
		uids = append(uids, session.UID)
	}

	assert.ElementsMatch(t, want, uids)
}

func TestSessionList(t *testing.T) {
	t.Parallel()

	ctx := context.Background()

	compose := newSSHEnvironment(t, ctx, legacyNamespace)
	_, first := startAcceptedAgent(t, ctx, compose)
	_, second := startAcceptedAgent(t, ctx, compose)
	signer := registerDeviceKey(t, ctx, compose)

	oldest := finishSession(t, ctx, compose, first, signer, "true")
	onSecond := finishSession(t, ctx, compose, second, signer, "true")

	_, opened := openSession(t, ctx, compose, first, signer, "")
	live := opened.UID
	requireSessionActive(t, ctx, compose, live, true)

	t.Run("by device_uid", func(t *testing.T) {
		requireSessionsListed(t, ctx, compose, propertyFilter(t, "device_uid", "eq", first.UID), oldest, live)
		requireSessionsListed(t, ctx, compose, propertyFilter(t, "device_uid", "eq", second.UID), onSecond)
		requireSessionsListed(t, ctx, compose, propertyFilter(t, "device_uid", "ne", first.UID), onSecond)
	})

	t.Run("by active status", func(t *testing.T) {
		requireSessionsListed(t, ctx, compose, propertyFilter(t, "active", "bool", true), live)
		requireSessionsListed(t, ctx, compose, propertyFilter(t, "active", "bool", false), oldest, onSecond)
	})

	t.Run("by closed status", func(t *testing.T) {
		requireSessionsListed(t, ctx, compose, propertyFilter(t, "closed", "bool", true), oldest, onSecond)
		requireSessionsListed(t, ctx, compose, propertyFilter(t, "closed", "bool", false), live)
	})

	t.Run("an operator the field does not take is refused", func(t *testing.T) {
		var refusal responses.Error

		resp, err := compose.R(ctx).
			SetQueryParam("filter", propertyFilter(t, "device_uid", "gt", first.UID)).
			SetError(&refusal).
			Get("/api/sessions")
		require.NoError(t, err)
		require.Equal(t, 400, resp.StatusCode(), resp.String())

		assert.Equal(t, map[string]string{"filter": query.ErrFilterPropertyInvalid.Error()}, refusal.Fields)
	})

	t.Run("newest started first", func(t *testing.T) {
		sessions := []models.Session{}

		resp, err := compose.R(ctx).SetResult(&sessions).Get("/api/sessions")
		require.NoError(t, err)
		require.Equal(t, 200, resp.StatusCode(), resp.String())

		uids := make([]string, 0, len(sessions))
		for i, session := range sessions {
			uids = append(uids, session.UID)

			if i > 0 {
				assert.False(t, session.StartedAt.After(sessions[i-1].StartedAt), "the list is newest first")
			}
		}

		assert.Equal(t, []string{live, onSecond, oldest}, uids)
	})
}