Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
16 changes: 16 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
bin/
obj/
*.mdf
*.ldf
*.db
*.suo
*.user
*.userosscache
*.sln.docstates
.vs/
logs/
*.log
out/
Dockerfile
docker-compose.yml
.env
36 changes: 36 additions & 0 deletions .github/workflows/commitlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Commit Lint

on:
pull_request:
types: [opened, synchronize, reopened]
push:
branches:
- main
- develop

jobs:
commitlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Lint commit messages
run: |
if [ "${{ github.event_name }}" = "pull_request" ]; then
echo "Linting PR commits from ${{ github.event.pull_request.base.sha }} to ${{ github.event.pull_request.head.sha }}"
npx commitlint --from=${{ github.event.pull_request.base.sha }} --to=${{ github.event.pull_request.head.sha }} --verbose
else
echo "Linting last commit"
npx commitlint --from=HEAD~1 --to=HEAD --verbose
fi
49 changes: 49 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Deploy to Yandex Cloud

on:
push:
branches:
- main

jobs:
build-and-deploy:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3

# Login to Yandex Cloud
- name: Yandex Cloud Login
uses: yandex-cloud/github-action@v3.0.0
with:
service-account-key: ${{ secrets.YC_SA_JSON_CREDENTIALS }}

# Login to Container Registry
- name: Login to Yandex Container Registry
run: |
yc container registry configure-docker

# Build Docker Image (Force AMD64 architecture)
- name: Build and Push Docker Image
run: |
# Use the Commit Hash as the tag so every build is unique
IMAGE_URL=cr.yandex/${{ secrets.YC_REGISTRY_ID }}/konto-api:${{ github.sha }}

docker build --platform linux/amd64 -t $IMAGE_URL .
docker push $IMAGE_URL

# Save the image URL for the next step
echo "IMAGE_URL=$IMAGE_URL" >> $GITHUB_ENV

# Deploy to Serverless Container
- name: Deploy Revision
run: |
yc serverless container revision deploy \
--container-id ${{ secrets.YC_CONTAINER_ID }} \
--image-url ${{ env.IMAGE_URL }} \
--service-account-id ${{ secrets.YC_SERVICE_ACCOUNT_ID }} \
--cores 1 \
--memory 512M \
--execution-timeout 30s \
--concurrency 4
33 changes: 33 additions & 0 deletions .github/workflows/format-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Format Check

on:
pull_request:
branches: [develop, main]
push:
branches: [develop, main]

jobs:
format:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: "9.0.x"

- name: Restore dependencies
run: dotnet restore KontoApi.sln

- name: Format code
run: dotnet format KontoApi.sln

- name: Check for changes
run: |
if [[ -n $(git status --porcelain) ]]; then
echo "Code formatting issues detected. Please run 'dotnet format' locally"
git diff
exit 1
fi
11 changes: 10 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
##
## Get latest from https://github.com/github/gitignore/blob/main/Dotnet.gitignore

# JetBrains IDE
.idea/

# Build results
[Dd]ebug/
[Dd]ebugPublic/
Expand Down Expand Up @@ -51,4 +54,10 @@ CodeCoverage/
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
nunit-*.xml

# Node.js (for commit linting tools)
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
4 changes: 4 additions & 0 deletions .husky/commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx --no -- commitlint --edit "$1"
50 changes: 50 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Contributing Guide

## Setup

After cloning the repository, install the commit linting tools:

```bash
npm install
```

This will install Husky git hooks that automatically enforce Conventional Commits on every commit

## Workflow

