Skip to content

Commit

Permalink
finish up tests
Browse files Browse the repository at this point in the history
  • Loading branch information
TurtleP committed Jun 14, 2024
1 parent 2ae9779 commit b65b3e9
Show file tree
Hide file tree
Showing 11 changed files with 373 additions and 83 deletions.
3 changes: 3 additions & 0 deletions Bundler.Client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ function App() {
zip.file(file.filepath, file.data);
}

const log = MediaConverter.getConversionLog();
if (log && log.size > 0) zip.file("convert.log", log);

zip
.generateAsync({ type: "blob" })
.then((blob: Blob) => downloadBlob(blob));
Expand Down
7 changes: 4 additions & 3 deletions Bundler.Client/src/services/MediaConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ export default class MediaConverter {
const data = file instanceof File ? file : file.data;

if (MediaConverter.isValidTextureType(file)) {
return await this.validateImage(filename, data);
const isValid = await MediaConverter.validateImage(filename, data);
if (!isValid) throw Error(`Texture '${filename}' dimensions invalid.`); else return true;
} else if (MediaConverter.isValidFontType(file)) {
return await this.validateFont(filename, data);
}
Expand Down Expand Up @@ -227,8 +228,8 @@ export default class MediaConverter {
mediaFiles.push(file);
}
}

if (response["log"] !== undefined) {
console.log(response);
if (response["log"]) {
const content = new Blob([response["log"]], { type: "text/plain" });
MediaConverter.log = new File([content], "convert.log");
}
Expand Down
242 changes: 242 additions & 0 deletions Bundler.QA/Backend/BundlerAPITest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
using System.Net;
using System.IO.Compression;

using Newtonsoft.Json;

using Bundler.QA.Common;
using Bundler.Server.Models;

namespace Bundler.QA.Backend
{
[NonParallelizable]
internal class BundlerAPITest : BaseTest
{
private HttpClient _client;

[OneTimeSetUp]
public void Setup()
=> this._client = new() { BaseAddress = new Uri("http://localhost:5001") };

[OneTimeTearDown]
public void Teardown()
=> this._client.Dispose();

private static string ChangeExtension(string filename)
{
return Path.GetExtension(filename) switch
{
".png" or ".jpg" or ".jpeg" => Path.ChangeExtension(filename, ".t3x"),
".otf" or ".ttf" => Path.ChangeExtension(filename, ".bcfnt"),
_ => filename
};
}

private static void ValidateZipArchive(string console, string base64, string[] filenames)
{
Console.WriteLine($"Validating {console} archive...");

if (console == "ctr") // change extensions based on file extension (png, jpg, ttf)
filenames = Array.ConvertAll(filenames, f => ChangeExtension(f));

var bytes = Convert.FromBase64String(base64);
using var stream = new MemoryStream(bytes);

using var zip = new ZipArchive(stream);

Assert.That(zip.Entries, Has.Count.EqualTo(filenames.Length));

foreach (var filename in filenames)
Assert.That(zip.Entries, Has.One.Matches<ZipArchiveEntry>(e => e.Name == filename));
}

#region Textures

[TestCase("dio.jpg")]
[TestCase("lenny.png")]
[Description("Test valid texture files (jpg, png) can upload (within size limits).")]
public async Task TestTextureConversion(string filename)
{
var content = new MultipartFormDataContent();
var fileBytes = new ByteArrayContent(Assets.GetData(filename));

content.Add(fileBytes, filename, filename);
var response = await this._client.PostAsync("convert", content);

var json = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
var expected = Path.ChangeExtension(filename, "t3x");

Assert.Multiple(() => {
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
Assert.That(json, Contains.Key("log"));
Assert.That(json, Contains.Key(expected));
});
}

[TestCase("cat_big_width.png")]
[TestCase("cat_big_height.png")]
[TestCase("cat_big_both.png")]
[TestCase("cat_big_width.jpg")]
[TestCase("cat_big_height.jpg")]
[TestCase("cat_big_both.jpg")]
[Description("Test large texture files cannot upload (> 1024 pixels).")]
public async Task TestUploadBigTextureDimensions(string filename)
{
var content = new MultipartFormDataContent();
var fileBytes = new ByteArrayContent(Assets.GetData(filename));

content.Add(fileBytes, filename, filename);
var response = await this._client.PostAsync("convert", content);

Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.UnprocessableEntity));
}

[TestCase("small_both.png")]
[TestCase("small_height.png")]
[TestCase("small_width.png")]
[TestCase("small_both.jpg")]
[TestCase("small_height.jpg")]
[TestCase("small_width.jpg")]
[Description("Test small texture files cannot upload (< 3 pixels).")]
public async Task TestUploadSmallFileDimensions(string filename)
{
var content = new MultipartFormDataContent();
var fileBytes = new ByteArrayContent(Assets.GetData(filename));

content.Add(fileBytes, filename, filename);
var response = await this._client.PostAsync("convert", content);

Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.UnprocessableEntity));
}

