Compare commits
1 Commits
0d4b560df8
...
feature/ux
| Author | SHA1 | Date | |
|---|---|---|---|
| d116b8d8f1 |
@@ -545,32 +545,6 @@ namespace GerbilManager.Tests
|
|||||||
finally { try { Directory.Delete(dir, recursive: true); } catch { } }
|
finally { try { Directory.Delete(dir, recursive: true); } catch { } }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void SeedGen3g_existing_varieties_preserve_id_name_binding()
|
|
||||||
{
|
|
||||||
// SEED-HELL bounce regression: the 61 existing entries must NOT change their
|
|
||||||
// Id->Name binding after GEN-3g. The 5 new entries (IDs 62-66) are appended.
|
|
||||||
// A hand-assigned Gerbil.ColorVarietyId pointing to "CP-Fuchs" (ID 58) must
|
|
||||||
// still map to CP-Fuchs after the migration runs (append-only, no rename-shift).
|
|
||||||
using var db = NewDb(); // EnsureCreated applies HasData including new 66-entry seed
|
|
||||||
|
|
||||||
// ID 58 (index 57 in old catalog, 0-based) = CP-Fuchs — must still be CP-Fuchs
|
|
||||||
var cpFuchsId = new Guid("00000000-0000-0000-0000-000000000058");
|
|
||||||
var cpFuchs = db.ColorVarieties.Find(cpFuchsId);
|
|
||||||
Assert.NotNull(cpFuchs);
|
|
||||||
Assert.Equal("CP-Fuchs", cpFuchs!.Name);
|
|
||||||
|
|
||||||
// New entries at IDs 62-66 exist with correct names
|
|
||||||
Assert.Equal("CP-Agouti-Hell", db.ColorVarieties.Find(new Guid("00000000-0000-0000-0000-000000000062"))!.Name);
|
|
||||||
Assert.Equal("CP-Silberagouti-Hell", db.ColorVarieties.Find(new Guid("00000000-0000-0000-0000-000000000063"))!.Name);
|
|
||||||
Assert.Equal("CP-Algierfuchs-Hell", db.ColorVarieties.Find(new Guid("00000000-0000-0000-0000-000000000064"))!.Name);
|
|
||||||
Assert.Equal("CP-Polarfuchs-Hell", db.ColorVarieties.Find(new Guid("00000000-0000-0000-0000-000000000065"))!.Name);
|
|
||||||
Assert.Equal("CP-Orangeschimmel-Hell", db.ColorVarieties.Find(new Guid("00000000-0000-0000-0000-000000000066"))!.Name);
|
|
||||||
|
|
||||||
// Total count is exactly 66
|
|
||||||
Assert.Equal(66, db.ColorVarieties.Count());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("01.02.2020", 2020, 2, 1)]
|
[InlineData("01.02.2020", 2020, 2, 1)]
|
||||||
[InlineData("5.3.21", 2021, 3, 5)]
|
[InlineData("5.3.21", 2021, 3, 5)]
|
||||||
|
|||||||
@@ -231,10 +231,6 @@ public class ApplicationContext : DbContext
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private static void SeedColorVarieties(ModelBuilder modelBuilder)
|
private static void SeedColorVarieties(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
// GEN-3g (Kevin): 5 CP-*-Hell variants appended at the end (IDs 62-66).
|
|
||||||
// Existing 61 entries are UNCHANGED (same ID->Name binding preserved).
|
|
||||||
// SortOrder for new entries is appended; Kevin's frontend catalog handles
|
|
||||||
// the interleaved display order via its own sortOrder values.
|
|
||||||
(string Name, string Genotype)[] catalog =
|
(string Name, string Genotype)[] catalog =
|
||||||
{
|
{
|
||||||
("Pink Eyed White (PEW)", "AA chch DD EE GG pp spsp rere"),
|
("Pink Eyed White (PEW)", "AA chch DD EE GG pp spsp rere"),
|
||||||
@@ -298,12 +294,6 @@ public class ApplicationContext : DbContext
|
|||||||
("CP-Fuchs-Hell", "AA cchmch dd ee GG PP spsp rere"),
|
("CP-Fuchs-Hell", "AA cchmch dd ee GG PP spsp rere"),
|
||||||
("CP-Blaufuchs", "AA cchmcchm dd ee gg PP spsp rere"),
|
("CP-Blaufuchs", "AA cchmcchm dd ee gg PP spsp rere"),
|
||||||
("CP-Orangeschimmel", "AA cchmcchm DD efef GG PP spsp rere"),
|
("CP-Orangeschimmel", "AA cchmcchm DD efef GG PP spsp rere"),
|
||||||
// GEN-3g: 5 new CP-*-Hell variants appended (IDs 62-66, no ID->Name drift)
|
|
||||||
("CP-Agouti-Hell", "AA cchmch DD EE GG PP spsp rere"),
|
|
||||||
("CP-Silberagouti-Hell", "AA cchmch DD EE gg PP spsp rere"),
|
|
||||||
("CP-Algierfuchs-Hell", "AA cchmch DD ee GG PP spsp rere"),
|
|
||||||
("CP-Polarfuchs-Hell", "AA cchmch DD ee gg PP spsp rere"),
|
|
||||||
("CP-Orangeschimmel-Hell","AA cchmch DD efef GG PP spsp rere"),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var rows = new ColorVariety[catalog.Length];
|
var rows = new ColorVariety[catalog.Length];
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,58 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
|
|
||||||
|
|
||||||
namespace GerbilManagerWebAPI.Migrations
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public partial class ReseedColorVarietiesGen3g : Migration
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.InsertData(
|
|
||||||
table: "ColorVarieties",
|
|
||||||
columns: new[] { "Id", "CanonicalGenotype", "Name", "SortOrder" },
|
|
||||||
values: new object[,]
|
|
||||||
{
|
|
||||||
{ new Guid("00000000-0000-0000-0000-000000000062"), "AA cchmch DD EE GG PP spsp rere", "CP-Agouti-Hell", 61 },
|
|
||||||
{ new Guid("00000000-0000-0000-0000-000000000063"), "AA cchmch DD EE gg PP spsp rere", "CP-Silberagouti-Hell", 62 },
|
|
||||||
{ new Guid("00000000-0000-0000-0000-000000000064"), "AA cchmch DD ee GG PP spsp rere", "CP-Algierfuchs-Hell", 63 },
|
|
||||||
{ new Guid("00000000-0000-0000-0000-000000000065"), "AA cchmch DD ee gg PP spsp rere", "CP-Polarfuchs-Hell", 64 },
|
|
||||||
{ new Guid("00000000-0000-0000-0000-000000000066"), "AA cchmch DD efef GG PP spsp rere", "CP-Orangeschimmel-Hell", 65 }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "ColorVarieties",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("00000000-0000-0000-0000-000000000062"));
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "ColorVarieties",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("00000000-0000-0000-0000-000000000063"));
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "ColorVarieties",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("00000000-0000-0000-0000-000000000064"));
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "ColorVarieties",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("00000000-0000-0000-0000-000000000065"));
|
|
||||||
|
|
||||||
migrationBuilder.DeleteData(
|
|
||||||
table: "ColorVarieties",
|
|
||||||
keyColumn: "Id",
|
|
||||||
keyValue: new Guid("00000000-0000-0000-0000-000000000066"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -605,41 +605,6 @@ namespace GerbilManagerWebAPI.Migrations
|
|||||||
CanonicalGenotype = "AA cchmcchm DD efef GG PP spsp rere",
|
CanonicalGenotype = "AA cchmcchm DD efef GG PP spsp rere",
|
||||||
Name = "CP-Orangeschimmel",
|
Name = "CP-Orangeschimmel",
|
||||||
SortOrder = 60
|
SortOrder = 60
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000062"),
|
|
||||||
CanonicalGenotype = "AA cchmch DD EE GG PP spsp rere",
|
|
||||||
Name = "CP-Agouti-Hell",
|
|
||||||
SortOrder = 61
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000063"),
|
|
||||||
CanonicalGenotype = "AA cchmch DD EE gg PP spsp rere",
|
|
||||||
Name = "CP-Silberagouti-Hell",
|
|
||||||
SortOrder = 62
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000064"),
|
|
||||||
CanonicalGenotype = "AA cchmch DD ee GG PP spsp rere",
|
|
||||||
Name = "CP-Algierfuchs-Hell",
|
|
||||||
SortOrder = 63
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000065"),
|
|
||||||
CanonicalGenotype = "AA cchmch DD ee gg PP spsp rere",
|
|
||||||
Name = "CP-Polarfuchs-Hell",
|
|
||||||
SortOrder = 64
|
|
||||||
},
|
|
||||||
new
|
|
||||||
{
|
|
||||||
Id = new Guid("00000000-0000-0000-0000-000000000066"),
|
|
||||||
CanonicalGenotype = "AA cchmch DD efef GG PP spsp rere",
|
|
||||||
Name = "CP-Orangeschimmel-Hell",
|
|
||||||
SortOrder = 65
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
54
gerbil-manager-web/e2e/genotype-table.spec.ts
Normal file
54
gerbil-manager-web/e2e/genotype-table.spec.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* UX-MOBILE-2: Genotyp-Tabellen-Overflow — die Tabelle scrollt horizontal,
|
||||||
|
* die Seite selbst bleibt NICHT breiter als der Viewport (kein horizontaler
|
||||||
|
* Page-Overflow auf 390px).
|
||||||
|
*/
|
||||||
|
import { de, expect, skipUnlessMock, test } from './fixtures'
|
||||||
|
|
||||||
|
const tl = de.pages.litters
|
||||||
|
|
||||||
|
test('Phone: Genotyp-Detail-Tabelle scrollt im eigenen Wrapper, kein Page-Overflow', async ({
|
||||||
|
page,
|
||||||
|
}, testInfo) => {
|
||||||
|
skipUnlessMock()
|
||||||
|
if (testInfo.project.name !== 'phone') return
|
||||||
|
|
||||||
|
// Wurf w-kruemel hat beide Eltern mit Genotypen → BreedingResultView rendert.
|
||||||
|
await page.goto('/wuerfe/w-kruemel')
|
||||||
|
await expect(page.getByRole('heading', { name: 'Wurf K' })).toBeVisible()
|
||||||
|
await expect(page.getByText(tl.detail.expectedColors).first()).toBeVisible()
|
||||||
|
|
||||||
|
// Genotyp-Detail-Tabelle ausklappen.
|
||||||
|
await page.getByRole('button', { name: de.pages.genetik.showGenotypes }).click()
|
||||||
|
|
||||||
|
// Scroll-Wrapper und Tabelle müssen vorhanden und sichtbar sein.
|
||||||
|
const wrapper = page.locator('.genotype-table-scroll').first()
|
||||||
|
await expect(wrapper).toBeVisible()
|
||||||
|
await expect(wrapper.locator('.genotype-table')).toBeVisible()
|
||||||
|
|
||||||
|
// Wrapper ist selbst scrollbar (Tabelle breiter als der sichtbare Bereich).
|
||||||
|
const wrapperScrollable = await wrapper.evaluate(
|
||||||
|
(el) => el.scrollWidth > el.clientWidth,
|
||||||
|
)
|
||||||
|
expect(wrapperScrollable).toBe(true)
|
||||||
|
|
||||||
|
// Die Seite selbst darf NICHT breiter als der Viewport sein.
|
||||||
|
const pageOverflow = await page.evaluate(
|
||||||
|
() => document.documentElement.scrollWidth > document.documentElement.clientWidth,
|
||||||
|
)
|
||||||
|
expect(pageOverflow).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('Desktop: Genotyp-Detail-Tabelle zeigt Wrapper auch auf breitem Viewport', async ({
|
||||||
|
page,
|
||||||
|
}, testInfo) => {
|
||||||
|
skipUnlessMock()
|
||||||
|
if (testInfo.project.name !== 'desktop') return
|
||||||
|
|
||||||
|
await page.goto('/wuerfe/w-kruemel')
|
||||||
|
await expect(page.getByText(tl.detail.expectedColors).first()).toBeVisible()
|
||||||
|
await page.getByRole('button', { name: de.pages.genetik.showGenotypes }).click()
|
||||||
|
|
||||||
|
await expect(page.locator('.genotype-table-scroll').first()).toBeVisible()
|
||||||
|
await expect(page.locator('.genotype-table').first()).toBeVisible()
|
||||||
|
})
|
||||||
@@ -65,6 +65,7 @@ export default function BreedingResultView({ result, title }: BreedingResultView
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
{showGenotypes && (
|
{showGenotypes && (
|
||||||
|
<div className="genotype-table-scroll">
|
||||||
<table className="genotype-table">
|
<table className="genotype-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -87,6 +88,7 @@ export default function BreedingResultView({ result, title }: BreedingResultView
|
|||||||
))}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -77,6 +77,10 @@ a {
|
|||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
max-width: 60rem;
|
max-width: 60rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
/* UX-MOBILE-2: prevent any wide content (e.g. genotype table) from making
|
||||||
|
the page body scroll horizontally. The .genotype-table-scroll wrapper
|
||||||
|
provides the per-table horizontal scroll. */
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tab-Leiste unten */
|
/* Tab-Leiste unten */
|
||||||
@@ -559,8 +563,14 @@ textarea {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* UX-MOBILE-2: scroll wrapper so genotype table scrolls horizontally on mobile
|
||||||
|
instead of overflowing the page. */
|
||||||
|
.genotype-table-scroll {
|
||||||
|
overflow-x: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
|
||||||
.genotype-table {
|
.genotype-table {
|
||||||
width: 100%;
|
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
margin-top: 0.75rem;
|
margin-top: 0.75rem;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
@@ -571,6 +581,7 @@ textarea {
|
|||||||
text-align: left;
|
text-align: left;
|
||||||
padding: 0.4rem 0.5rem;
|
padding: 0.4rem 0.5rem;
|
||||||
border-bottom: 1px solid var(--color-border);
|
border-bottom: 1px solid var(--color-border);
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.genotype-table code {
|
.genotype-table code {
|
||||||
|
|||||||
Reference in New Issue
Block a user