1. Pick a task from [Kanban Board](https://github.com/orgs/project-konto/projects/1/views/2)
2. Create a new branch from `development` (name it `feature/<FEATURE-NAME>` or `bug/<BUG-NAME>`)
3. Commit your changes using Conventional Commits format:
- Format: `<type>(<scope>): <subject> #<issue>`
- Example: `feat(api): add transaction import #23`
- Allowed types: `feat`, `fix`, `docs`, `chore`, `refactor`, `test`, `perf`, `build`, `ci`, `revert`, `style`
4. Push your branch and open a Pull Request against `development`
5. Wait for workflows and code review and make any requested changes
6. Sync with `development`

## Commit Message Format

All commits must follow the [Conventional Commits](https://www.conventionalcommits.org/) specification. The commit message hook will prevent invalid commits locally, and CI will verify all commits in pull requests

## Logging

We use **Serilog** for structured logging. Inject `ILogger<T>` in your class:

```csharp
public class Service
{
private readonly ILogger<Service> loger;

public Service(ILogger<Service> logger)
{
this.loger = logger;
}

public void DoWork(int userId)
{
loger.LogInformation("Processing user {UserId}", userId);
}
}
```

Available log levels: `LogDebug`, `LogInformation`, `LogWarning`, `LogError`, `LogCritical`
29 changes: 29 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Build stage
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /app

# Yandex Cloud CA certificate
RUN mkdir -p /app/certs
ADD https://storage.yandexcloud.net/cloud-certs/CA.pem /app/certs/root.crt
RUN chmod 644 /app/certs/root.crt

# Copy csproj and restore as distinct layers
COPY src/Api/KontoApi.Api.csproj src/Api/
COPY src/Application/KontoApi.Application.csproj src/Application/
COPY src/Domain/KontoApi.Domain.csproj src/Domain/
COPY src/Infrastructure/KontoApi.Infrastructure.csproj src/Infrastructure/
RUN dotnet restore src/Api/KontoApi.Api.csproj

# Copy everything else and build
COPY . .
RUN dotnet publish src/Api/KontoApi.Api.csproj -c Release -o out

# Runtime stage
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime
WORKDIR /app
COPY --from=build /app/out .
COPY --from=build /app/certs /app/certs

EXPOSE 80

ENTRYPOINT ["sh", "-c", "dotnet KontoApi.Api.dll --urls http://0.0.0.0:${PORT:-80}"]
113 changes: 113 additions & 0 deletions KontoApi.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Api", "Api", "{81034408-37C8-1011-444E-4C15C2FADA8E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KontoApi.Api", "src\Api\KontoApi.Api.csproj", "{F48668CC-EDBB-468D-A81C-23E1B428D687}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Domain", "Domain", "{8B290487-4C16-E85E-E807-F579CBE9FC4D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KontoApi.Domain", "src\Domain\KontoApi.Domain.csproj", "{CA516A11-7E7D-4140-B077-4B37BCB3523B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Infrastructure", "Infrastructure", "{9048EB7F-3875-A59E-E36B-5BD4C6F2A282}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KontoApi.Infrastructure", "src\Infrastructure\KontoApi.Infrastructure.csproj", "{B3837337-6390-4516-8848-86C6E300B39F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Application", "Application", "{22BAF98C-8415-17C4-B26A-D537657BC863}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KontoApi.Application", "src\Application\KontoApi.Application.csproj", "{87223133-95CD-4D6B-9710-4DC1B958EC4F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0AB3BF05-4346-4AA6-1389-037BE0695223}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KontoApi.Tests", "tests\KontoApi.Tests\KontoApi.Tests.csproj", "{DC598036-8206-4BA0-A562-DF4DC6088302}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F48668CC-EDBB-468D-A81C-23E1B428D687}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F48668CC-EDBB-468D-A81C-23E1B428D687}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F48668CC-EDBB-468D-A81C-23E1B428D687}.Debug|x64.ActiveCfg = Debug|Any CPU
{F48668CC-EDBB-468D-A81C-23E1B428D687}.Debug|x64.Build.0 = Debug|Any CPU
{F48668CC-EDBB-468D-A81C-23E1B428D687}.Debug|x86.ActiveCfg = Debug|Any CPU
{F48668CC-EDBB-468D-A81C-23E1B428D687}.Debug|x86.Build.0 = Debug|Any CPU
{F48668CC-EDBB-468D-A81C-23E1B428D687}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F48668CC-EDBB-468D-A81C-23E1B428D687}.Release|Any CPU.Build.0 = Release|Any CPU
{F48668CC-EDBB-468D-A81C-23E1B428D687}.Release|x64.ActiveCfg = Release|Any CPU
{F48668CC-EDBB-468D-A81C-23E1B428D687}.Release|x64.Build.0 = Release|Any CPU
{F48668CC-EDBB-468D-A81C-23E1B428D687}.Release|x86.ActiveCfg = Release|Any CPU
{F48668CC-EDBB-468D-A81C-23E1B428D687}.Release|x86.Build.0 = Release|Any CPU
{CA516A11-7E7D-4140-B077-4B37BCB3523B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CA516A11-7E7D-4140-B077-4B37BCB3523B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CA516A11-7E7D-4140-B077-4B37BCB3523B}.Debug|x64.ActiveCfg = Debug|Any CPU
{CA516A11-7E7D-4140-B077-4B37BCB3523B}.Debug|x64.Build.0 = Debug|Any CPU
{CA516A11-7E7D-4140-B077-4B37BCB3523B}.Debug|x86.ActiveCfg = Debug|Any CPU
{CA516A11-7E7D-4140-B077-4B37BCB3523B}.Debug|x86.Build.0 = Debug|Any CPU
{CA516A11-7E7D-4140-B077-4B37BCB3523B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CA516A11-7E7D-4140-B077-4B37BCB3523B}.Release|Any CPU.Build.0 = Release|Any CPU
{CA516A11-7E7D-4140-B077-4B37BCB3523B}.Release|x64.ActiveCfg = Release|Any CPU
{CA516A11-7E7D-4140-B077-4B37BCB3523B}.Release|x64.Build.0 = Release|Any CPU
{CA516A11-7E7D-4140-B077-4B37BCB3523B}.Release|x86.ActiveCfg = Release|Any CPU
{CA516A11-7E7D-4140-B077-4B37BCB3523B}.Release|x86.Build.0 = Release|Any CPU
{B3837337-6390-4516-8848-86C6E300B39F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B3837337-6390-4516-8848-86C6E300B39F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B3837337-6390-4516-8848-86C6E300B39F}.Debug|x64.ActiveCfg = Debug|Any CPU
{B3837337-6390-4516-8848-86C6E300B39F}.Debug|x64.Build.0 = Debug|Any CPU
{B3837337-6390-4516-8848-86C6E300B39F}.Debug|x86.ActiveCfg = Debug|Any CPU
{B3837337-6390-4516-8848-86C6E300B39F}.Debug|x86.Build.0 = Debug|Any CPU
{B3837337-6390-4516-8848-86C6E300B39F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B3837337-6390-4516-8848-86C6E300B39F}.Release|Any CPU.Build.0 = Release|Any CPU
{B3837337-6390-4516-8848-86C6E300B39F}.Release|x64.ActiveCfg = Release|Any CPU
{B3837337-6390-4516-8848-86C6E300B39F}.Release|x64.Build.0 = Release|Any CPU
{B3837337-6390-4516-8848-86C6E300B39F}.Release|x86.ActiveCfg = Release|Any CPU
{B3837337-6390-4516-8848-86C6E300B39F}.Release|x86.Build.0 = Release|Any CPU
{87223133-95CD-4D6B-9710-4DC1B958EC4F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{87223133-95CD-4D6B-9710-4DC1B958EC4F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{87223133-95CD-4D6B-9710-4DC1B958EC4F}.Debug|x64.ActiveCfg = Debug|Any CPU
{87223133-95CD-4D6B-9710-4DC1B958EC4F}.Debug|x64.Build.0 = Debug|Any CPU
{87223133-95CD-4D6B-9710-4DC1B958EC4F}.Debug|x86.ActiveCfg = Debug|Any CPU
{87223133-95CD-4D6B-9710-4DC1B958EC4F}.Debug|x86.Build.0 = Debug|Any CPU
{87223133-95CD-4D6B-9710-4DC1B958EC4F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{87223133-95CD-4D6B-9710-4DC1B958EC4F}.Release|Any CPU.Build.0 = Release|Any CPU
{87223133-95CD-4D6B-9710-4DC1B958EC4F}.Release|x64.ActiveCfg = Release|Any CPU
{87223133-95CD-4D6B-9710-4DC1B958EC4F}.Release|x64.Build.0 = Release|Any CPU
{87223133-95CD-4D6B-9710-4DC1B958EC4F}.Release|x86.ActiveCfg = Release|Any CPU
{87223133-95CD-4D6B-9710-4DC1B958EC4F}.Release|x86.Build.0 = Release|Any CPU
{DC598036-8206-4BA0-A562-DF4DC6088302}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DC598036-8206-4BA0-A562-DF4DC6088302}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DC598036-8206-4BA0-A562-DF4DC6088302}.Debug|x64.ActiveCfg = Debug|Any CPU
{DC598036-8206-4BA0-A562-DF4DC6088302}.Debug|x64.Build.0 = Debug|Any CPU
{DC598036-8206-4BA0-A562-DF4DC6088302}.Debug|x86.ActiveCfg = Debug|Any CPU
{DC598036-8206-4BA0-A562-DF4DC6088302}.Debug|x86.Build.0 = Debug|Any CPU
{DC598036-8206-4BA0-A562-DF4DC6088302}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DC598036-8206-4BA0-A562-DF4DC6088302}.Release|Any CPU.Build.0 = Release|Any CPU
{DC598036-8206-4BA0-A562-DF4DC6088302}.Release|x64.ActiveCfg = Release|Any CPU
{DC598036-8206-4BA0-A562-DF4DC6088302}.Release|x64.Build.0 = Release|Any CPU
{DC598036-8206-4BA0-A562-DF4DC6088302}.Release|x86.ActiveCfg = Release|Any CPU
{DC598036-8206-4BA0-A562-DF4DC6088302}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{81034408-37C8-1011-444E-4C15C2FADA8E} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{F48668CC-EDBB-468D-A81C-23E1B428D687} = {81034408-37C8-1011-444E-4C15C2FADA8E}
{8B290487-4C16-E85E-E807-F579CBE9FC4D} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{CA516A11-7E7D-4140-B077-4B37BCB3523B} = {8B290487-4C16-E85E-E807-F579CBE9FC4D}
{9048EB7F-3875-A59E-E36B-5BD4C6F2A282} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{B3837337-6390-4516-8848-86C6E300B39F} = {9048EB7F-3875-A59E-E36B-5BD4C6F2A282}
{22BAF98C-8415-17C4-B26A-D537657BC863} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{87223133-95CD-4D6B-9710-4DC1B958EC4F} = {22BAF98C-8415-17C4-B26A-D537657BC863}
{DC598036-8206-4BA0-A562-DF4DC6088302} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
EndGlobalSection
EndGlobal
14 changes: 14 additions & 0 deletions KontoApi.sln.DotSettings.user
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AControllerBase_002Ecs_002Fl_003A_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fdaf5f45634c140d1ba51dbccef7e0b1855d30_003F75_003Fe264c451_003FControllerBase_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AControllerBase_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fdaf5f45634c140d1ba51dbccef7e0b1855d30_003F75_003Fe264c451_003FControllerBase_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AControllerBase_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FSourcesCache_003Fc7afd9724cf757c4a8469dba2bdc22ab5ac111c91f431dbfefc992dacb3e8635_003FControllerBase_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ADbSet_00601_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F3acb8a24d4ad434690d7c571c6ae2acf291438_003F93_003Fa6fdf714_003FDbSet_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIActionResult_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FSourcesCache_003F13dc2b82f180e129c1f1186d422e1ed4122e23e1e1f265941fb7d2d3e1ce2_003FIActionResult_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/dotCover/Editor/HighlightingSourceSnapshotLocation/@EntryValue">/Users/egorvetoskin/Library/Caches/JetBrains/Rider2025.2/resharper-host/temp/Rider/vAny/CoverageData/_KontoApi.-1767776553/Snapshot/snapshot.utdcvr</s:String>
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=b3224c2f_002D1e6d_002D4e7c_002D8576_002Dd80d06d4a0f6/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" IsActive="True" Name="CategorySeederTests" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;
&lt;TestAncestor&gt;
&lt;TestId&gt;xUnit::DC598036-8206-4BA0-A562-DF4DC6088302::net10.0::KontoApi.Tests.CategoryTests.CategorySeederTests&lt;/TestId&gt;
&lt;TestId&gt;xUnit::DC598036-8206-4BA0-A562-DF4DC6088302::net10.0::KontoApi.Tests.CategoryTests.CategoryRepositoryTests&lt;/TestId&gt;
&lt;TestId&gt;xUnit::DC598036-8206-4BA0-A562-DF4DC6088302::net10.0::KontoApi.Tests.Integration.AccountApiIntegrationTests&lt;/TestId&gt;
&lt;/TestAncestor&gt;
&lt;/SessionState&gt;</s:String></wpf:ResourceDictionary>
Loading
Loading