Add E2E tests
This commit is contained in:
parent
a29171f32f
commit
044bba759f
|
|
@ -1,14 +1,14 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ArcElement, Chart as ChartJS } from "chart.js";
|
import { ArcElement, Chart as ChartJS } from "chart.js";
|
||||||
import { useTranslation } from "i18next-vue";
|
|
||||||
import { computed } from "vue";
|
import { computed } from "vue";
|
||||||
import { Pie } from "vue-chartjs";
|
import { Pie } from "vue-chartjs";
|
||||||
|
import { useChosenProfileMapping } from "./composables";
|
||||||
|
|
||||||
ChartJS.register(ArcElement);
|
ChartJS.register(ArcElement);
|
||||||
|
|
||||||
const props = defineProps<{ data: Record<string, number> }>();
|
const props = defineProps<{ data: Record<string, number> }>();
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { CHOSEN_PROFILE_TO_COLOR, CHOSEN_PROFILE_TO_NAME } = useChosenProfileMapping();
|
||||||
|
|
||||||
const data = computed(() => ({
|
const data = computed(() => ({
|
||||||
labels: Object.entries(props.data).map(([key]) => key),
|
labels: Object.entries(props.data).map(([key]) => key),
|
||||||
|
|
@ -21,20 +21,6 @@ const data = computed(() => ({
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const CHOSEN_PROFILE_TO_NAME: Record<string, string> = {
|
|
||||||
all: t("a.Allbranche"),
|
|
||||||
leben: t("a.Leben"),
|
|
||||||
nichtleben: t("a.Nichtleben"),
|
|
||||||
krankenzusatzversicherung: t("a.Krankenzusatzversicherungen"),
|
|
||||||
};
|
|
||||||
|
|
||||||
const CHOSEN_PROFILE_TO_COLOR: Record<string, string> = {
|
|
||||||
all: "#558AED",
|
|
||||||
leben: "#FE955A",
|
|
||||||
nichtleben: "#54CE8B",
|
|
||||||
krankenzusatzversicherung: "#FAC852",
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
w
|
w
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -58,6 +44,7 @@ w
|
||||||
v-for="(value, key) in props.data"
|
v-for="(value, key) in props.data"
|
||||||
:key="key"
|
:key="key"
|
||||||
class="flex items-center space-x-2"
|
class="flex items-center space-x-2"
|
||||||
|
:data-cy="`dashboard.stats.trainingResponsible.chart.${CHOSEN_PROFILE_TO_NAME[key]}.${value}`"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="h-4 w-4 rounded-full"
|
class="h-4 w-4 rounded-full"
|
||||||
|
|
|
||||||
|
|
@ -55,14 +55,17 @@ const attendanceCountPerChosenProfile = computed(() => {
|
||||||
<div class="flex flex-col flex-wrap items-stretch md:flex-row">
|
<div class="flex flex-col flex-wrap items-stretch md:flex-row">
|
||||||
<BaseBox
|
<BaseBox
|
||||||
:details-link="`/dashboard/cost/${courseSessionId}`"
|
:details-link="`/dashboard/cost/${courseSessionId}`"
|
||||||
data-cy="dashboard.mentor.competenceSummary"
|
data-cy="dashboard.stats.trainingResponsible.cost"
|
||||||
class="w-1/2"
|
class="w-1/2"
|
||||||
>
|
>
|
||||||
<template #title>{{ $t("Kosten in") }} {{ new Date().getFullYear() }}</template>
|
<template #title>{{ $t("Kosten in") }} {{ new Date().getFullYear() }}</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="flex flex-row space-x-3 bg-white pb-6">
|
<div class="flex flex-row space-x-3 bg-white pb-6">
|
||||||
<div class="flex h-[74px] items-center justify-center py-1 pr-3">
|
<div class="flex h-[74px] items-center justify-center py-1 pr-3">
|
||||||
<span class="text-3xl font-bold">
|
<span
|
||||||
|
class="text-3xl font-bold"
|
||||||
|
data-cy="dashboard.stats.trainingResponsible.totalCost"
|
||||||
|
>
|
||||||
{{ formatCurrencyChfCentimes(totalCostInCurrentYear) }}
|
{{ formatCurrencyChfCentimes(totalCostInCurrentYear) }}
|
||||||
</span>
|
</span>
|
||||||
<span class="ml-4">CHF</span>
|
<span class="ml-4">CHF</span>
|
||||||
|
|
@ -72,13 +75,14 @@ const attendanceCountPerChosenProfile = computed(() => {
|
||||||
</BaseBox>
|
</BaseBox>
|
||||||
<BaseBox
|
<BaseBox
|
||||||
:details-link="`/dashboard/persons?course=${courseId}`"
|
:details-link="`/dashboard/persons?course=${courseId}`"
|
||||||
data-cy="dashboard.mentor.competenceSummary"
|
data-cy="dashboard.stats.trainingResponsible.participants"
|
||||||
>
|
>
|
||||||
<template #title>{{ $t("Teilnehmer im 2024") }}</template>
|
<template #title>{{ $t("Teilnehmer im 2024") }}</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<div class="flex flex-row space-x-3 bg-white pb-6">
|
<div class="flex flex-row space-x-3 bg-white pb-6">
|
||||||
<div
|
<div
|
||||||
class="flex h-[74px] items-center justify-center py-1 pr-3 text-3xl font-bold"
|
class="flex h-[74px] items-center justify-center py-1 pr-3 text-3xl font-bold"
|
||||||
|
data-cy="dashboard.stats.trainingResponsible.participantsInCurrentYear"
|
||||||
>
|
>
|
||||||
<span>{{ attendanceCountInCurrentYear }}</span>
|
<span>{{ attendanceCountInCurrentYear }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { useTranslation } from "i18next-vue";
|
||||||
|
|
||||||
|
export function useChosenProfileMapping() {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const CHOSEN_PROFILE_TO_NAME: Record<string, string> = {
|
||||||
|
all: t("a.Allbranche"),
|
||||||
|
leben: t("a.Leben"),
|
||||||
|
nichtleben: t("a.Nichtleben"),
|
||||||
|
krankenzusatzversicherung: t("a.Krankenzusatzversicherungen"),
|
||||||
|
};
|
||||||
|
|
||||||
|
const CHOSEN_PROFILE_TO_COLOR: Record<string, string> = {
|
||||||
|
all: "#558AED",
|
||||||
|
leben: "#FE955A",
|
||||||
|
nichtleben: "#54CE8B",
|
||||||
|
krankenzusatzversicherung: "#FAC852",
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
CHOSEN_PROFILE_TO_NAME,
|
||||||
|
CHOSEN_PROFILE_TO_COLOR,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -45,15 +45,14 @@ const participantsForYear = (year: number) => {
|
||||||
<div
|
<div
|
||||||
v-for="entry in statistics?.training_responsible_statistics?.cost_per_year"
|
v-for="entry in statistics?.training_responsible_statistics?.cost_per_year"
|
||||||
:key="entry?.year"
|
:key="entry?.year"
|
||||||
data-cy="year"
|
|
||||||
class="w-full border-b pb-2 pt-2 first:pt-0 last:border-b-0 last:pb-0"
|
class="w-full border-b pb-2 pt-2 first:pt-0 last:border-b-0 last:pb-0"
|
||||||
>
|
>
|
||||||
<div class="flex w-full flex-row justify-between">
|
<div class="flex w-full flex-row justify-between">
|
||||||
<p class="text-base">{{ entry?.year }}</p>
|
<p class="text-base">{{ entry?.year }}</p>
|
||||||
<p class="text-base">
|
<p class="text-base" :data-cy="`participants-${entry?.year}`">
|
||||||
{{ participantsForYear(entry?.year ?? 0) }} {{ $t("a.Teilnehmer") }}
|
{{ participantsForYear(entry?.year ?? 0) }} {{ $t("a.Teilnehmer") }}
|
||||||
</p>
|
</p>
|
||||||
<p class="text-base font-bold">
|
<p class="text-base font-bold" :data-cy="`cost-${entry?.year}`">
|
||||||
{{ formatCurrencyChfCentimes(entry?.total_cost) }} CHF
|
{{ formatCurrencyChfCentimes(entry?.total_cost) }} CHF
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { useChosenProfileMapping } from "@/components/dashboard/composables";
|
||||||
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
import ItDropdownSelect from "@/components/ui/ItDropdownSelect.vue";
|
||||||
import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
|
import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
|
||||||
import { useDashboardPersonsDueDates } from "@/composables";
|
import { useDashboardPersonsDueDates } from "@/composables";
|
||||||
|
|
@ -37,6 +38,7 @@ const { t } = useTranslation();
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
|
|
||||||
const { loading, dashboardPersons } = useDashboardPersonsDueDates(props.mode);
|
const { loading, dashboardPersons } = useDashboardPersonsDueDates(props.mode);
|
||||||
|
const { CHOSEN_PROFILE_TO_NAME } = useChosenProfileMapping();
|
||||||
|
|
||||||
const courses = computed(() => {
|
const courses = computed(() => {
|
||||||
return [
|
return [
|
||||||
|
|
@ -173,18 +175,17 @@ const chosenProfiles = computed(() => {
|
||||||
const values = _(dashboardPersons.value)
|
const values = _(dashboardPersons.value)
|
||||||
.map((cs) => {
|
.map((cs) => {
|
||||||
return Object.assign({}, cs, {
|
return Object.assign({}, cs, {
|
||||||
name: cs.chosen_profile,
|
name: CHOSEN_PROFILE_TO_NAME[cs.chosen_profile],
|
||||||
id: cs.chosen_profile,
|
id: cs.chosen_profile,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.filter((cs) => cs.chosen_profile !== "all")
|
|
||||||
.uniqBy("id")
|
.uniqBy("id")
|
||||||
.orderBy("name")
|
.orderBy("name")
|
||||||
.value();
|
.value();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
id: "all",
|
id: UNFILTERED,
|
||||||
name: `${t("Zulassungsprofil")}: ${t("a.Alle")}`,
|
name: `${t("Zulassungsprofil")}: ${t("a.Alle")}`,
|
||||||
},
|
},
|
||||||
...values,
|
...values,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
import { login } from "../helpers"
|
||||||
|
|
||||||
|
function selectDropboxItem(dropboxSelector, item) {
|
||||||
|
cy.get(dropboxSelector).click()
|
||||||
|
cy.get(dropboxSelector).contains(item).click()
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("ausbildungsverantwortlicher.cy.js", () => {
|
||||||
|
|
||||||
|
it("check data on dashboard", () => {
|
||||||
|
login("test-ausbildungsverantwortlicher1@example.com", "test")
|
||||||
|
cy.visit("/")
|
||||||
|
|
||||||
|
cy.get('[data-cy="panel-role-key"]').should("contain", "Ausbildungsverantwortlicher")
|
||||||
|
|
||||||
|
cy.get('[data-cy="num-dashboard-persons"]').should("contain", "2 Personen")
|
||||||
|
|
||||||
|
cy.get('[data-cy="dashboard.stats.trainingResponsible.totalCost"]').should(
|
||||||
|
"contain",
|
||||||
|
"324",
|
||||||
|
)
|
||||||
|
|
||||||
|
cy.get('[data-cy="dashboard.stats.trainingResponsible.participantsInCurrentYear"]').should(
|
||||||
|
"contain",
|
||||||
|
"1",
|
||||||
|
)
|
||||||
|
|
||||||
|
cy.get('[data-cy="dashboard.stats.trainingResponsible.chart.Allbranche.1"]').should(
|
||||||
|
'exist'
|
||||||
|
)
|
||||||
|
cy.get('[data-cy="dashboard.stats.trainingResponsible.chart.Nichtleben.1"]').should(
|
||||||
|
'exist'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("check cost detail page", () => {
|
||||||
|
login("test-ausbildungsverantwortlicher1@example.com", "test")
|
||||||
|
cy.visit("/")
|
||||||
|
|
||||||
|
cy.get(
|
||||||
|
'[data-cy="dashboard.stats.trainingResponsible.cost"] [data-cy="basebox.detailsLink"]',
|
||||||
|
).click()
|
||||||
|
|
||||||
|
cy.get('[data-cy="cost-2024"]').should("have.length", 1)
|
||||||
|
cy.get('[data-cy="cost-2023"]').should("have.length", 1)
|
||||||
|
|
||||||
|
cy.get('[data-cy="cost-2024"]').should("contain", "324 CHF")
|
||||||
|
cy.get('[data-cy="cost-2023"]').should("contain", "324 CHF")
|
||||||
|
cy.get('[data-cy="participants-2024"]').should("contain", "1")
|
||||||
|
cy.get('[data-cy="participants-2023"]').should("contain", "1")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("check participants detail page", () => {
|
||||||
|
login("test-ausbildungsverantwortlicher1@example.com", "test")
|
||||||
|
cy.visit("/")
|
||||||
|
|
||||||
|
cy.get(
|
||||||
|
'[data-cy="dashboard.stats.trainingResponsible.participants"] [data-cy="basebox.detailsLink"]',
|
||||||
|
).click()
|
||||||
|
|
||||||
|
// Test paid year filter
|
||||||
|
cy.get('[data-cy="person"]').should("have.length", 2)
|
||||||
|
selectDropboxItem('[data-cy="select-paid-year"]', "2023")
|
||||||
|
cy.get('[data-cy="person"]').should("have.length", 1)
|
||||||
|
selectDropboxItem('[data-cy="select-paid-year"]', "2024")
|
||||||
|
cy.get('[data-cy="person"]').should("have.length", 1)
|
||||||
|
selectDropboxItem('[data-cy="select-paid-year"]', "Jahr: Alle")
|
||||||
|
cy.get('[data-cy="person"]').should("have.length", 2)
|
||||||
|
|
||||||
|
// Test chosen profile filter
|
||||||
|
selectDropboxItem('[data-cy="select-chosen-profile"]', "Nichtleben")
|
||||||
|
cy.get('[data-cy="person"]').should("have.length", 1)
|
||||||
|
selectDropboxItem('[data-cy="select-chosen-profile"]', "Allbranche")
|
||||||
|
cy.get('[data-cy="person"]').should("have.length", 1)
|
||||||
|
selectDropboxItem('[data-cy="select-chosen-profile"]', "Alle")
|
||||||
|
cy.get('[data-cy="person"]').should("have.length", 2)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
@ -267,7 +267,6 @@ def create_versicherungsvermittlerin_course(
|
||||||
chosen_profile=CourseProfile.objects.get_or_create(
|
chosen_profile=CourseProfile.objects.get_or_create(
|
||||||
id=COURSE_PROFILE_NICHTLEBEN_ID,
|
id=COURSE_PROFILE_NICHTLEBEN_ID,
|
||||||
code=COURSE_PROFILE_NICHTLEBEN_CODE,
|
code=COURSE_PROFILE_NICHTLEBEN_CODE,
|
||||||
order=3,
|
|
||||||
)[0],
|
)[0],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -305,12 +304,16 @@ def create_versicherungsvermittlerin_course(
|
||||||
participant=student_3_csu,
|
participant=student_3_csu,
|
||||||
role=AgentParticipantRoleType.BERUFSBILDNER.value,
|
role=AgentParticipantRoleType.BERUFSBILDNER.value,
|
||||||
)
|
)
|
||||||
CheckoutInformationFactory(
|
checkout = CheckoutInformationFactory(
|
||||||
user=User.objects.get(id=TEST_STUDENT1_VV_USER_ID),
|
user=User.objects.get(id=TEST_STUDENT1_VV_USER_ID),
|
||||||
)
|
)
|
||||||
CheckoutInformationFactory(
|
checkout.created_at = datetime(2024, 9, 1, tzinfo=timezone.utc)
|
||||||
|
checkout.save()
|
||||||
|
checkout = CheckoutInformationFactory(
|
||||||
user=User.objects.get(id=TEST_STUDENT3_VV_USER_ID),
|
user=User.objects.get(id=TEST_STUDENT3_VV_USER_ID),
|
||||||
)
|
)
|
||||||
|
checkout.created_at = datetime(2023, 9, 1, tzinfo=timezone.utc)
|
||||||
|
checkout.save()
|
||||||
|
|
||||||
|
|
||||||
def create_versicherungsvermittlerin_pruefung_course(
|
def create_versicherungsvermittlerin_pruefung_course(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue