Skip to content

Commit 563012f

Browse files
committed
Added initial integration tests.
1 parent 434ec8f commit 563012f

File tree

8 files changed

+506
-33
lines changed

8 files changed

+506
-33
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,20 @@ Run a specific test
104104
dotnet test -v n --framework net8.0 --filter "test-file-pattern"
105105
```
106106

107+
### Integration Tests
108+
Integration tests in `PowerSync.Common.IntegrationTests` are intended to run against the [self-host nodejs demo](https://github.com/powersync-ja/self-host-demo/tree/main/demos/nodejs).
109+
The integration tests are disabled by default, define the following environment variable to let them run.
110+
111+
```bash
112+
RUN_INTEGRATION_TESTS=true dotnet test -v n --framework net8.0
113+
```
114+
115+
Run integration tests exclusively.
116+
117+
```bash
118+
RUN_INTEGRATION_TESTS=true dotnet test -v n --framework net8.0 --filter "Category=Integration"
119+
```
120+
107121
## Using the PowerSync.Common package in your project
108122
```bash
109123
dotnet add package PowerSync.Common --prerelease
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
namespace PowerSync.Common.IntegrationTests;
2+
3+
using System;
4+
using System.Net.Http;
5+
using System.Text;
6+
using System.Text.Json;
7+
using System.Threading.Tasks;
8+
using System.Collections.Generic;
9+
using PowerSync.Common.DB.Crud;
10+
11+
public class NodeClient
12+
{
13+
private readonly HttpClient _httpClient;
14+
private readonly string _backendUrl;
15+
private readonly string _userId;
16+
17+
public NodeClient(string userId)
18+
{
19+
_httpClient = new HttpClient();
20+
_backendUrl = "http://localhost:6060";
21+
_userId = userId;
22+
}
23+
24+
public NodeClient(string backendUrl, string userId)
25+
{
26+
_httpClient = new HttpClient();
27+
_backendUrl = backendUrl;
28+
_userId = userId;
29+
}
30+
31+
public Task<string> CreateList(string id, string name)
32+
{
33+
return CreateItem("lists", id, name);
34+
}
35+
async Task<string> CreateItem(string table, string id, string name)
36+
{
37+
var data = new Dictionary<string, object>
38+
{
39+
{ "created_at", DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss") },
40+
{ "name", name },
41+
{ "owner_id", _userId }
42+
};
43+
44+
var batch = new[]
45+
{
46+
new
47+
{
48+
op = UpdateType.PUT.ToString(),
49+
table = table,
50+
id = id,
51+
data = data
52+
}
53+
};
54+
55+
var payload = JsonSerializer.Serialize(new { batch });
56+
var content = new StringContent(payload, Encoding.UTF8, "application/json");
57+
58+
HttpResponseMessage response = await _httpClient.PostAsync($"{_backendUrl}/api/data", content);
59+
60+
if (!response.IsSuccessStatusCode)
61+
{
62+
Console.WriteLine(await response.Content.ReadAsStringAsync());
63+
throw new Exception(
64+
$"Failed to create item. Status: {response.StatusCode}, " +
65+
$"Response: {await response.Content.ReadAsStringAsync()}"
66+
);
67+
}
68+
69+
return await response.Content.ReadAsStringAsync();
70+
}
71+
72+
public Task<string> DeleteList(string id)
73+
{
74+
return DeleteItem("lists", id);
75+
}
76+
77+
async Task<string> DeleteItem(string table, string id)
78+
{
79+
var batch = new[]
80+
{
81+
new
82+
{
83+
op = UpdateType.DELETE.ToString(),
84+
table = table,
85+
id = id
86+
}
87+
};
88+
89+
var payload = JsonSerializer.Serialize(new { batch });
90+
var content = new StringContent(payload, Encoding.UTF8, "application/json");
91+
92+
HttpResponseMessage response = await _httpClient.PostAsync($"{_backendUrl}/api/data", content);
93+
94+
if (!response.IsSuccessStatusCode)
95+
{
96+
Console.WriteLine(await response.Content.ReadAsStringAsync());
97+
throw new Exception(
98+
$"Failed to delete item. Status: {response.StatusCode}, " +
99+
$"Response: {await response.Content.ReadAsStringAsync()}"
100+
);
101+
}
102+
103+
return await response.Content.ReadAsStringAsync();
104+
}
105+
106+
public void Dispose()
107+
{
108+
_httpClient?.Dispose();
109+
}
110+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
namespace PowerSync.Common.IntegrationTests;
2+
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Net.Http;
7+
using System.Text;
8+
using System.Text.Json;
9+
using System.Threading.Tasks;
10+
using System.IO;
11+
using PowerSync.Common.Client;
12+
using PowerSync.Common.Client.Connection;
13+
using PowerSync.Common.DB.Crud;
14+
15+
16+
public class NodeConnector : IPowerSyncBackendConnector
17+
{
18+
private readonly HttpClient _httpClient;
19+
20+
public string BackendUrl { get; }
21+
public string PowerSyncUrl { get; }
22+
public string UserId { get; private set; }
23+
private string? clientId;
24+
25+
public NodeConnector(string userId)
26+
{
27+
_httpClient = new HttpClient();
28+
29+
// Load or generate User ID
30+
UserId = userId;
31+
32+
BackendUrl = "http://localhost:6060";
33+
PowerSyncUrl = "http://localhost:8080";
34+
35+
clientId = null;
36+
}
37+
38+
public async Task<PowerSyncCredentials?> FetchCredentials()
39+
{
40+
string tokenEndpoint = "api/auth/token";
41+
string url = $"{BackendUrl}/{tokenEndpoint}?user_id={UserId}";
42+
43+
HttpResponseMessage response = await _httpClient.GetAsync(url);
44+
if (!response.IsSuccessStatusCode)
45+
{
46+
throw new Exception($"Received {response.StatusCode} from {tokenEndpoint}: {await response.Content.ReadAsStringAsync()}");
47+
}
48+
49+
string responseBody = await response.Content.ReadAsStringAsync();
50+
var jsonResponse = JsonSerializer.Deserialize<Dictionary<string, string>>(responseBody);
51+
52+
if (jsonResponse == null || !jsonResponse.ContainsKey("token"))
53+
{
54+
throw new Exception("Invalid response received from authentication endpoint.");
55+
}
56+
57+
return new PowerSyncCredentials(PowerSyncUrl, jsonResponse["token"]);
58+
}
59+
60+
public async Task UploadData(IPowerSyncDatabase database)
61+
{
62+
CrudTransaction? transaction;
63+
try
64+
{
65+
transaction = await database.GetNextCrudTransaction();
66+
}
67+
catch (Exception ex)
68+
{
69+
Console.WriteLine($"UploadData Error: {ex.Message}");
70+
return;
71+
}
72+
73+
if (transaction == null)
74+
{
75+
return;
76+
}
77+
78+
clientId ??= await database.GetClientId();
79+
80+
try
81+
{
82+
var batch = new List<object>();
83+
84+
foreach (var operation in transaction.Crud)
85+
{
86+
batch.Add(new
87+
{
88+
op = operation.Op.ToString(),
89+
table = operation.Table,
90+
id = operation.Id,
91+
data = operation.OpData
92+
});
93+
}
94+
95+
var payload = JsonSerializer.Serialize(new { batch });
96+
var content = new StringContent(payload, Encoding.UTF8, "application/json");
97+
98+
HttpResponseMessage response = await _httpClient.PostAsync($"{BackendUrl}/api/data", content);
99+
100+
if (!response.IsSuccessStatusCode)
101+
{
102+
throw new Exception($"Received {response.StatusCode} from /api/data: {await response.Content.ReadAsStringAsync()}");
103+
}
104+
105+
await transaction.Complete();
106+
}
107+
catch (Exception ex)
108+
{
109+
Console.WriteLine($"UploadData Error: {ex.Message}");
110+
throw;
111+
}
112+
}
113+
}

Tests/PowerSync/PowerSync.Common.IntegrationTests/PowerSync.Common.IntegrationTests.csproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net9.0</TargetFramework>
4+
<!-- <TargetFrameworks>netstandard2.0;net6.0;net8.0;net9.0</TargetFrameworks> -->
5+
<TargetFrameworks>net8.0</TargetFrameworks>
6+
57
<ImplicitUsings>enable</ImplicitUsings>
68
<Nullable>enable</Nullable>
79
<IsPackable>false</IsPackable>

0 commit comments

Comments
 (0)