[TestCase]
[Description("Test 'corrupt' texture files cannot upload.")]
public async Task TestUploadCorruptTexture()
{
var content = new MultipartFormDataContent();
var fileBytes = new ByteArrayContent(Assets.GetData("corrupt.png"));

content.Add(fileBytes, "corrupt.png", "corrupt.png");
var response = await this._client.PostAsync("convert", content);

Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.UnprocessableEntity));
}

[TestCase("chika.gif")]
[TestCase("rectangle.bmp")]
[TestCase("rectangle.tga")]
[Description("Test invalid file types cannot upload.")]
public async Task TestUploadInvalidTexture(string filename)
{
var content = new MultipartFormDataContent();
var fileBytes = new ByteArrayContent(Assets.GetData(filename));

content.Add(fileBytes, filename, filename);
var response = await this._client.PostAsync("convert", content);

Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.UnsupportedMediaType));
}

#endregion

#region Fonts

[TestCase("Oneday.otf")]
[TestCase("Perfect DOS VGA 437.ttf")]
public async Task TestFontConversion(string filename)
{
var content = new MultipartFormDataContent();
var fileBytes = new ByteArrayContent(Assets.GetData(filename));

content.Add(fileBytes, filename, filename);
var response = await this._client.PostAsync("convert", content);

var json = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
var expected = Path.ChangeExtension(filename, "bcfnt");

Assert.Multiple(() => {
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
Assert.That(json, Contains.Key("log"));
Assert.That(json, Contains.Key(expected));
});
}

[TestCase]
[Description("Test 'corrupt' font files cannot upload.")]
public async Task TestUploadCorruptFont()
{
var content = new MultipartFormDataContent();
var fileBytes = new ByteArrayContent(Assets.GetData("corrupt.ttf"));

content.Add(fileBytes, "corrupt.ttf", "corrupt.ttf");
var response = await this._client.PostAsync("convert", content);

Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.UnprocessableEntity));
}

[TestCase]
[Description("Test invalid font files cannot upload.")]
public async Task TestUploadInvalidFont()
{
var content = new MultipartFormDataContent();
var fileBytes = new ByteArrayContent(Assets.GetData("arial.fnt"));

content.Add(fileBytes, "arial.fnt", "arial.fnt");
var response = await this._client.PostAsync("convert", content);

Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest));
}

#endregion

#region Bundles

[TestCase("bundle-macOS.zip")]
[Description("Test uploading a bundle *directly* to /compile works")]
public async Task TestUploadBundle(string filename)
{
var content = new MultipartFormDataContent();

var fileBytes = new ByteArrayContent(Assets.GetData(filename));
content.Add(fileBytes, filename, filename);

BundlerQuery query = new()
{
Title = "Test Bundle",
Description = "Test Bundle Description",
Author = "Test Author",
Version = "1.0.0",
Targets = "ctr,hac,cafe"
};

var response = await this._client.PostAsync($"compile?{query}", content);

Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
}

/* super basic test, there's what, 120 possible combinations? */
[TestCase("Hello", "World", "MEMES", "0.1.0", "")]
[TestCase("Hello", "World", "MEMES", "", "ctr,cafe,hac")]
[TestCase("Hello", "World", "", "0.1.0", "ctr,cafe,hac")]
[TestCase("Hello", "", "MEMES", "0.1.0", "ctr,cafe,hac")]
[TestCase("", "World", "MEMES", "0.1.0", "ctr,cafe,hac")]
[TestCase("", "", "", "", "")]
[Description("Doing a POST request to /compile without a completed query should return a 400")]
public async Task TestUploadBundleNoCompleteQuery(string title, string description, string author, string version, string targets)
{
BundlerQuery query = new()
{
Title = title,
Description = description,
Author = author,
Version = version,
Targets = targets
};

var response = await this._client.PostAsync($"compile?{query}", new MultipartFormDataContent());

Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.BadRequest));
}

#endregion
}
}
4 changes: 4 additions & 0 deletions Bundler.QA/Bundler.QA.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
<PackageReference Include="Selenium.WebDriver" Version="4.21.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\bundler.Server\Bundler.Server.csproj" />
</ItemGroup>

<ItemGroup>
<Using Include="NUnit.Framework" />
</ItemGroup>
Expand Down
24 changes: 10 additions & 14 deletions Bundler.QA/Common/Assets.cs
Original file line number Diff line number Diff line change
@@ -1,36 +1,32 @@
using System.Linq;
using System.IO.Compression;

namespace Bundler.QA.Common
{
public class Assets
{
private const string ResourcesPath = "Resources";
private static Assets? _instance = null;

private readonly Dictionary<string, byte[]> AssetData = [];
private readonly Dictionary<string, Dictionary<string, byte[]>> AssetCollections = [];

private Assets()
private static readonly Dictionary<string, byte[]> Data = [];

static Assets()
{
foreach (var file in Directory.GetFiles(ResourcesPath, "*", SearchOption.AllDirectories))
{
var (name, data) = (Path.GetFullPath(file), File.ReadAllBytes(file));
this.AssetData.Add(name, data);
Data.Add(name, data);
}
}

public static Assets Instance()
=> _instance ??= new();

public string GetFilepath(string name)
public static string GetFilepath(string name)
{
var filepath = this.AssetData.Keys.FirstOrDefault(k => k.Contains(name));
var filepath = Data.Keys.FirstOrDefault(k => k.Contains(name));
return filepath is null ? throw new FileNotFoundException($"File not found: {name}") : filepath;
}

public byte[] GetData(string name)
public static byte[] GetData(string name)
{
return this.AssetData[name];
var bytes = Data.FirstOrDefault(k => k.Key.Contains(name)).Value;
return bytes is null ? throw new FileNotFoundException($"File not found: {name}") : bytes;
}
}
}
13 changes: 13 additions & 0 deletions Bundler.QA/Common/BaseTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.IO.Compression;

namespace Bundler.QA.Common
{
public class BaseTest
{
public static void CreateBundle(string name, Span<(string name, string path)> files)
{
using var bundle = ZipFile.Open(name, ZipArchiveMode.Create);
foreach (var file in files) bundle.CreateEntryFromFile(Assets.GetFilepath(file.name), file.path);
}
}
}
2 changes: 1 addition & 1 deletion Bundler.QA/Frontend/BundlerPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public void UploadFile(string name, bool isAsset = true)
{
Console.WriteLine($"Uploading {name}..");

var file = isAsset ? Assets.Instance().GetFilepath(name) : name;
var file = isAsset ? Assets.GetFilepath(name) : name;
this._webdriver.Find(FileInput)?.SendKeys(file);
}

Expand Down
Loading

0 comments on commit b65b3e9

Please sign in to comment.